Merge branch 'ignite-13038'
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..1958528
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,10 @@
+.git
+*Dockerfile*
+*docker-compose*
+**/build/
+**/node_modules/
+**/target/
+!web-agent/target/*.zip
+**/backend/agent_dists/*.zip
+**/backend/config/*.json
+**/backend/test
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7bf9a55
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*.iml
+.npmrc
+build/
+node_modules/
+package-lock.json
+.idea/
diff --git a/DEVNOTES.txt b/DEVNOTES.txt
new file mode 100644
index 0000000..531c1ea
--- /dev/null
+++ b/DEVNOTES.txt
@@ -0,0 +1,145 @@
+Ignite Web Console Build Instructions
+=====================================
+1. Install MongoDB (version >=3.0) using instructions from http://docs.mongodb.org/manual/installation.
+2. Install Node.js (version >=8.0.0) using installer from https://nodejs.org/en/download/current for your OS.
+3. Change directory to 'modules/backend' and
+ run "npm install --no-optional" for download backend dependencies.
+4. Change directory to 'modules/frontend' and
+ run "npm install --no-optional" for download frontend dependencies.
+5. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
+6. Copy ignite-web-agent-<version>.zip from 'modules/web-agent/target'
+ to 'modules/backend/agent_dists' folder.
+
+Steps 1 - 4 should be executed once.
+
+Ignite Web Console Run In Development Mode
+==========================================
+1. Configure MongoDB to run as service or in terminal change dir to $MONGO_INSTALL_DIR/server/3.2/bin
+  and start MongoDB by executing "mongod".
+
+2. In new terminal change directory to 'modules/backend'.
+   If needed run "npm install --no-optional" (if dependencies changed) and run "npm start" to start backend.
+
+3. In new terminal change directory to 'modules/frontend'.
+  If needed run "npm install --no-optional" (if dependencies changed) and start webpack in development mode "npm run dev".
+
+4. In browser open: http://localhost:9000
+
+How to migrate model:
+
+1. Model will be upgraded on first start.
+2. To downgrade model execute in terminal following command: "./node_modules/.bin/migrate down <migration-name> -d <dbConnectionUri>".
+   Example: "./node_modules/.bin/migrate down add_index -d mongodb://localhost/console".
+
+
+Ignite Web Console Direct-Install Maven Build Instructions
+==========================================================
+To build direct-install archive from sources run following command in Ignite project root folder:
+"mvn clean package -pl :ignite-web-console -am -P web-console,direct-install,lgpl -DskipTests=true -DskipClientDocs -Dmaven.javadoc.skip=true"
+
+Assembled archive can be found here: `modules/target/ignite-web-console-direct-install-*.zip`.
+
+
+Ignite Web Console Docker Images Build Instructions
+===================================================
+Install Docker (version >=17.05) using instructions from https://www.docker.com/community-edition.
+
+To build docker images from sources run following command in Ignite project root folder:
+
+"mvn clean package -pl :ignite-web-console -am -P web-console,docker-image -DskipTests=true -DskipClientDocs -Dmaven.javadoc.skip=true"
+
+Prepared image can be listed with `docker images` command.
+
+
+Ignite Web Console Backend Docker Image Build Manual Instructions
+====================================================================
+Install Docker (version >=17.05) using instructions from https://www.docker.com/community-edition.
+
+1. Build Apache Ignite Web Agent archive as described in `modules/web-agent/README.txt`.
+2. Goto Web Console's root directory.
+3. Build docker image:
+
+"docker build . -t apacheignite/web-console-backend[:<version>] -f docker/compose/backend/Dockerfile"
+
+Prepared image can be listed in `docker images` command output.
+
+
+Ignite Web Console Frontend Docker Image Build Manual Instructions
+====================================================================
+Install Docker (version >=17.05) using instructions from https://www.docker.com/community-edition.
+
+1. Build Apache Ignite Web Agent archive as described in `modules/web-agent/README.txt`.
+2. Goto Web Console's root directory.
+3. Build docker image:
+
+"docker build . -t apacheignite/web-console-frontend[:<version>] -f docker/compose/frontend/Dockerfile"
+
+Prepared image can be listed in `docker images` command output.
+
+
+End-to-end tests
+================
+E2E tests are performed with TestCafe framework - https://testcafe.devexpress.com
+
+To launch tests on your local machine you will need:
+1. Install and launch MongoDB.
+2. Optionally install Chromium (https://www.chromium.org/getting-involved/download-chromium or https://chromium.woolyss.com).
+   You may use any other browser, just set 'BROWSERS' constant in 'modules/e2e/testcafe/index.js'.
+3. In new terminal change directory to 'modules/e2e/testcafe' folder and execute: "npm install".
+4. To start test environment and tests execute: "npm run test".
+
+During developing tests you may need to run some particular tests without running all suites.
+For this case you need to run environment and test separately.
+To perform it do the following:
+1. Ensure that MongoDB is up and running and all dependencies for backend and frontend are installed.
+2. Open directory "modules/e2e/testcafe" in terminal. Install dependencies for E2E testing with "npm install" command.
+3. Execute command "npm run env". This will start backend and frontend environment.
+4. Open another terminal window and run command "node index.js" in the same directory. This will run only tests without launching environment.
+
+Please refer to TestCafe documentation at https://devexpress.github.io/testcafe/documentation/test-api/test-code-structure.html#skipping-tests
+ upon how to specify which particular test should be run or skipped.
+
+You can modify the following params with environment variables:
+- DB_URL - connection string to test MongoDB. Default: mongodb://localhost/console-e2e
+- APP_URL - URL for test environment applications. Default: http://localhost:9001
+- REPORTER - Which "TestCafe" reporter to use. Set to 'teamcity' to use Teamcity reporter. Default: "spec" (native Testcafe reporter)
+
+You can run tests in docker:
+1. Install docker and docker-compose.
+2. Execute in terminal: "docker-compose up --build --abort-on-container-exit" in directory "modules/e2e".
+3. If you need to cleanup docker container then execute "docker-compose down".
+
+
+Frontend unit tests
+===================
+Unit tests are performed with Mocha framework - https://mochajs.org
+
+To launch tests on your local machine you will need:
+1. In new terminal change directory to 'modules/frontend' folder and execute: "npm install".
+2. To start test environment and tests execute: "npm run test".
+
+
+Backend unit tests
+==================
+Unit tests are performed with Mocha framework - https://mochajs.org
+
+To launch tests on your local machine you will need:
+1. In new terminal change directory to 'modules/backend' folder and execute: "npm install".
+2. To start test environment and tests execute: "npm run test".
+
+
+Web Console settings
+====================
+Web Console backend could be configured with custom parameters.
+
+See "backend/config/settings.json.sample" for list of parameters with example value.
+
+If you need custom parameters, you will need create "backend/config/settings.json" and adjust values.
+
+Web Console settings for Docker
+===============================
+Web Console backend could be configured with custom parameters.
+
+You may pass custom parameters with help of "-e" option.
+
+For example: docker run -e "server_disable_signup=true" -p 9090:80 $IMAGE_ID
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..286082c
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,36 @@
+Ignite Web Console
+======================================
+An Interactive Configuration Wizard and Management Tool for Apache Ignite
+
+The Apache Ignite Web Console includes an interactive configuration wizard which helps you create and download configuration
+ files for your Apache Ignite cluster. The tool also provides management capabilities which allow you to run SQL queries
+ on your in-memory cache as well as view execution plans, in-memory schema, and streaming charts.
+
+In order to simplify evaluation of Web Console demo mode was implemented.
+ To start demo, you need to click button "Start demo". New tab will be open with prepared demo data on each screen.
+
+ Demo for import domain model from database.
+  In this mode an in-memory H2 database will be started.
+  How to evaluate:
+    1) Go to Ignite Web Console "Domain model" screen.
+    2) Click "Import from database". You should see modal with demo description.
+    3) Click "Next" button. You should see list of available schemas.
+    4) Click "Next" button. You should see list of available tables.
+    5) Click "Next" button. You should see import options.
+    6) Select some of them and click "Save".
+
+ Demo for SQL.
+   How to evaluate:
+    In this mode internal Ignite node will be started. Cache created and populated with data.
+     1) Click "SQL" in Ignite Web Console top menu.
+     2) "Demo" notebook with preconfigured queries will be opened.
+     3) You can also execute any SQL queries for tables: "Country, Department, Employee, Parking, Car".
+
+ For example:
+  1) Enter SQL statement:
+      SELECT p.name, count(*) AS cnt FROM "ParkingCache".Parking p
+       INNER JOIN "CarCache".Car c ON (p.id) = (c.parkingId)
+       GROUP BY P.NAME
+  2) Click "Execute" button. You should get some data in table.
+  3) Click charts buttons to see auto generated charts.
+
diff --git a/assembly/README.txt b/assembly/README.txt
new file mode 100644
index 0000000..e88e345
--- /dev/null
+++ b/assembly/README.txt
@@ -0,0 +1,127 @@
+Requirements
+-------------------------------------
+1. JDK 8 suitable for your platform.
+2. Supported browsers: Chrome, Firefox, Safari, Edge.
+3. Ignite cluster should be started with `ignite-rest-http` module in classpath.
+ For this copy `ignite-rest-http` folder from `libs\optional` to `libs` folder.
+
+How to run
+-------------------------------------
+1. Unpack ignite-web-console-x.x.x.zip to some folder.
+2. Change work directory to folder where Web Console was unpacked.
+3. Start ignite-web-console-xxx executable for you platform:
+    For Linux: `sudo ./ignite-web-console-linux`
+    For macOS: `sudo ./ignite-web-console-macos`
+    For Windows: `ignite-web-console-win.exe`
+
+NOTE: For Linux and macOS `sudo` required because non-privileged users are not allowed to bind to privileged ports (port numbers below 1024).
+
+4. Open URL `localhost` in browser.
+5. Login with user `admin@admin` and password `admin`.
+6. Start web agent from folder `web agent`. For Web Agent settings see `web-agent\README.txt`.
+
+NOTE: Cluster URL should be specified in `web-agent\default.properties` in `node-uri` parameter.
+
+Technical details
+-------------------------------------
+1. Package content:
+    `libs` - this folder contains Web Console and MongoDB binaries.
+    `user_data` - this folder contains all Web Console data (registered users, created objects, ...) and
+     should be preserved in case of update to new version.
+    `web-agent` - this folder contains Web Agent.
+2. Package already contains MongoDB for macOS, Windows, RHEL, CentOs and Ubuntu on other platforms MongoDB will be downloaded on first start. MongoDB executables will be downloaded to `libs\mogodb` folder.
+3. Web console will start on default HTTP port `80` and bind to all interfaces `0.0.0.0`.
+3. To bind Web Console to specific network interface:
+    On Linux: `./ignite-web-console-linux --server:host 192.168.0.1`
+    On macOS: `sudo ./ignite-web-console-macos --server:host 192.168.0.1`
+    On Windows: `ignite-web-console-win.exe --server:host 192.168.0.1`
+4. To start Web Console on another port, for example `3000`:
+    On Linux: `sudo ./ignite-web-console-linux --server:port 3000`
+    On macOS: `./ignite-web-console-macos --server:port 3000`
+    On Windows: `ignite-web-console-win.exe --server:port 3000`
+
+All available parameters with defaults:
+    Web Console host:                              --server:host 0.0.0.0
+    Web Console port:                              --server:port 80
+
+    Enable HTTPS:                                  --server:ssl false
+    Disable self registration:                     --server:disable:signup false
+
+    MongoDB URL:                                   --mongodb:url mongodb://localhost/console
+
+    Enable account activation:                     --activation:enabled false
+    Activation timeout(milliseconds):              --activation:timeout 1800000
+    Activation send email throttle (milliseconds): --activation:sendTimeout 180000
+
+    Mail service:                                  --mail:service "gmail"
+    Signature text:                                --mail:sign "Kind regards, Apache Ignite Team"
+    Greeting text:                                 --mail:greeting "Apache Ignite Web Console"
+    Mail FROM:                                     --mail:from "Apache Ignite Web Console <someusername@somecompany.somedomain>"
+    User to send e-mail:                           --mail:auth:user "someusername@somecompany.somedomain"
+    E-mail service password:                       --mail:auth:pass ""
+
+SSL options has no default values:
+    --server:key "path to file with server.key"
+    --server:cert "path to file with server.crt"
+    --server:ca "path to file with ca.crt"
+    --server:passphrase "Password for key"
+    --server:ciphers "Comma separated ciphers list"
+    --server:secureProtocol "The TLS protocol version to use"
+    --server:clientCertEngine "Name of an OpenSSL engine which can provide the client certificate"
+    --server:pfx "Path to PFX or PKCS12 encoded private key and certificate chain"
+    --server:crl "Path to file with CRLs (Certificate Revocation Lists)"
+    --server:dhparam "Diffie Hellman parameters"
+    --server:ecdhCurve "A string describing a named curve"
+    --server:maxVersion "Optional the maximmu TLS version to allow"
+    --server:minVersion "Optional the minimum TLS version to allow"
+    --server:secureOptions "Optional OpenSSL options"
+    --server:sessionIdContext "Opaque identifier used by servers to ensure session state is not shared between applications"
+    --server:honorCipherOrder "true or false"
+    --server:requestCert "Set to true to specify whether a server should request a certificate from a connecting client"
+    --server:rejectUnauthorized "Set to true to automatically reject clients with invalid certificates"
+
+Documentation for SSL options: https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options
+
+Sample usages:
+    `ignite-web-console-win.exe --mail:auth:user "my_user@gmail.com" --mail:auth:pass "my_password"`
+    `ignite-web-console-win.exe --server:port 11443 --server:ssl true --server:requestCert true --server:key "server.key" --server:cert "server.crt" --server:ca "ca.crt" --server:passphrase "my_password"`
+
+Advanced configuration of SMTP for Web Console.
+-------------------------------------
+1. Create sub-folder "config" in folder with Web Console executable.
+2. Create in config folder file "settings.json".
+3. Specify SMTP settings in settings.json (updating to your specific names and passwords):
+
+Sample "settings.json":
+{
+    "mail": {
+        "service": "gmail",
+        "greeting": "My Company Greeting",
+        "from": "My Company Web Console <some_name@gmail.com>",
+        "sign": "Kind regards,<br>My Company Team",
+        "auth": {
+            "user": "some_name@gmail.com",
+            "pass": "my_password"
+        }
+    }
+}
+
+Web Console sends e-mails with help of NodeMailer: https://nodemailer.com.
+
+Documentation available here:
+   https://nodemailer.com/smtp
+   https://nodemailer.com/smtp/well-known
+
+In case of non GMail SMTP server it may require to change options in "settings.json" according to NodeMailer documentation.
+
+Troubleshooting
+-------------------------------------
+1. On Windows check that MongoDB is not blocked by Antivirus/Firewall/Smartscreen.
+2. Root permission is required to bind to 80 port under macOS and Linux, but you may always start Web Console
+   on another port if you don't have such permission.
+3. For extended debug output start Web Console as following:
+     On Linux execute command in terminal: `DEBUG=mongodb-* ./ignite-web-console-linux`
+     On macOS execute command in terminal: `DEBUG=mongodb-* ./ignite-web-console-macos`
+     On Windows execute two commands in terminal:
+         `SET DEBUG=mongodb-*`
+         `ignite-web-console-win.exe`
diff --git a/assembly/direct-install.xml b/assembly/direct-install.xml
new file mode 100644
index 0000000..d34cd07
--- /dev/null
+++ b/assembly/direct-install.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+    <id>release-ignite-web-agent</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>${project.basedir}/target</directory>
+            <outputDirectory>/libs/agent_dists</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${project.basedir}/target</directory>
+            <outputDirectory>/libs/mongodb/mongodb-download</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${project.basedir}/target</directory>
+            <outputDirectory>/user_data</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/assembly</directory>
+            <outputDirectory>/</outputDirectory>
+            <includes>
+                <include>**/README*</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/backend/build</directory>
+            <outputDirectory>/</outputDirectory>
+            <includes>
+                <include>ignite-web-console-win.exe</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>${basedir}/backend/build</directory>
+            <outputDirectory>/</outputDirectory>
+            <fileMode>0755</fileMode>
+            <includes>
+                <include>ignite-web-console-*</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/web-agent/target</directory>
+            <outputDirectory>/libs/agent_dists</outputDirectory>
+            <includes>
+                <include>ignite-web-agent-${project.version}.zip</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/frontend/build</directory>
+            <outputDirectory>/libs/frontend</outputDirectory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/docker/compose/backend/Dockerfile b/docker/compose/backend/Dockerfile
new file mode 100644
index 0000000..de2652c
--- /dev/null
+++ b/docker/compose/backend/Dockerfile
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+FROM node:8-slim
+
+ENV NPM_CONFIG_LOGLEVEL error
+
+WORKDIR /opt/web-console
+
+# Install node modules for frontend and backend modules.
+COPY backend/package*.json backend/
+RUN (cd backend && npm install --no-optional --production)
+
+# Copy source.
+COPY backend backend
+
+COPY web-agent/target/ignite-web-agent-*.zip backend/agent_dists
+
+EXPOSE 3000
+
+CMD ["npm", "start"]
diff --git a/docker/compose/docker-compose.yml b/docker/compose/docker-compose.yml
new file mode 100644
index 0000000..7a2cfe6
--- /dev/null
+++ b/docker/compose/docker-compose.yml
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+
+version: '3'
+
+services:
+  mongodb:
+    image: mongo:4.0
+    container_name: 'mongodb'
+    volumes:
+      # External volume for persisting data. (HOST_PATH:CONTAINER_PATH).
+      - ./data/mongo:/data/db
+
+  backend:
+    image: apacheignite/web-console-backend
+    depends_on:
+      - mongodb
+    # Restart on crash.
+    restart: always
+    environment:
+      # Port for serving frontend API
+      - server_port=3000
+      # Cookie session secret
+      - server_sessionSecret=CHANGE ME
+      # URL for mongodb connection
+      - mongodb_url=mongodb://mongodb/console
+      # Mail connection settings. Leave empty if no needed. See also settings, https://github.com/nodemailer/nodemailer
+      - mail_service=
+      - mail_sign=
+      - mail_greeting=
+      - mail_from=
+      - mail_auth_user=
+      - mail_auth_pass=
+
+  frontend:
+    image: apacheignite/web-console-frontend
+    depends_on:
+      - mongodb
+    ports:
+      # Proxy HTTP nginx port (HOST_PORT:DOCKER_PORT)
+      - 80:80
diff --git a/docker/compose/frontend/Dockerfile b/docker/compose/frontend/Dockerfile
new file mode 100644
index 0000000..07cbc46
--- /dev/null
+++ b/docker/compose/frontend/Dockerfile
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+
+FROM node:8-slim as frontend-build
+
+ENV NPM_CONFIG_LOGLEVEL error
+
+WORKDIR /opt/web-console
+
+# Install node modules for frontend.
+COPY frontend/package*.json frontend/
+RUN (cd frontend && npm install --no-optional)
+
+# Copy source.
+COPY frontend frontend
+
+RUN (cd frontend && npm run build)
+
+FROM nginx:1-alpine
+
+WORKDIR /data/www
+
+COPY --from=frontend-build /opt/web-console/frontend/build .
+
+COPY docker/compose/frontend/nginx/nginx.conf /etc/nginx/nginx.conf
+COPY docker/compose/frontend/nginx/web-console.conf /etc/nginx/web-console.conf
+
+VOLUME /etc/nginx
+VOLUME /data/www
+
+EXPOSE 80
diff --git a/docker/compose/frontend/nginx/nginx.conf b/docker/compose/frontend/nginx/nginx.conf
new file mode 100644
index 0000000..c98875f
--- /dev/null
+++ b/docker/compose/frontend/nginx/nginx.conf
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+user  nginx;
+worker_processes auto;
+
+error_log  /var/log/nginx/error.log  warn;
+pid        /var/run/nginx.pid;
+
+events {
+  use epoll;
+  worker_connections   512;
+  multi_accept         on;
+}
+
+http {
+  server_tokens        off;
+  sendfile             on;
+  aio                  on;
+  tcp_nopush           on;
+
+  keepalive_timeout    60;
+  tcp_nodelay          on;
+
+  client_max_body_size 100m;
+
+  #access log
+  log_format main '$http_host $remote_addr - $remote_user [$time_local] '
+  '"$request" $status $bytes_sent '
+  '"$http_referer" "$http_user_agent" '
+  '"$gzip_ratio"';
+
+  include /etc/nginx/mime.types;
+  default_type  application/octet-stream;
+
+  gzip              on;
+  gzip_disable      "msie6";
+  gzip_types        text/plain text/css text/xml text/javascript application/json application/x-javascript application/xml application/xml+rss application/javascript;
+  gzip_vary         on;
+  gzip_comp_level   5;
+
+  access_log  /var/log/nginx/access.log  main;
+  #conf.d
+  include web-console.conf;
+}
diff --git a/docker/compose/frontend/nginx/web-console.conf b/docker/compose/frontend/nginx/web-console.conf
new file mode 100644
index 0000000..4fbf204
--- /dev/null
+++ b/docker/compose/frontend/nginx/web-console.conf
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+
+upstream backend-api {
+  server backend:3000;
+}
+
+server {
+  listen 80;
+  server_name _;
+
+  set $ignite_console_dir /data/www;
+
+  root $ignite_console_dir;
+
+  error_page 500 502 503 504 /50x.html;
+
+  location / {
+    try_files $uri /index.html = 404;
+  }
+
+  location /api/v1 {
+    proxy_set_header Host $http_host;
+    proxy_pass http://backend-api;
+  }
+
+  location /socket.io {
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_http_version 1.1;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header Host $host;
+    proxy_pass http://backend-api;
+  }
+
+  location /agents {
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_http_version 1.1;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header Host $host;
+    proxy_pass http://backend-api;
+  }
+
+  location = /50x.html {
+    root $ignite_console_dir/error_page;
+  }
+}
diff --git a/docker/web-agent/Dockerfile b/docker/web-agent/Dockerfile
new file mode 100644
index 0000000..7e45ad3
--- /dev/null
+++ b/docker/web-agent/Dockerfile
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+
+# Start from Java 8 based on Alpine Linux image (~5Mb)
+FROM openjdk:8-jre-alpine
+
+# Provide default arguments
+ARG DEFAULT_DRIVER_FOLDER="/opt/ignite/drivers"
+ARG DEFAULT_NODE_URI="http://localhost:8080"
+ARG DEFAULT_SERVER_URI="http://localhost"
+ARG DEFAULT_TOKENS="NO_TOKENS"
+
+ENV DRIVER_FOLDER=$DEFAULT_DRIVER_FOLDER
+ENV NODE_URI=$DEFAULT_NODE_URI
+ENV SERVER_URI=$DEFAULT_SERVER_URI
+ENV TOKENS=$DEFAULT_TOKENS
+
+# Settings
+USER root
+ENV AGENT_HOME /opt/ignite/ignite-web-agent
+WORKDIR ${AGENT_HOME} 
+
+# Add missing software
+RUN apk --no-cache \
+    add bash
+
+# Copy main binary archive
+COPY ignite-web-agent* ./
+
+# Entrypoint
+CMD ./ignite-web-agent.sh -d ${DRIVER_FOLDER} -n ${NODE_URI} -s ${SERVER_URI} -t ${TOKENS}
+
diff --git a/docker/web-agent/README.txt b/docker/web-agent/README.txt
new file mode 100644
index 0000000..b217d1c
--- /dev/null
+++ b/docker/web-agent/README.txt
@@ -0,0 +1,36 @@
+Apache Ignite Web Agent Docker module
+=====================================
+Apache Ignite Web Agent Docker module provides Dockerfile and accompanying files
+for building docker image of Web Agent.
+
+
+Build image
+===========
+1) Build Apache Ignite Web Console module
+
+        mvn clean install -T 2C \
+                          -Pall-java,all-scala,licenses,web-console \
+                          -pl :ignite-web-console -am \
+                          -DskipTests
+
+2) Go to Apache Ignite Web Console Docker module directory and copy Apache
+   Ignite Web Agent's binary archive
+
+        cd docker/web-agent
+        cp -rfv ../../modules/web-agent/target/ignite-web-agent-*.zip ./
+
+3) Unpack and remove Apache Ignite Web Agent's binary archive
+
+        unzip ignite-web-agent-*.zip
+        rm -rf ignite-web-agent-*.zip
+
+4) Build docker image
+
+        docker build . -t apacheignite/web-agent[:<version>]
+
+   Prepared image will be available in local docker registry (can be seen
+   issuing `docker images` command)
+
+5) Clean up
+
+        rm -rf ignite-web-agent*
diff --git a/docker/web-console/standalone/Dockerfile b/docker/web-console/standalone/Dockerfile
new file mode 100644
index 0000000..bd03c7d
--- /dev/null
+++ b/docker/web-console/standalone/Dockerfile
@@ -0,0 +1,84 @@
+#
+# 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.
+#
+
+#~~~~~~~~~~~~~~~~~~#
+#  Frontend build  #
+#~~~~~~~~~~~~~~~~~~#
+FROM node:10-stretch as frontend-build
+
+ENV NPM_CONFIG_LOGLEVEL error
+
+WORKDIR /opt/web-console
+
+# Install node modules and build sources
+COPY frontend frontend
+RUN cd frontend && \
+    npm install --no-optional && \
+    npm run build
+
+
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
+#  Web Console Standalone assemble  #
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
+FROM node:10-stretch
+
+ENV NPM_CONFIG_LOGLEVEL error
+
+# Install global node packages
+RUN npm install -g pm2
+
+# Update software sources and install missing applications
+RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 \
+    && echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.0 main" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list
+    apt update && \
+    apt install -y --no-install-recommends \
+        nginx-light \
+        mongodb-org-server \
+        dos2unix && \
+    apt-get clean && \
+    rm -rf /var/lib/apt/lists/*
+
+WORKDIR /opt/web-console
+
+# Install node modules for backend
+COPY backend/package*.json backend/
+RUN cd backend && \
+    npm install --no-optional --production
+
+# Copy and build sources
+COPY backend backend
+RUN cd backend && \
+    npm run build
+
+# Copy Ignite Web Agent module package
+COPY ignite-web-agent-*.zip backend/agent_dists
+
+# Copy previously built frontend
+COPY --from=frontend-build /opt/web-console/frontend/build static
+
+# Copy and fix entrypoint script
+COPY docker-entrypoint.sh docker-entrypoint.sh
+RUN chmod +x docker-entrypoint.sh \
+    && dos2unix docker-entrypoint.sh
+
+# Copy nginx configuration
+COPY nginx/* /etc/nginx/
+
+EXPOSE 80
+
+ENTRYPOINT ["/opt/web-console/docker-entrypoint.sh"]
+
diff --git a/docker/web-console/standalone/README.txt b/docker/web-console/standalone/README.txt
new file mode 100644
index 0000000..c97e792
--- /dev/null
+++ b/docker/web-console/standalone/README.txt
@@ -0,0 +1,35 @@
+Apache Ignite Web Console Standalone Docker module
+==================================================
+Apache Ignite Web Console Standalone Docker module provides Dockerfile and accompanying files
+for building docker image of Web Console.
+
+
+Ignite Web Console Standalone Docker Image Build Instructions
+=============================================================
+1) Build ignite-web-console module
+
+        mvn clean install -P web-console -DskipTests -T 2C -pl :ignite-web-console -am
+
+2) Copy ignite-web-agent-<version>.zip from 'modules/web-console/web-agent/target'
+   to 'docker/web-console/standalone' directory
+
+        cp -rf modules/web-console/web-agent/target/ignite-web-agent-*.zip docker/web-console/standalone
+
+3) Go to Apache Ignite Web Console Docker module directory and copy Apache
+   Ignite Web Console's frontend and backend directory
+
+        cd docker/web-console/standalone
+        cp -rf ../../../modules/web-console/backend ./
+        cp -rf ../../../modules/web-console/frontend ./
+
+4) Build docker image
+
+        docker build . -t apacheignite/web-console-standalone:[:<version>]
+
+   Prepared image will be available in local docker registry (can be seen
+   issuing `docker images` command)
+
+5) Clean up
+
+        rm -rf backend frontend ignite-web-agent*
+
diff --git a/docker/web-console/standalone/docker-entrypoint.sh b/docker/web-console/standalone/docker-entrypoint.sh
new file mode 100644
index 0000000..6757de6
--- /dev/null
+++ b/docker/web-console/standalone/docker-entrypoint.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# 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.
+#
+
+/usr/bin/mongod --fork --config=/etc/mongod.conf
+
+service nginx start
+
+cd backend && pm2 start ./index.js --no-daemon
diff --git a/docker/web-console/standalone/nginx/nginx.conf b/docker/web-console/standalone/nginx/nginx.conf
new file mode 100644
index 0000000..dbc79d7
--- /dev/null
+++ b/docker/web-console/standalone/nginx/nginx.conf
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+
+user  www-data;
+worker_processes  1;
+
+error_log  /var/log/nginx/error.log  warn;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  128;
+}
+
+http {
+    server_tokens off;
+    sendfile            on;
+    tcp_nopush          on;
+
+    keepalive_timeout   60;
+    tcp_nodelay         on;
+
+    client_max_body_size 100m;
+
+    #access log
+    log_format main '$http_host $remote_addr - $remote_user [$time_local] '
+    '"$request" $status $bytes_sent '
+    '"$http_referer" "$http_user_agent" '
+    '"$gzip_ratio"';
+
+    include /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+    gzip on;
+    gzip_disable "msie6";
+    gzip_types text/plain text/css text/xml text/javascript application/json application/x-javascript application/xml application/xml+rss application/javascript;
+    gzip_vary on;
+    gzip_comp_level 5;
+
+    access_log  /var/log/nginx/access.log  main;
+    #conf.d
+    include web-console.conf ;
+}
diff --git a/docker/web-console/standalone/nginx/web-console.conf b/docker/web-console/standalone/nginx/web-console.conf
new file mode 100644
index 0000000..caf171e
--- /dev/null
+++ b/docker/web-console/standalone/nginx/web-console.conf
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+
+upstream backend-api {
+  server localhost:3000;
+}
+
+server {
+  listen 80;
+  server_name _;
+
+  set $ignite_console_dir /opt/web-console/static;
+
+  root $ignite_console_dir;
+
+  error_page 500 502 503 504 /50x.html;
+
+  location / {
+    try_files $uri /index.html = 404;
+  }
+
+  location /api/v1 {
+    proxy_set_header Host $http_host;
+    proxy_pass http://backend-api;
+  }
+
+  location /socket.io {
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_http_version 1.1;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header Host $host;
+    proxy_pass http://backend-api;
+  }
+
+  location /agents {
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_http_version 1.1;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header Host $host;
+    proxy_pass http://backend-api;
+  }
+
+  location = /50x.html {
+    root $ignite_console_dir/error_page;
+  }
+}
diff --git a/licenses/apache-2.0.txt b/licenses/apache-2.0.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/licenses/apache-2.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/licenses/cc-by-3.0.txt b/licenses/cc-by-3.0.txt
new file mode 100644
index 0000000..bd32fa8
--- /dev/null
+++ b/licenses/cc-by-3.0.txt
@@ -0,0 +1,319 @@
+Creative Commons Legal Code
+
+Attribution 3.0 Unported
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+    DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+CONDITIONS.
+
+1. Definitions
+
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+    other pre-existing works, such as a translation, adaptation,
+    derivative work, arrangement of music or other alterations of a
+    literary or artistic work, or phonogram or performance and includes
+    cinematographic adaptations or any other form in which the Work may be
+    recast, transformed, or adapted including in any form recognizably
+    derived from the original, except that a work that constitutes a
+    Collection will not be considered an Adaptation for the purpose of
+    this License. For the avoidance of doubt, where the Work is a musical
+    work, performance or phonogram, the synchronization of the Work in
+    timed-relation with a moving image ("synching") will be considered an
+    Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+    encyclopedias and anthologies, or performances, phonograms or
+    broadcasts, or other works or subject matter other than works listed
+    in Section 1(f) below, which, by reason of the selection and
+    arrangement of their contents, constitute intellectual creations, in
+    which the Work is included in its entirety in unmodified form along
+    with one or more other contributions, each constituting separate and
+    independent works in themselves, which together are assembled into a
+    collective whole. A work that constitutes a Collection will not be
+    considered an Adaptation (as defined above) for the purposes of this
+    License.
+ c. "Distribute" means to make available to the public the original and
+    copies of the Work or Adaptation, as appropriate, through sale or
+    other transfer of ownership.
+ d. "Licensor" means the individual, individuals, entity or entities that
+    offer(s) the Work under the terms of this License.
+ e. "Original Author" means, in the case of a literary or artistic work,
+    the individual, individuals, entity or entities who created the Work
+    or if no individual or entity can be identified, the publisher; and in
+    addition (i) in the case of a performance the actors, singers,
+    musicians, dancers, and other persons who act, sing, deliver, declaim,
+    play in, interpret or otherwise perform literary or artistic works or
+    expressions of folklore; (ii) in the case of a phonogram the producer
+    being the person or legal entity who first fixes the sounds of a
+    performance or other sounds; and, (iii) in the case of broadcasts, the
+    organization that transmits the broadcast.
+ f. "Work" means the literary and/or artistic work offered under the terms
+    of this License including without limitation any production in the
+    literary, scientific and artistic domain, whatever may be the mode or
+    form of its expression including digital form, such as a book,
+    pamphlet and other writing; a lecture, address, sermon or other work
+    of the same nature; a dramatic or dramatico-musical work; a
+    choreographic work or entertainment in dumb show; a musical
+    composition with or without words; a cinematographic work to which are
+    assimilated works expressed by a process analogous to cinematography;
+    a work of drawing, painting, architecture, sculpture, engraving or
+    lithography; a photographic work to which are assimilated works
+    expressed by a process analogous to photography; a work of applied
+    art; an illustration, map, plan, sketch or three-dimensional work
+    relative to geography, topography, architecture or science; a
+    performance; a broadcast; a phonogram; a compilation of data to the
+    extent it is protected as a copyrightable work; or a work performed by
+    a variety or circus performer to the extent it is not otherwise
+    considered a literary or artistic work.
+ g. "You" means an individual or entity exercising rights under this
+    License who has not previously violated the terms of this License with
+    respect to the Work, or who has received express permission from the
+    Licensor to exercise rights under this License despite a previous
+    violation.
+ h. "Publicly Perform" means to perform public recitations of the Work and
+    to communicate to the public those public recitations, by any means or
+    process, including by wire or wireless means or public digital
+    performances; to make available to the public Works in such a way that
+    members of the public may access these Works from a place and at a
+    place individually chosen by them; to perform the Work to the public
+    by any means or process and the communication to the public of the
+    performances of the Work, including by public digital performance; to
+    broadcast and rebroadcast the Work by any means including signs,
+    sounds or images.
+ i. "Reproduce" means to make copies of the Work by any means including
+    without limitation by sound or visual recordings and the right of
+    fixation and reproducing fixations of the Work, including storage of a
+    protected performance or phonogram in digital form or other electronic
+    medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+limit, or restrict any uses free from copyright or rights arising from
+limitations or exceptions that are provided for in connection with the
+copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License,
+Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+perpetual (for the duration of the applicable copyright) license to
+exercise the rights in the Work as stated below:
+
+ a. to Reproduce the Work, to incorporate the Work into one or more
+    Collections, and to Reproduce the Work as incorporated in the
+    Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+    including any translation in any medium, takes reasonable steps to
+    clearly label, demarcate or otherwise identify that changes were made
+    to the original Work. For example, a translation could be marked "The
+    original work was translated from English to Spanish," or a
+    modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+    in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+
+     i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+        which the right to collect royalties through any statutory or
+        compulsory licensing scheme cannot be waived, the Licensor
+        reserves the exclusive right to collect such royalties for any
+        exercise by You of the rights granted under this License;
+    ii. Waivable Compulsory License Schemes. In those jurisdictions in
+        which the right to collect royalties through any statutory or
+        compulsory licensing scheme can be waived, the Licensor waives the
+        exclusive right to collect such royalties for any exercise by You
+        of the rights granted under this License; and,
+   iii. Voluntary License Schemes. The Licensor waives the right to
+        collect royalties, whether individually or, in the event that the
+        Licensor is a member of a collecting society that administers
+        voluntary licensing schemes, via that society, from any exercise
+        by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now
+known or hereafter devised. The above rights include the right to make
+such modifications as are technically necessary to exercise the rights in
+other media and formats. Subject to Section 8(f), all rights not expressly
+granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made
+subject to and limited by the following restrictions:
+
+ a. You may Distribute or Publicly Perform the Work only under the terms
+    of this License. You must include a copy of, or the Uniform Resource
+    Identifier (URI) for, this License with every copy of the Work You
+    Distribute or Publicly Perform. You may not offer or impose any terms
+    on the Work that restrict the terms of this License or the ability of
+    the recipient of the Work to exercise the rights granted to that
+    recipient under the terms of the License. You may not sublicense the
+    Work. You must keep intact all notices that refer to this License and
+    to the disclaimer of warranties with every copy of the Work You
+    Distribute or Publicly Perform. When You Distribute or Publicly
+    Perform the Work, You may not impose any effective technological
+    measures on the Work that restrict the ability of a recipient of the
+    Work from You to exercise the rights granted to that recipient under
+    the terms of the License. This Section 4(a) applies to the Work as
+    incorporated in a Collection, but this does not require the Collection
+    apart from the Work itself to be made subject to the terms of this
+    License. If You create a Collection, upon notice from any Licensor You
+    must, to the extent practicable, remove from the Collection any credit
+    as required by Section 4(b), as requested. If You create an
+    Adaptation, upon notice from any Licensor You must, to the extent
+    practicable, remove from the Adaptation any credit as required by
+    Section 4(b), as requested.
+ b. If You Distribute, or Publicly Perform the Work or any Adaptations or
+    Collections, You must, unless a request has been made pursuant to
+    Section 4(a), keep intact all copyright notices for the Work and
+    provide, reasonable to the medium or means You are utilizing: (i) the
+    name of the Original Author (or pseudonym, if applicable) if supplied,
+    and/or if the Original Author and/or Licensor designate another party
+    or parties (e.g., a sponsor institute, publishing entity, journal) for
+    attribution ("Attribution Parties") in Licensor's copyright notice,
+    terms of service or by other reasonable means, the name of such party
+    or parties; (ii) the title of the Work if supplied; (iii) to the
+    extent reasonably practicable, the URI, if any, that Licensor
+    specifies to be associated with the Work, unless such URI does not
+    refer to the copyright notice or licensing information for the Work;
+    and (iv) , consistent with Section 3(b), in the case of an Adaptation,
+    a credit identifying the use of the Work in the Adaptation (e.g.,
+    "French translation of the Work by Original Author," or "Screenplay
+    based on original Work by Original Author"). The credit required by
+    this Section 4 (b) may be implemented in any reasonable manner;
+    provided, however, that in the case of a Adaptation or Collection, at
+    a minimum such credit will appear, if a credit for all contributing
+    authors of the Adaptation or Collection appears, then as part of these
+    credits and in a manner at least as prominent as the credits for the
+    other contributing authors. For the avoidance of doubt, You may only
+    use the credit required by this Section for the purpose of attribution
+    in the manner set out above and, by exercising Your rights under this
+    License, You may not implicitly or explicitly assert or imply any
+    connection with, sponsorship or endorsement by the Original Author,
+    Licensor and/or Attribution Parties, as appropriate, of You or Your
+    use of the Work, without the separate, express prior written
+    permission of the Original Author, Licensor and/or Attribution
+    Parties.
+ c. Except as otherwise agreed in writing by the Licensor or as may be
+    otherwise permitted by applicable law, if You Reproduce, Distribute or
+    Publicly Perform the Work either by itself or as part of any
+    Adaptations or Collections, You must not distort, mutilate, modify or
+    take other derogatory action in relation to the Work which would be
+    prejudicial to the Original Author's honor or reputation. Licensor
+    agrees that in those jurisdictions (e.g. Japan), in which any exercise
+    of the right granted in Section 3(b) of this License (the right to
+    make Adaptations) would be deemed to be a distortion, mutilation,
+    modification or other derogatory action prejudicial to the Original
+    Author's honor and reputation, the Licensor will waive or not assert,
+    as appropriate, this Section, to the fullest extent permitted by the
+    applicable national law, to enable You to reasonably exercise Your
+    right under Section 3(b) of this License (right to make Adaptations)
+    but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ a. This License and the rights granted hereunder will terminate
+    automatically upon any breach by You of the terms of this License.
+    Individuals or entities who have received Adaptations or Collections
+    from You under this License, however, will not have their licenses
+    terminated provided such individuals or entities remain in full
+    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+    survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+    perpetual (for the duration of the applicable copyright in the Work).
+    Notwithstanding the above, Licensor reserves the right to release the
+    Work under different license terms or to stop distributing the Work at
+    any time; provided, however that any such election will not serve to
+    withdraw this License (or any other license that has been, or is
+    required to be, granted under the terms of this License), and this
+    License will continue in full force and effect unless terminated as
+    stated above.
+
+8. Miscellaneous
+
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+    the Licensor offers to the recipient a license to the Work on the same
+    terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+    offers to the recipient a license to the original Work on the same
+    terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+    applicable law, it shall not affect the validity or enforceability of
+    the remainder of the terms of this License, and without further action
+    by the parties to this agreement, such provision shall be reformed to
+    the minimum extent necessary to make such provision valid and
+    enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+    breach consented to unless such waiver or consent shall be in writing
+    and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+    respect to the Work licensed here. There are no understandings,
+    agreements or representations with respect to the Work not specified
+    here. Licensor shall not be bound by any additional provisions that
+    may appear in any communication from You. This License may not be
+    modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+    License were drafted utilizing the terminology of the Berne Convention
+    for the Protection of Literary and Artistic Works (as amended on
+    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+    and the Universal Copyright Convention (as revised on July 24, 1971).
+    These rights and subject matter take effect in the relevant
+    jurisdiction in which the License terms are sought to be enforced
+    according to the corresponding provisions of the implementation of
+    those treaty provisions in the applicable national law. If the
+    standard suite of rights granted under applicable copyright law
+    includes additional rights not granted under this License, such
+    additional rights are deemed to be included in the License; this
+    License is not intended to restrict the license of any rights under
+    applicable law.
+
+
+Creative Commons Notice
+
+    Creative Commons is not a party to this License, and makes no warranty
+    whatsoever in connection with the Work. Creative Commons will not be
+    liable to You or any party on any legal theory for any damages
+    whatsoever, including without limitation any general, special,
+    incidental or consequential damages arising in connection to this
+    license. Notwithstanding the foregoing two (2) sentences, if Creative
+    Commons has expressly identified itself as the Licensor hereunder, it
+    shall have all rights and obligations of Licensor.
+
+    Except for the limited purpose of indicating to the public that the
+    Work is licensed under the CCPL, Creative Commons does not authorize
+    the use by either party of the trademark "Creative Commons" or any
+    related trademark or logo of Creative Commons without the prior
+    written consent of Creative Commons. Any permitted use will be in
+    compliance with Creative Commons' then-current trademark usage
+    guidelines, as may be published on its website or otherwise made
+    available upon request from time to time. For the avoidance of doubt,
+    this trademark restriction does not form part of this License.
+
+    Creative Commons may be contacted at https://creativecommons.org/.
\ No newline at end of file
diff --git a/modules/backend/.eslintrc b/modules/backend/.eslintrc
new file mode 100644
index 0000000..b288d07
--- /dev/null
+++ b/modules/backend/.eslintrc
@@ -0,0 +1,169 @@
+env:
+    es6: true
+    browser: false
+    mocha: true
+parserOptions:
+    sourceType: module
+    ecmaVersion: 2018
+
+rules:
+    arrow-parens: [1, "always"]
+    arrow-spacing: [1, { "before": true, "after": true }]
+    accessor-pairs: 2
+    block-scoped-var: 2
+    brace-style: [0, "1tbs"]
+    comma-dangle: [2, "never"]
+    comma-spacing: [2, {"before": false, "after": true}]
+    comma-style: [2, "last"]
+    complexity: [1, 40]
+    computed-property-spacing: [2, "never"]
+    consistent-return: 0
+    consistent-this: [0, "that"]
+    constructor-super: 2
+    curly: [2, "multi-or-nest"]
+    default-case: 2
+    dot-location: 0
+    dot-notation: [2, { "allowKeywords": true }]
+    eol-last: 2
+    eqeqeq: 2
+    func-names: 0
+    func-style: [0, "declaration"]
+    generator-star-spacing: 0
+    guard-for-in: 1
+    handle-callback-err: 0
+    id-length: [2, {"min": 1, "max": 60}]
+    indent: [2, 4, {"SwitchCase": 1, "MemberExpression": "off", "CallExpression": {"arguments": "off"}}]
+    key-spacing: [2, { "beforeColon": false, "afterColon": true }]
+    lines-around-comment: 0
+    linebreak-style: [0, "unix"]
+    max-depth: [0, 4]
+    max-len: [0, 120, 4]
+    max-nested-callbacks: [1, 4]
+    max-params: [0, 3]
+    max-statements: [0, 10]
+    new-cap: 2
+    new-parens: 2
+    no-alert: 2
+    no-array-constructor: 2
+    no-bitwise: 0
+    no-caller: 2
+    no-catch-shadow: 2
+    no-cond-assign: 2
+    no-console: 0
+    no-constant-condition: 2
+    no-continue: 0
+    no-class-assign: 2
+    no-const-assign: 2
+    no-control-regex: 2
+    no-debugger: 2
+    no-delete-var: 2
+    no-div-regex: 0
+    no-dupe-keys: 2
+    no-dupe-args: 2
+    no-duplicate-case: 2
+    no-else-return: 2
+    no-empty: 2
+    no-empty-character-class: 2
+    no-eq-null: 2
+    no-eval: 2
+    no-ex-assign: 2
+    no-extend-native: 2
+    no-extra-bind: 2
+    no-extra-boolean-cast: 2
+    no-extra-parens: 0
+    no-extra-semi: 2
+    no-fallthrough: 2
+    no-floating-decimal: 1
+    no-func-assign: 2
+    no-implied-eval: 2
+    no-inline-comments: 0
+    no-inner-declarations: [2, "functions"]
+    no-invalid-regexp: 2
+    no-irregular-whitespace: 2
+    no-iterator: 2
+    no-label-var: 2
+    no-labels: 2
+    no-lone-blocks: 2
+    no-lonely-if: 2
+    no-implicit-coercion: [2, {"boolean": false, "number": true, "string": true}]
+    no-loop-func: 2
+    no-mixed-requires: [0, false]
+    no-mixed-spaces-and-tabs: [2, true]
+    no-multi-spaces: ["error", {"exceptions": { "VariableDeclarator": true }}]
+    no-multi-str: 2
+    no-multiple-empty-lines: [0, {"max": 2}]
+    no-native-reassign: 2
+    no-negated-in-lhs: 2
+    no-nested-ternary: 0
+    no-new: 2
+    no-new-func: 2
+    no-new-object: 2
+    no-new-require: 0
+    no-new-wrappers: 2
+    no-obj-calls: 2
+    no-octal: 2
+    no-octal-escape: 2
+    no-param-reassign: 0
+    no-path-concat: 0
+    no-plusplus: 0
+    no-process-env: 0
+    no-process-exit: 0
+    no-proto: 2
+    no-redeclare: 2
+    no-regex-spaces: 1
+    no-restricted-modules: 0
+    no-script-url: 0
+    no-self-compare: 2
+    no-sequences: 2
+    no-shadow: 0
+    no-shadow-restricted-names: 2
+    no-spaced-func: 2
+    no-sparse-arrays: 1
+    no-sync: 0
+    no-ternary: 0
+    no-trailing-spaces: ["error", {"ignoreComments": true}]
+    no-throw-literal: 0
+    no-this-before-super: 2
+    no-unexpected-multiline: 2
+    // The rule produces undesired results with TS
+    // no-undef: 2
+    no-undef-init: 2
+    no-undefined: 2
+    no-unneeded-ternary: 2
+    no-unreachable: 2
+    no-unused-expressions: [2, { allowShortCircuit: true }]
+    no-unused-vars: [0, {"vars": "all", "args": "after-used"}]
+    typescript/no-unused-vars: [0]
+    no-useless-call: 2
+    no-void: 0
+    no-var: 2
+    no-warning-comments: 0
+    no-with: 2
+    newline-after-var: 0
+    object-shorthand: [2, "always"]
+    one-var: [2, "never"]
+    operator-assignment: [2, "always"]
+    operator-linebreak: 0
+    padded-blocks: 0
+    prefer-const: 1
+    prefer-spread: 2
+    quote-props: [2, "as-needed"]
+    quotes: [2, "single", {"allowTemplateLiterals": true}]
+    radix: 1
+    semi: [2, "always"]
+    semi-spacing: [2, {"before": false, "after": true}]
+    sort-vars: 0
+    keyword-spacing: 2
+    space-before-blocks: [2, "always"]
+    space-before-function-paren: [2, "never"]
+    space-in-parens: 0
+    space-infix-ops: 2
+    space-unary-ops: [2, { "words": true, "nonwords": false }]
+    spaced-comment: [1, "always", {"markers": ["/"]}]
+    use-isnan: 2
+    valid-jsdoc: 0
+    valid-typeof: 2
+    vars-on-top: 2
+    wrap-iife: 0
+    wrap-regex: 0
+    yoda: [2, "never"]
diff --git a/modules/backend/.gitignore b/modules/backend/.gitignore
new file mode 100644
index 0000000..73bd1a1
--- /dev/null
+++ b/modules/backend/.gitignore
@@ -0,0 +1,3 @@
+agent_dists/*.zip
+config/*.json
+!package-lock.json
diff --git a/modules/backend/agent_dists/README.txt b/modules/backend/agent_dists/README.txt
new file mode 100644
index 0000000..e0a67c6
--- /dev/null
+++ b/modules/backend/agent_dists/README.txt
@@ -0,0 +1,6 @@
+Ignite Web Console
+======================================
+
+This is a default directory for agent distributions.
+
+A custom directory can be set in `backend/config/settings.json`.
diff --git a/modules/backend/app/agentSocket.js b/modules/backend/app/agentSocket.js
new file mode 100644
index 0000000..0df5c5e
--- /dev/null
+++ b/modules/backend/app/agentSocket.js
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const _ = require('lodash');
+
+// Fire me up!
+
+/**
+ * Module interaction with agents.
+ */
+module.exports = {
+    implements: 'agent-socket'
+};
+
+/**
+ * @returns {AgentSocket}
+ */
+module.exports.factory = function() {
+    /**
+     * Connected agent descriptor.
+     */
+    class AgentSocket {
+        /**
+         * @param {Socket} socket Socket for interaction.
+         * @param {Object} accounts Active accounts.
+         * @param {Array.<String>} tokens Agent tokens.
+         * @param {String} demoEnabled Demo enabled.
+         */
+        constructor(socket, accounts, tokens, demoEnabled) {
+            Object.assign(this, {
+                accounts,
+                cluster: null,
+                demo: {
+                    enabled: demoEnabled,
+                    browserSockets: []
+                },
+                socket,
+                tokens
+            });
+        }
+
+        resetToken(oldToken) {
+            _.pull(this.tokens, oldToken);
+
+            this.emitEvent('agent:reset:token', oldToken)
+                .then(() => {
+                    if (_.isEmpty(this.tokens) && this.socket.connected)
+                        this.socket.close();
+                });
+        }
+
+        /**
+         * Send event to agent.
+         *
+         * @this {AgentSocket}
+         * @param {String} event Event name.
+         * @param {Array.<Object>} args - Transmitted arguments.
+         * @param {Function} [callback] on finish
+         */
+        _emit(event, args, callback) {
+            if (!this.socket.connected) {
+                if (callback)
+                    callback('org.apache.ignite.agent.AgentException: Connection is closed');
+
+                return;
+            }
+
+            this.socket.emit(event, ...args, callback);
+        }
+
+        /**
+         * Send event to agent.
+         *
+         * @param {String} event - Event name.
+         * @param {Object?} args - Transmitted arguments.
+         * @returns {Promise}
+         */
+        emitEvent(event, ...args) {
+            return new Promise((resolve, reject) =>
+                this._emit(event, args, (resErr, res) => {
+                    if (resErr)
+                        return reject(resErr);
+
+                    resolve(res);
+                })
+            );
+        }
+
+        restResultParse(res) {
+            if (res.status === 0)
+                return JSON.parse(res.data);
+
+            if (res.status === 2)
+                throw new Error('AgentSocket failed to authenticate in grid. Please check agent\'s login and password or node port.');
+
+            throw new Error(res.error);
+        }
+
+        /**
+         * @param {Socket} browserSocket
+         */
+        attachToDemoCluster(browserSocket) {
+            this.demo.browserSockets.push(...browserSocket);
+        }
+    }
+
+    return AgentSocket;
+};
diff --git a/modules/backend/app/agentsHandler.js b/modules/backend/app/agentsHandler.js
new file mode 100644
index 0000000..f6e3da9
--- /dev/null
+++ b/modules/backend/app/agentsHandler.js
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const uuid = require('uuid/v4');
+
+const fs = require('fs');
+const path = require('path');
+const JSZip = require('jszip');
+const socketio = require('socket.io');
+const _ = require('lodash');
+
+// Fire me up!
+
+/**
+ * Module interaction with agents.
+ */
+module.exports = {
+    implements: 'agents-handler',
+    inject: ['settings', 'mongo', 'agent-socket']
+};
+
+/**
+ * @param settings
+ * @param mongo
+ * @param {AgentSocket} AgentSocket
+ * @returns {AgentsHandler}
+ */
+module.exports.factory = function(settings, mongo, AgentSocket) {
+    class AgentSockets {
+        constructor() {
+            /**
+             * @type {Map.<String, Array.<String>>}
+             */
+            this.sockets = new Map();
+        }
+
+        get(account) {
+            let sockets = this.sockets.get(account._id.toString());
+
+            if (_.isEmpty(sockets))
+                this.sockets.set(account._id.toString(), sockets = []);
+
+            return sockets;
+        }
+
+        /**
+         * @param {AgentSocket} sock
+         * @param {String} account
+         * @return {Array.<AgentSocket>}
+         */
+        add(account, sock) {
+            const sockets = this.get(account);
+
+            sockets.push(sock);
+        }
+
+        /**
+         * @param {Socket} browserSocket
+         * @return {AgentSocket}
+         */
+        find(browserSocket) {
+            const {_id} = browserSocket.request.user;
+
+            const sockets = this.sockets.get(_id);
+
+            return _.find(sockets, (sock) => _.includes(sock.demo.browserSockets, browserSocket));
+        }
+    }
+
+    class Cluster {
+        constructor(top) {
+            const clusterName = top.clusterName;
+
+            this.id = _.isEmpty(top.clusterId) ? uuid() : top.clusterId;
+            this.name = _.isEmpty(clusterName) ? `Cluster ${this.id.substring(0, 8).toUpperCase()}` : clusterName;
+            this.nids = top.nids;
+            this.addresses = top.addresses;
+            this.clients = top.clients;
+            this.clusterVersion = top.clusterVersion;
+            this.active = top.active;
+            this.secured = top.secured;
+        }
+
+        isSameCluster(top) {
+            return _.intersection(this.nids, top.nids).length > 0;
+        }
+
+        update(top) {
+            this.clusterVersion = top.clusterVersion;
+            this.nids = top.nids;
+            this.addresses = top.addresses;
+            this.clients = top.clients;
+            this.clusterVersion = top.clusterVersion;
+            this.active = top.active;
+            this.secured = top.secured;
+        }
+
+        same(top) {
+            return _.difference(this.nids, top.nids).length === 0 &&
+                _.isEqual(this.addresses, top.addresses) &&
+                this.clusterVersion === top.clusterVersion &&
+                this.active === top.active;
+        }
+    }
+
+    /**
+     * Connected agents manager.
+     */
+    class AgentsHandler {
+        /**
+         * @constructor
+         */
+        constructor() {
+            /**
+             * Connected agents.
+             * @type {AgentSockets}
+             */
+            this._agentSockets = new AgentSockets();
+
+            this.clusters = [];
+            this.topLsnrs = [];
+        }
+
+        /**
+         * Collect supported agents list.
+         * @private
+         */
+        _collectSupportedAgents() {
+            const jarFilter = (file) => path.extname(file) === '.jar';
+
+            const agentArchives = fs.readdirSync(settings.agent.dists)
+                .filter((file) => path.extname(file) === '.zip');
+
+            const agentsPromises = _.map(agentArchives, (fileName) => {
+                const filePath = path.join(settings.agent.dists, fileName);
+
+                return JSZip.loadAsync(fs.readFileSync(filePath))
+                    .then((zip) => {
+                        const jarPath = _.find(_.keys(zip.files), jarFilter);
+
+                        return JSZip.loadAsync(zip.files[jarPath].async('nodebuffer'))
+                            .then((jar) => jar.files['META-INF/MANIFEST.MF'].async('string'))
+                            .then((lines) =>
+                                _.reduce(lines.split(/\s*\n+\s*/), (acc, line) => {
+                                    if (!_.isEmpty(line)) {
+                                        const arr = line.split(/\s*:\s*/);
+
+                                        acc[arr[0]] = arr[1];
+                                    }
+
+                                    return acc;
+                                }, {}))
+                            .then((manifest) => {
+                                const ver = manifest['Implementation-Version'];
+                                const buildTime = manifest['Build-Time'];
+
+                                if (ver && buildTime)
+                                    return { fileName, filePath, ver, buildTime };
+                            });
+                    });
+            });
+
+            return Promise.all(agentsPromises)
+                .then((descs) => {
+                    const agentDescs = _.keyBy(_.remove(descs, null), 'ver');
+
+                    const latestVer = _.head(Object.keys(agentDescs).sort((a, b) => {
+                        const aParts = a.split('.');
+                        const bParts = b.split('.');
+
+                        for (let i = 0; i < aParts.length; ++i) {
+                            if (aParts[i] !== bParts[i])
+                                return aParts[i] < bParts[i] ? 1 : -1;
+                        }
+
+                        if (aParts.length === bParts.length)
+                            return 0;
+
+                        return aParts.length < bParts.length ? 1 : -1;
+                    }));
+
+                    // Latest version of agent distribution.
+                    if (latestVer)
+                        agentDescs.current = agentDescs[latestVer];
+
+                    return agentDescs;
+                });
+        }
+
+        getOrCreateCluster(top) {
+            let cluster = _.find(this.clusters, (c) => c.isSameCluster(top));
+
+            if (_.isNil(cluster)) {
+                cluster = new Cluster(top);
+
+                this.clusters.push(cluster);
+            }
+
+            return cluster;
+        }
+
+        /**
+         * Add topology listener.
+         *
+         * @param lsnr
+         */
+        addTopologyListener(lsnr) {
+            this.topLsnrs.push(lsnr);
+        }
+
+        /**
+         * Link agent with browsers by account.
+         *
+         * @param {Socket} sock
+         * @param {Array.<mongo.Account>} accounts
+         * @param {Array.<String>} tokens
+         * @param {boolean} demoEnabled
+         *
+         * @private
+         */
+        onConnect(sock, accounts, tokens, demoEnabled) {
+            const agentSocket = new AgentSocket(sock, accounts, tokens, demoEnabled);
+
+            _.forEach(accounts, (account) => {
+                this._agentSockets.add(account, agentSocket);
+
+                this._browsersHnd.agentStats(account);
+            });
+
+            sock.on('disconnect', () => {
+                _.forEach(accounts, (account) => {
+                    _.pull(this._agentSockets.get(account), agentSocket);
+
+                    this._browsersHnd.agentStats(account);
+                });
+            });
+
+            sock.on('cluster:topology', (top) => {
+                if (_.isNil(top)) {
+                    console.log('Invalid format of message: "cluster:topology"');
+
+                    return;
+                }
+
+                const cluster = this.getOrCreateCluster(top);
+
+                _.forEach(this.topLsnrs, (lsnr) => lsnr(agentSocket, cluster, top));
+
+                if (agentSocket.cluster !== cluster) {
+                    agentSocket.cluster = cluster;
+
+                    _.forEach(accounts, (account) => {
+                        this._browsersHnd.agentStats(account);
+                    });
+                }
+                else {
+                    const changed = !cluster.same(top);
+
+                    if (changed) {
+                        cluster.update(top);
+
+                        _.forEach(accounts, (account) => {
+                            this._browsersHnd.clusterChanged(account, cluster);
+                        });
+                    }
+                }
+            });
+
+            sock.on('cluster:disconnected', () => {
+                const newTop = _.assign({}, agentSocket.cluster, {nids: []});
+
+                _.forEach(this.topLsnrs, (lsnr) => lsnr(agentSocket, agentSocket.cluster, newTop));
+
+                agentSocket.cluster = null;
+
+                _.forEach(accounts, (account) => {
+                    this._browsersHnd.agentStats(account);
+                });
+            });
+
+            return agentSocket;
+        }
+
+        getAccounts(tokens) {
+            return mongo.Account.find({token: {$in: tokens}}, '_id token').lean().exec()
+                .then((accounts) => ({accounts, activeTokens: _.uniq(_.map(accounts, 'token'))}));
+        }
+
+        /**
+         * @param {http.Server|https.Server} srv Server instance that we want to attach agent handler.
+         * @param {BrowsersHandler} browsersHnd
+         */
+        attach(srv, browsersHnd) {
+            this._browsersHnd = browsersHnd;
+
+            this._collectSupportedAgents()
+                .then((supportedAgents) => {
+                    this.currentAgent = _.get(supportedAgents, 'current');
+
+                    if (this.io)
+                        throw 'Agent server already started!';
+
+                    this.io = socketio(srv, {path: '/agents'});
+
+                    this.io.on('connection', (sock) => {
+                        const sockId = sock.id;
+
+                        console.log('Connected agent with socketId: ', sockId);
+
+                        sock.on('disconnect', (reason) => {
+                            console.log(`Agent disconnected with [socketId=${sockId}, reason=${reason}]`);
+                        });
+
+                        sock.on('agent:auth', ({ver, bt, tokens, disableDemo} = {}, cb) => {
+                            console.log(`Received authentication request [socketId=${sockId}, tokens=${tokens}, ver=${ver}].`);
+
+                            if (_.isEmpty(tokens))
+                                return cb('Tokens not set. Please reload agent archive or check settings');
+
+                            if (ver && bt && !_.isEmpty(supportedAgents)) {
+                                const btDistr = _.get(supportedAgents, [ver, 'buildTime']);
+
+                                if (_.isEmpty(btDistr) || btDistr !== bt)
+                                    return cb('You are using an older version of the agent. Please reload agent');
+                            }
+
+                            return this.getAccounts(tokens)
+                                .then(({accounts, activeTokens}) => {
+                                    if (_.isEmpty(activeTokens))
+                                        return cb(`Failed to authenticate with token(s): ${tokens.join(',')}. Please reload agent archive or check settings`);
+
+                                    cb(null, activeTokens);
+
+                                    return this.onConnect(sock, accounts, activeTokens, !disableDemo);
+                                })
+                                // TODO IGNITE-1379 send error to web master.
+                                .catch(() => cb(`Invalid token(s): ${tokens.join(',')}. Please reload agent archive or check settings`));
+                        });
+                    });
+                })
+                .catch(() => {
+                    console.log('Failed to collect supported agents');
+                });
+        }
+
+        agent(account, demo, clusterId) {
+            if (!this.io)
+                return Promise.reject(new Error('Agent server not started yet!'));
+
+            const socks = this._agentSockets.get(account);
+
+            if (_.isEmpty(socks))
+                return Promise.reject(new Error('Failed to find connected agent for this account'));
+
+            if (demo) {
+                const sock = _.find(socks, (sock) => sock.demo.enabled);
+
+                if (sock)
+                    return Promise.resolve(sock);
+
+                return Promise.reject(new Error('Demo mode disabled by administrator'));
+            }
+
+            if (_.isNil(clusterId))
+                return Promise.resolve(_.head(socks));
+
+            const sock = _.find(socks, (agentSock) => _.get(agentSock, 'cluster.id') === clusterId);
+
+            if (_.isEmpty(sock))
+                return Promise.reject(new Error('Failed to find agent connected to cluster'));
+
+            return Promise.resolve(sock);
+        }
+
+        agents(account) {
+            if (!this.io)
+                return Promise.reject(new Error('Agent server not started yet!'));
+
+            const socks = this._agentSockets.get(account);
+
+            if (_.isEmpty(socks))
+                return Promise.reject(new Error('Failed to find connected agent for this token'));
+
+            return Promise.resolve(socks);
+        }
+
+        /**
+         * Try stop agent for token if not used by others.
+         *
+         * @param {mongo.Account} account
+         */
+        onTokenReset(account) {
+            if (_.isNil(this.io))
+                return;
+
+            const agentSockets = this._agentSockets.get(account);
+
+            _.forEach(agentSockets, (sock) => sock.resetToken(account.token));
+        }
+    }
+
+    return new AgentsHandler();
+};
diff --git a/modules/backend/app/apiServer.js b/modules/backend/app/apiServer.js
new file mode 100644
index 0000000..90c39ba
--- /dev/null
+++ b/modules/backend/app/apiServer.js
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+// Fire me up!
+
+const Express = require('express');
+
+module.exports = {
+    implements: 'api-server',
+    inject: ['settings', 'configure', 'routes'],
+    factory(settings, configure, routes) {
+        /**
+         * Connected agents manager.
+         */
+        class ApiServer {
+            /**
+             * @param {Server} srv
+             */
+            attach(srv) {
+                const app = new Express();
+
+                configure.express(app);
+
+                routes.register(app);
+
+                if (settings.packaged) {
+                    const staticDir = path.join(process.cwd(), 'libs/frontend');
+
+                    try {
+                        fs.accessSync(staticDir, fs.F_OK);
+
+                        app.use('/', Express.static(staticDir));
+
+                        app.get('*', function(req, res) {
+                            res.sendFile(path.join(staticDir, 'index.html'));
+                        });
+                    }
+                    catch (e) {
+                        console.log(`Failed to find folder with frontend files: ${staticDir}`);
+                    }
+                }
+
+                // Catch 404 and forward to error handler.
+                app.use((req, res) => {
+                    if (req.xhr)
+                        return res.status(404).send({ error: 'Not Found: ' + req.originalUrl });
+
+                    return res.sendStatus(404);
+                });
+
+                // Production error handler: no stacktraces leaked to user.
+                app.use((err, req, res) => {
+                    res.status(err.status || 500);
+
+                    res.render('error', {
+                        message: err.message,
+                        error: {}
+                    });
+                });
+
+                srv.addListener('request', app);
+
+                return app;
+            }
+        }
+
+        return new ApiServer();
+    }
+};
diff --git a/modules/backend/app/browsersHandler.js b/modules/backend/app/browsersHandler.js
new file mode 100644
index 0000000..4d5b02d
--- /dev/null
+++ b/modules/backend/app/browsersHandler.js
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const _ = require('lodash');
+const socketio = require('socket.io');
+
+// Fire me up!
+
+/**
+ * Module interaction with browsers.
+ */
+module.exports = {
+    implements: 'browsers-handler',
+    inject: ['configure', 'errors', 'mongo'],
+    factory: (configure, errors, mongo) => {
+        class BrowserSockets {
+            constructor() {
+                this.sockets = new Map();
+            }
+
+            /**
+             * @param {Socket} sock
+             */
+            add(sock) {
+                const key = sock.request.user._id.toString();
+
+                if (this.sockets.has(key))
+                    this.sockets.get(key).push(sock);
+                else
+                    this.sockets.set(key, [sock]);
+
+                return this.sockets.get(sock.request.user);
+            }
+
+            /**
+             * @param {Socket} sock
+             */
+            remove(sock) {
+                const key = sock.request.user._id.toString();
+
+                const sockets = this.sockets.get(key);
+
+                _.pull(sockets, sock);
+
+                return sockets;
+            }
+
+            get(account) {
+                const key = account._id.toString();
+
+                let sockets = this.sockets.get(key);
+
+                if (_.isEmpty(sockets))
+                    this.sockets.set(key, sockets = []);
+
+                return sockets;
+            }
+        }
+
+        class BrowsersHandler {
+            /**
+             * @constructor
+             */
+            constructor() {
+                /**
+                 * Connected browsers.
+                 * @type {BrowserSockets}
+                 */
+                this._browserSockets = new BrowserSockets();
+
+                /**
+                 * Registered Visor task.
+                 * @type {Map}
+                 */
+                this._visorTasks = new Map();
+            }
+
+            /**
+             * @param {Error} err
+             * @return {{code: number, message: *}}
+             */
+            errorTransformer(err) {
+                return {
+                    code: err.code || 1,
+                    message: err.message || err
+                };
+            }
+
+            /**
+             * @param {String} account
+             * @param {Array.<Socket>} [socks]
+             */
+            agentStats(account, socks = this._browserSockets.get(account)) {
+                return this._agentHnd.agents(account)
+                    .then((agentSocks) => {
+                        const stat = _.reduce(agentSocks, (acc, agentSock) => {
+                            acc.count += 1;
+                            acc.hasDemo = acc.hasDemo || _.get(agentSock, 'demo.enabled');
+
+                            if (agentSock.cluster)
+                                acc.clusters.push(agentSock.cluster);
+
+                            return acc;
+                        }, {count: 0, hasDemo: false, clusters: []});
+
+                        stat.clusters = _.uniqWith(stat.clusters, _.isEqual);
+
+                        return stat;
+                    })
+                    .catch(() => ({count: 0, hasDemo: false, clusters: []}))
+                    .then((stat) => _.forEach(socks, (sock) => sock.emit('agents:stat', stat)));
+            }
+
+            clusterChanged(account, cluster) {
+                const socks = this._browserSockets.get(account);
+
+                _.forEach(socks, (sock) => {
+                    if (sock)
+                        sock.emit('cluster:changed', cluster);
+                    else
+                        console.log(`Fount closed socket [account=${account}, cluster=${cluster}]`);
+                });
+            }
+
+            pushInitialData(sock) {
+                // Send initial data.
+            }
+
+            emitNotification(sock) {
+                sock.emit('user:notifications', this.notification);
+            }
+
+            /**
+             * @param {String} notification Notification message.
+             */
+            updateNotification(notification) {
+                this.notification = notification;
+
+                for (const socks of this._browserSockets.sockets.values()) {
+                    for (const sock of socks)
+                        this.emitNotification(sock);
+                }
+            }
+
+            executeOnAgent(account, demo, event, ...args) {
+                const cb = _.last(args);
+
+                return this._agentHnd.agent(account, demo)
+                    .then((agentSock) => agentSock.emitEvent(event, ..._.dropRight(args)))
+                    .then((res) => cb(null, res))
+                    .catch((err) => cb(this.errorTransformer(err)));
+            }
+
+            agentListeners(sock) {
+                const demo = sock.request._query.IgniteDemoMode === 'true';
+                const account = () => sock.request.user;
+
+                // Return available drivers to browser.
+                sock.on('schemaImport:drivers', (...args) => {
+                    this.executeOnAgent(account(), demo, 'schemaImport:drivers', ...args);
+                });
+
+                // Return schemas from database to browser.
+                sock.on('schemaImport:schemas', (...args) => {
+                    this.executeOnAgent(account(), demo, 'schemaImport:schemas', ...args);
+                });
+
+                // Return tables from database to browser.
+                sock.on('schemaImport:metadata', (...args) => {
+                    this.executeOnAgent(account(), demo, 'schemaImport:metadata', ...args);
+                });
+            }
+
+            /**
+             * @param {Promise.<AgentSocket>} agent
+             * @param {Boolean} demo
+             * @param {{sessionId: String}|{'login': String, 'password': String}} credentials
+             * @param {Object.<String, String>} params
+             * @return {Promise.<T>}
+             */
+            executeOnNode(agent, token, demo, credentials, params) {
+                return agent
+                    .then((agentSock) => agentSock.emitEvent('node:rest',
+                        {uri: 'ignite', token, demo, params: _.merge({}, credentials, params)}));
+            }
+
+            registerVisorTask(taskId, taskCls, ...argCls) {
+                this._visorTasks.set(taskId, {
+                    taskCls,
+                    argCls
+                });
+            }
+
+            nodeListeners(sock) {
+                // Return command result from grid to browser.
+                sock.on('node:rest', (arg, cb) => {
+                    const {clusterId, params, credentials} = arg || {};
+
+                    if (!_.isFunction(cb))
+                        cb = console.log;
+
+                    const demo = _.get(sock, 'request._query.IgniteDemoMode') === 'true';
+
+                    if ((_.isNil(clusterId) && !demo) || _.isNil(params)) {
+                        console.log('Received invalid message: "node:rest" on socket:', JSON.stringify(sock.handshake));
+
+                        return cb('Invalid format of message: "node:rest"');
+                    }
+
+                    const agent = this._agentHnd.agent(sock.request.user, demo, clusterId);
+
+                    const token = sock.request.user.token;
+
+                    this.executeOnNode(agent, token, demo, credentials, params)
+                        .then((data) => cb(null, data))
+                        .catch((err) => cb(this.errorTransformer(err)));
+                });
+
+                const internalVisor = (postfix) => `org.apache.ignite.internal.visor.${postfix}`;
+
+                this.registerVisorTask('querySql', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArg'));
+                this.registerVisorTask('querySqlV2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV2'));
+                this.registerVisorTask('querySqlV3', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV3'));
+                this.registerVisorTask('querySqlX2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryTaskArg'));
+
+                this.registerVisorTask('queryScanX2', internalVisor('query.VisorScanQueryTask'), internalVisor('query.VisorScanQueryTaskArg'));
+
+                this.registerVisorTask('queryFetch', internalVisor('query.VisorQueryNextPageTask'), 'org.apache.ignite.lang.IgniteBiTuple', 'java.lang.String', 'java.lang.Integer');
+                this.registerVisorTask('queryFetchX2', internalVisor('query.VisorQueryNextPageTask'), internalVisor('query.VisorQueryNextPageTaskArg'));
+
+                this.registerVisorTask('queryFetchFirstPage', internalVisor('query.VisorQueryFetchFirstPageTask'), internalVisor('query.VisorQueryNextPageTaskArg'));
+                this.registerVisorTask('queryPing', internalVisor('query.VisorQueryPingTask'), internalVisor('query.VisorQueryNextPageTaskArg'));
+
+                this.registerVisorTask('queryClose', internalVisor('query.VisorQueryCleanupTask'), 'java.util.Map', 'java.util.UUID', 'java.util.Set');
+                this.registerVisorTask('queryCloseX2', internalVisor('query.VisorQueryCleanupTask'), internalVisor('query.VisorQueryCleanupTaskArg'));
+
+                this.registerVisorTask('toggleClusterState', internalVisor('misc.VisorChangeGridActiveStateTask'), internalVisor('misc.VisorChangeGridActiveStateTaskArg'));
+
+                this.registerVisorTask('cacheNamesCollectorTask', internalVisor('cache.VisorCacheNamesCollectorTask'), 'java.lang.Void');
+
+                this.registerVisorTask('cacheNodesTask', internalVisor('cache.VisorCacheNodesTask'), 'java.lang.String');
+                this.registerVisorTask('cacheNodesTaskX2', internalVisor('cache.VisorCacheNodesTask'), internalVisor('cache.VisorCacheNodesTaskArg'));
+
+                // Return command result from grid to browser.
+                sock.on('node:visor', (arg, cb) => {
+                    const {clusterId, params, credentials} = arg || {};
+
+                    if (!_.isFunction(cb))
+                        cb = console.log;
+
+                    const demo = _.get(sock, 'request._query.IgniteDemoMode') === 'true';
+
+                    if ((_.isNil(clusterId) && !demo) || _.isNil(params)) {
+                        console.log('Received invalid message: "node:visor" on socket:', JSON.stringify(sock.handshake));
+
+                        return cb('Invalid format of message: "node:visor"');
+                    }
+
+                    const {taskId, nids, args = []} = params;
+
+                    const desc = this._visorTasks.get(taskId);
+
+                    if (_.isNil(desc))
+                        return cb(this.errorTransformer(new errors.IllegalArgumentException(`Failed to find Visor task for id: ${taskId}`)));
+
+                    const exeParams = {
+                        cmd: 'exe',
+                        name: 'org.apache.ignite.internal.visor.compute.VisorGatewayTask',
+                        p1: nids,
+                        p2: desc.taskCls
+                    };
+
+                    _.forEach(_.concat(desc.argCls, args), (param, idx) => { exeParams[`p${idx + 3}`] = param; });
+
+                    const agent = this._agentHnd.agent(sock.request.user, demo, clusterId);
+
+                    const token = sock.request.user.token;
+
+                    this.executeOnNode(agent, token, demo, credentials, exeParams)
+                        .then((data) => {
+                            if (data.finished && !data.zipped)
+                                return cb(null, data.result);
+
+                            return cb(null, data);
+                        })
+                        .catch((err) => cb(this.errorTransformer(err)));
+                });
+            }
+
+            /**
+             *
+             * @param server
+             * @param {AgentsHandler} agentHnd
+             */
+            attach(server, agentHnd) {
+                this._agentHnd = agentHnd;
+
+                if (this.io)
+                    throw 'Browser server already started!';
+
+                mongo.Notifications.findOne().sort('-date').exec()
+                    .then((notification) => {
+                        this.notification = notification;
+                    })
+                    .then(() => {
+                        const io = socketio(server);
+
+                        configure.socketio(io);
+
+                        // Handle browser connect event.
+                        io.sockets.on('connection', (sock) => {
+                            this._browserSockets.add(sock);
+
+                            // Handle browser disconnect event.
+                            sock.on('disconnect', () => {
+                                this._browserSockets.remove(sock);
+                            });
+
+                            this.agentListeners(sock);
+                            this.nodeListeners(sock);
+
+                            this.pushInitialData(sock);
+                            this.agentStats(sock.request.user, [sock]);
+                            this.emitNotification(sock);
+                        });
+                    });
+            }
+        }
+
+        return new BrowsersHandler();
+    }
+};
diff --git a/modules/backend/app/configure.js b/modules/backend/app/configure.js
new file mode 100644
index 0000000..b907a1e
--- /dev/null
+++ b/modules/backend/app/configure.js
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const _ = require('lodash');
+const logger = require('morgan');
+const cookieParser = require('cookie-parser');
+const bodyParser = require('body-parser');
+const session = require('express-session');
+const MongoDBStore = require('connect-mongodb-session');
+const passport = require('passport');
+const passportSocketIo = require('passport.socketio');
+const mongoSanitize = require('express-mongo-sanitize');
+
+// Fire me up!
+
+/**
+ * Module for configuration express and websocket server.
+ */
+module.exports = {
+    implements: 'configure',
+    inject: ['settings', 'mongo', 'middlewares:*']
+};
+
+module.exports.factory = function(settings, mongo, apis) {
+    const _sessionStore = new (MongoDBStore(session))({uri: settings.mongoUrl});
+
+    return {
+        express: (app) => {
+            app.use(logger('dev', {
+                skip: (req, res) => res.statusCode < 400
+            }));
+
+            _.forEach(apis, (api) => app.use(api));
+
+            app.use(bodyParser.json({limit: '50mb'}));
+            app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
+
+
+            app.use(mongoSanitize({replaceWith: '_'}));
+
+            app.use(session({
+                secret: settings.sessionSecret,
+                resave: false,
+                saveUninitialized: true,
+                unset: 'destroy',
+                cookie: {
+                    expires: new Date(Date.now() + settings.cookieTTL),
+                    maxAge: settings.cookieTTL
+                },
+                store: _sessionStore
+            }));
+
+            app.use(passport.initialize());
+            app.use(passport.session());
+
+            passport.serializeUser((user, done) => done(null, user._id));
+
+            passport.deserializeUser((id, done) => {
+                if (mongo.ObjectId.isValid(id))
+                    return mongo.Account.findById(id, done);
+
+                // Invalidates the existing login session.
+                done(null, false);
+            });
+
+            passport.use(mongo.Account.createStrategy());
+        },
+        socketio: (io) => {
+            const _onAuthorizeSuccess = (data, accept) => accept();
+
+            const _onAuthorizeFail = (data, message, error, accept) => {
+                if (error)
+                    accept(new Error(message));
+
+                return accept(new Error(message));
+            };
+
+            io.use(passportSocketIo.authorize({
+                cookieParser,
+                key: 'connect.sid', // the name of the cookie where express/connect stores its session_id
+                secret: settings.sessionSecret, // the session_secret to parse the cookie
+                store: _sessionStore, // we NEED to use a sessionstore. no memorystore please
+                success: _onAuthorizeSuccess, // *optional* callback on success - read more below
+                fail: _onAuthorizeFail // *optional* callback on fail/error - read more below
+            }));
+        }
+    };
+};
diff --git a/modules/backend/app/mongo.js b/modules/backend/app/mongo.js
new file mode 100644
index 0000000..b9ee9de
--- /dev/null
+++ b/modules/backend/app/mongo.js
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const fs = require('fs');
+const _ = require('lodash');
+const mongoose = require('mongoose');
+
+// Fire me up!
+
+/**
+ * Module mongo schema.
+ */
+module.exports = {
+    implements: 'mongo',
+    inject: ['settings', 'schemas']
+};
+
+const defineSchema = (schemas) => {
+    const result = { connection: mongoose.connection };
+
+    result.ObjectId = mongoose.Types.ObjectId;
+
+    result.errCodes = {
+        DUPLICATE_KEY_ERROR: 11000,
+        DUPLICATE_KEY_UPDATE_ERROR: 11001
+    };
+
+    // Define models.
+    _.forEach(schemas, (schema, name) => {
+        result[name] = mongoose.model(name, schema);
+    });
+
+    result.handleError = function(res, err) {
+        // TODO IGNITE-843 Send error to admin
+        res.status(err.code || 500).send(err.message);
+    };
+
+    return result;
+};
+
+const upgradeAccounts = (mongo, activation) => {
+    if (activation) {
+        return mongo.Account.find({
+            $or: [{activated: false}, {activated: {$exists: false}}],
+            activationToken: {$exists: false}
+        }, '_id').lean().exec()
+            .then((accounts) => {
+                const conditions = _.map(accounts, (account) => ({session: {$regex: `"${account._id}"`}}));
+
+                return mongoose.connection.db.collection('sessions').deleteMany({$or: conditions});
+            });
+    }
+
+    return mongo.Account.updateMany({activated: false}, {$unset: {activationSentAt: '', activationToken: ''}}).exec();
+};
+
+module.exports.factory = function(settings, schemas) {
+    // Use native promises
+    mongoose.Promise = global.Promise;
+
+    console.log(settings.mongoUrl, 'Trying to connect to local MongoDB...');
+
+    // Connect to mongoDB database.
+    return mongoose.connect(settings.mongoUrl, {useNewUrlParser: true, useCreateIndex: true})
+        .then(() => defineSchema(schemas))
+        .catch(() => {
+            console.log(`Failed to connect to MongoDB with connection string: "${settings.mongoUrl}", will try to download and start embedded MongoDB`);
+
+            const dbDir = `${process.cwd()}/user_data`;
+
+            if (!fs.existsSync(dbDir))
+                fs.mkdirSync(dbDir);
+
+            const {MongodHelper} = require('mongodb-prebuilt');
+            const {MongoDBDownload} = require('mongodb-download');
+
+            const helper = new MongodHelper(['--port', '27017', '--dbpath', dbDir]);
+
+            helper.mongoBin.mongoDBPrebuilt.mongoDBDownload = new MongoDBDownload({
+                downloadDir: `${process.cwd()}/libs/mongodb`,
+                version: '4.0.9'
+            });
+
+            let mongodRun;
+
+            if (settings.packaged) {
+                mongodRun = new Promise((resolve, reject) => {
+                    helper.resolveLink = resolve;
+                    helper.rejectLink = reject;
+
+                    helper.mongoBin.runCommand()
+                        .then(() => {
+                            helper.mongoBin.childProcess.removeAllListeners('close');
+
+                            helper.mongoBin.childProcess.stderr.on('data', (data) => helper.stderrHandler(data));
+                            helper.mongoBin.childProcess.stdout.on('data', (data) => helper.stdoutHandler(data));
+                            helper.mongoBin.childProcess.on('close', (code) => helper.closeHandler(code));
+                        });
+                });
+            }
+            else
+                mongodRun = helper.run();
+
+            return mongodRun
+                .catch((err) => {
+                    console.log('Failed to start embedded MongoDB', err);
+
+                    return Promise.reject(err);
+                })
+                .then(() => {
+                    console.log('Embedded MongoDB successfully started');
+
+                    return mongoose.connect(settings.mongoUrl, {useNewUrlParser: true, useCreateIndex: true})
+                        .catch((err) => {
+                            console.log('Failed to connect to embedded MongoDB', err);
+
+                            return Promise.reject(err);
+                        });
+                })
+                .then(() => defineSchema(schemas))
+                .then((mongo) => {
+                    if (settings.packaged) {
+                        return mongo.Account.count()
+                            .then((count) => {
+                                if (count === 0) {
+                                    return Promise.all([
+                                        mongo.Account.create({
+                                            _id: '59fc0c25e145c32be0f83b33',
+                                            salt: '7b4ccb9e375508a8f87c8f347083ce98cb8785d857dd18208f9a480e992a26bb',
+                                            hash: '909d5ed6e0b0a656ef542e2e8e851e9eb00cfb77984e0a6b4597c335d1436a577b3b289601eb8d1f3646e488cd5ea2bbb3e97fcc131cd6a9571407a45b1817bf1af1dd0ccdd070f07733da19e636ff9787369c5f38f86075f78c60809fe4a52288a68ca38aae0ad2bd0cc77b4cae310abf260e9523d361fd9be60e823a7d8e73954ddb18091e668acd3f57baf9fa7db4267e198d829761997a4741734335589ab62793ceb089e8fffe6e5b0e86f332b33a3011ba44e6efd29736f31cbd2b2023e5173baf517f337eb7a4321ea2b67ec827cffa271d26d3f2def93b5efa3ae7e6e327e55feb121ee96b8ff5016527cc7d854a9b49b44c993387c1093705cb26b1802a2e4c1d34508fb93d051d7e5e2e6cc65b6048a999f94c369973b46b204295f0b2f23f8e30723f9e984ddb2c53dcbf0a77a6d0795d44c3ad97a4ae49d6767db9630e2ef76c2069da87088f1400b1292df9bd787122b2cfef1f26a884a298a0bab3d6e6b689381cf6389d2f019e6cd19e82c84048bacfdd1bee946f9d40dda040be426e583abf92529a1c4f032d5058a9799a77e6642312b8d231d79300d5d0d3f74d62797f9d192e8581698e9539812a539ef1b9fbf718f44dd549896ea9449f6ea744586222e5fc29dfcd5eb79e7646ad3d37868f5073833c554853dee6b067bf2bbfab44c011f2de98a8570292f8109b6bde11e3be51075a656c32b521b7',
+                                            email: 'admin@admin',
+                                            firstName: 'admin',
+                                            lastName: 'admin',
+                                            company: 'admin',
+                                            country: 'United States',
+                                            admin: true,
+                                            token: 'ruQvlWff09zqoVYyh6WJ',
+                                            attempts: 0,
+                                            resetPasswordToken: 'O2GWgOkKkhqpDcxjYnSP',
+                                            activated: true
+                                        }),
+                                        mongo.Space.create({
+                                            _id: '59fc0c26e145c32be0f83b34',
+                                            name: 'Personal space',
+                                            owner: '59fc0c25e145c32be0f83b33',
+                                            usedBy: [],
+                                            demo: false
+                                        })
+                                    ]);
+                                }
+                            })
+                            .then(() => mongo)
+                            .catch(() => mongo);
+                    }
+
+                    return mongo;
+                });
+        })
+        .then((mongo) => {
+            return upgradeAccounts(mongo, settings.activation.enabled)
+                .then(() => mongo)
+                .catch(() => mongo);
+        });
+};
diff --git a/modules/backend/app/nconf.js b/modules/backend/app/nconf.js
new file mode 100644
index 0000000..3f5d7d1
--- /dev/null
+++ b/modules/backend/app/nconf.js
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const fs = require('fs');
+const nconf = require('nconf');
+
+// Fire me up!
+
+/**
+ * Module with server-side configuration.
+ */
+module.exports = {
+    implements: 'nconf',
+    factory() {
+        nconf.env({separator: '_'}).argv();
+
+        const dfltFile = 'config/settings.json';
+        const customFile = nconf.get('settings') || dfltFile;
+
+        try {
+            fs.accessSync(customFile, fs.F_OK);
+
+            nconf.file({file: customFile});
+        }
+        catch (ignored) {
+            try {
+                fs.accessSync(dfltFile, fs.F_OK);
+
+                nconf.file({file: dfltFile});
+            }
+            catch (ignored2) {
+                // No-op.
+            }
+        }
+
+        return nconf;
+    }
+};
diff --git a/modules/backend/app/routes.js b/modules/backend/app/routes.js
new file mode 100644
index 0000000..ce7b5d8
--- /dev/null
+++ b/modules/backend/app/routes.js
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'routes',
+    inject: ['routes/public', 'routes/admin', 'routes/profiles', 'routes/demo', 'routes/clusters', 'routes/domains',
+        'routes/caches', 'routes/igfss', 'routes/notebooks', 'routes/downloads', 'routes/configurations', 'routes/activities']
+};
+
+module.exports.factory = function(publicRoute, adminRoute, profilesRoute, demoRoute,
+    clustersRoute, domainsRoute, cachesRoute, igfssRoute, notebooksRoute, downloadsRoute, configurationsRoute, activitiesRoute) {
+    return {
+        register: (app) => {
+            const _mustAuthenticated = (req, res, next) => {
+                if (req.isAuthenticated())
+                    return next();
+
+                res.status(401).send('Access denied. You are not authorized to access this page.');
+            };
+
+            const _adminOnly = (req, res, next) => {
+                if (req.isAuthenticated() && req.user.admin)
+                    return next();
+
+                res.status(401).send('Access denied. You are not authorized to access this page.');
+            };
+
+            // Registering the standard routes.
+            // NOTE: Order is important!
+            app.use('/api/v1/', publicRoute);
+            app.use('/api/v1/admin', _mustAuthenticated, _adminOnly, adminRoute);
+            app.use('/api/v1/profile', _mustAuthenticated, profilesRoute);
+            app.use('/api/v1/demo', _mustAuthenticated, demoRoute);
+
+            app.all('/api/v1/configuration/*', _mustAuthenticated);
+
+            app.use('/api/v1/configuration/clusters', clustersRoute);
+            app.use('/api/v1/configuration/domains', domainsRoute);
+            app.use('/api/v1/configuration/caches', cachesRoute);
+            app.use('/api/v1/configuration/igfs', igfssRoute);
+            app.use('/api/v1/configuration', configurationsRoute);
+
+            app.use('/api/v1/notebooks', _mustAuthenticated, notebooksRoute);
+            app.use('/api/v1/downloads', _mustAuthenticated, downloadsRoute);
+            app.use('/api/v1/activities', _mustAuthenticated, activitiesRoute);
+        }
+    };
+};
diff --git a/modules/backend/app/schemas.js b/modules/backend/app/schemas.js
new file mode 100644
index 0000000..21c8120
--- /dev/null
+++ b/modules/backend/app/schemas.js
@@ -0,0 +1,1323 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const mongoose = require('mongoose');
+const passportMongo = require('passport-local-mongoose');
+
+// Fire me up!
+
+/**
+ * Module mongo schema.
+ */
+module.exports = {
+    implements: 'schemas',
+    inject: []
+};
+
+module.exports.factory = function() {
+    const Schema = mongoose.Schema;
+    const ObjectId = mongoose.Schema.Types.ObjectId;
+
+    // Define Account schema.
+    const Account = new Schema({
+        firstName: String,
+        lastName: String,
+        email: {type: String, unique: true},
+        phone: String,
+        company: String,
+        country: String,
+        registered: Date,
+        lastLogin: Date,
+        lastActivity: Date,
+        admin: Boolean,
+        token: String,
+        resetPasswordToken: String,
+        activated: {type: Boolean, default: false},
+        activationSentAt: Date,
+        activationToken: String
+    });
+
+    // Install passport plugin.
+    Account.plugin(passportMongo, {
+        usernameField: 'email', limitAttempts: true, lastLoginField: 'lastLogin',
+        usernameLowerCase: true,
+        errorMessages: {
+            UserExistsError: 'A user with the given email is already registered'
+        }
+    });
+
+    const transform = (doc, ret) => {
+        return {
+            _id: ret._id,
+            email: ret.email,
+            phone: ret.phone,
+            firstName: ret.firstName,
+            lastName: ret.lastName,
+            company: ret.company,
+            country: ret.country,
+            admin: ret.admin,
+            token: ret.token,
+            registered: ret.registered,
+            lastLogin: ret.lastLogin,
+            lastActivity: ret.lastActivity
+        };
+    };
+
+    // Configure transformation to JSON.
+    Account.set('toJSON', {transform});
+
+    // Configure transformation to JSON.
+    Account.set('toObject', {transform});
+
+    // Define Space schema.
+    const Space = new Schema({
+        name: String,
+        owner: {type: ObjectId, ref: 'Account'},
+        demo: {type: Boolean, default: false},
+        usedBy: [{
+            permission: {type: String, enum: ['VIEW', 'FULL']},
+            account: {type: ObjectId, ref: 'Account'}
+        }]
+    });
+
+    // Define Domain model schema.
+    const DomainModel = new Schema({
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
+        clusters: [{type: ObjectId, ref: 'Cluster'}],
+        caches: [{type: ObjectId, ref: 'Cache'}],
+        queryMetadata: {type: String, enum: ['Annotations', 'Configuration']},
+        kind: {type: String, enum: ['query', 'store', 'both']},
+        tableName: String,
+        keyFieldName: String,
+        valueFieldName: String,
+        databaseSchema: String,
+        databaseTable: String,
+        keyType: String,
+        valueType: {type: String},
+        keyFields: [{
+            databaseFieldName: String,
+            databaseFieldType: String,
+            javaFieldName: String,
+            javaFieldType: String
+        }],
+        valueFields: [{
+            databaseFieldName: String,
+            databaseFieldType: String,
+            javaFieldName: String,
+            javaFieldType: String
+        }],
+        queryKeyFields: [String],
+        fields: [{
+            name: String,
+            className: String,
+            notNull: Boolean,
+            defaultValue: String,
+            precision: Number,
+            scale: Number
+        }],
+        aliases: [{field: String, alias: String}],
+        indexes: [{
+            name: String,
+            indexType: {type: String, enum: ['SORTED', 'FULLTEXT', 'GEOSPATIAL']},
+            fields: [{name: String, direction: Boolean}],
+            inlineSizeType: Number,
+            inlineSize: Number
+        }],
+        generatePojo: Boolean
+    });
+
+    DomainModel.index({valueType: 1, space: 1, clusters: 1}, {unique: true});
+
+    // Define Cache schema.
+    const Cache = new Schema({
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
+        name: {type: String},
+        groupName: {type: String},
+        clusters: [{type: ObjectId, ref: 'Cluster'}],
+        domains: [{type: ObjectId, ref: 'DomainModel'}],
+        cacheMode: {type: String, enum: ['PARTITIONED', 'REPLICATED', 'LOCAL']},
+        atomicityMode: {type: String, enum: ['ATOMIC', 'TRANSACTIONAL', 'TRANSACTIONAL_SNAPSHOT']},
+        partitionLossPolicy: {
+            type: String,
+            enum: ['READ_ONLY_SAFE', 'READ_ONLY_ALL', 'READ_WRITE_SAFE', 'READ_WRITE_ALL', 'IGNORE']
+        },
+
+        affinity: {
+            kind: {type: String, enum: ['Default', 'Rendezvous', 'Fair', 'Custom']},
+            Rendezvous: {
+                affinityBackupFilter: String,
+                partitions: Number,
+                excludeNeighbors: Boolean
+            },
+            Fair: {
+                affinityBackupFilter: String,
+                partitions: Number,
+                excludeNeighbors: Boolean
+            },
+            Custom: {
+                className: String
+            }
+        },
+
+        affinityMapper: String,
+
+        nodeFilter: {
+            kind: {type: String, enum: ['Default', 'Exclude', 'IGFS', 'OnNodes', 'Custom']},
+            Exclude: {
+                nodeId: String
+            },
+            IGFS: {
+                igfs: {type: ObjectId, ref: 'Igfs'}
+            },
+            Custom: {
+                className: String
+            }
+        },
+
+        backups: Number,
+        memoryMode: {type: String, enum: ['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']},
+        offHeapMode: Number,
+        offHeapMaxMemory: Number,
+        startSize: Number,
+        swapEnabled: Boolean,
+        cacheWriterFactory: String,
+        cacheLoaderFactory: String,
+        expiryPolicyFactory: String,
+        interceptor: String,
+        storeByValue: Boolean,
+        eagerTtl: {type: Boolean, default: true},
+        encryptionEnabled: Boolean,
+        eventsDisabled: Boolean,
+
+        keyConfiguration: [{
+            typeName: String,
+            affinityKeyFieldName: String
+        }],
+
+        cacheStoreSessionListenerFactories: [String],
+
+        onheapCacheEnabled: Boolean,
+
+        evictionPolicy: {
+            kind: {type: String, enum: ['LRU', 'FIFO', 'SORTED']},
+            LRU: {
+                batchSize: Number,
+                maxMemorySize: Number,
+                maxSize: Number
+            },
+            FIFO: {
+                batchSize: Number,
+                maxMemorySize: Number,
+                maxSize: Number
+            },
+            SORTED: {
+                batchSize: Number,
+                maxMemorySize: Number,
+                maxSize: Number
+            }
+        },
+
+        rebalanceMode: {type: String, enum: ['SYNC', 'ASYNC', 'NONE']},
+        rebalanceBatchSize: Number,
+        rebalanceBatchesPrefetchCount: Number,
+        rebalanceOrder: Number,
+        rebalanceDelay: Number,
+        rebalanceTimeout: Number,
+        rebalanceThrottle: Number,
+
+        cacheStoreFactory: {
+            kind: {
+                type: String,
+                enum: ['CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
+            },
+            CacheJdbcPojoStoreFactory: {
+                dataSourceBean: String,
+                dialect: {
+                    type: String,
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                },
+                implementationVersion: String,
+                batchSize: Number,
+                maximumPoolSize: Number,
+                maximumWriteAttempts: Number,
+                parallelLoadCacheMinimumThreshold: Number,
+                hasher: String,
+                transformer: String,
+                sqlEscapeAll: Boolean
+            },
+            CacheJdbcBlobStoreFactory: {
+                connectVia: {type: String, enum: ['URL', 'DataSource']},
+                connectionUrl: String,
+                user: String,
+                dataSourceBean: String,
+                dialect: {
+                    type: String,
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                },
+                initSchema: Boolean,
+                createTableQuery: String,
+                loadQuery: String,
+                insertQuery: String,
+                updateQuery: String,
+                deleteQuery: String
+            },
+            CacheHibernateBlobStoreFactory: {
+                hibernateProperties: [{name: String, value: String}]
+            }
+        },
+        storeConcurrentLoadAllThreshold: Number,
+        maxQueryIteratorsCount: Number,
+        storeKeepBinary: Boolean,
+        loadPreviousValue: Boolean,
+        readThrough: Boolean,
+        writeThrough: Boolean,
+
+        writeBehindEnabled: Boolean,
+        writeBehindBatchSize: Number,
+        writeBehindFlushSize: Number,
+        writeBehindFlushFrequency: Number,
+        writeBehindFlushThreadCount: Number,
+        writeBehindCoalescing: {type: Boolean, default: true},
+
+        isInvalidate: Boolean,
+        defaultLockTimeout: Number,
+        atomicWriteOrderMode: {type: String, enum: ['CLOCK', 'PRIMARY']},
+        writeSynchronizationMode: {type: String, enum: ['FULL_SYNC', 'FULL_ASYNC', 'PRIMARY_SYNC']},
+
+        sqlEscapeAll: Boolean,
+        sqlSchema: String,
+        sqlOnheapRowCacheSize: Number,
+        longQueryWarningTimeout: Number,
+        sqlFunctionClasses: [String],
+        snapshotableIndex: Boolean,
+        queryDetailMetricsSize: Number,
+        queryParallelism: Number,
+        statisticsEnabled: Boolean,
+        managementEnabled: Boolean,
+        readFromBackup: Boolean,
+        copyOnRead: Boolean,
+        maxConcurrentAsyncOperations: Number,
+        nearConfiguration: {
+            enabled: Boolean,
+            nearStartSize: Number,
+            nearEvictionPolicy: {
+                kind: {type: String, enum: ['LRU', 'FIFO', 'SORTED']},
+                LRU: {
+                    batchSize: Number,
+                    maxMemorySize: Number,
+                    maxSize: Number
+                },
+                FIFO: {
+                    batchSize: Number,
+                    maxMemorySize: Number,
+                    maxSize: Number
+                },
+                SORTED: {
+                    batchSize: Number,
+                    maxMemorySize: Number,
+                    maxSize: Number
+                }
+            }
+        },
+        clientNearConfiguration: {
+            enabled: Boolean,
+            nearStartSize: Number,
+            nearEvictionPolicy: {
+                kind: {type: String, enum: ['LRU', 'FIFO', 'SORTED']},
+                LRU: {
+                    batchSize: Number,
+                    maxMemorySize: Number,
+                    maxSize: Number
+                },
+                FIFO: {
+                    batchSize: Number,
+                    maxMemorySize: Number,
+                    maxSize: Number
+                },
+                SORTED: {
+                    batchSize: Number,
+                    maxMemorySize: Number,
+                    maxSize: Number
+                }
+            }
+        },
+        evictionFilter: String,
+        memoryPolicyName: String,
+        dataRegionName: String,
+        sqlIndexMaxInlineSize: Number,
+        topologyValidator: String,
+        diskPageCompression: {type: String, enum: ['SKIP_GARBAGE', 'ZSTD', 'LZ4', 'SNAPPY']},
+        diskPageCompressionLevel: Number
+    });
+
+    Cache.index({name: 1, space: 1, clusters: 1}, {unique: true});
+
+    const Igfs = new Schema({
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
+        name: {type: String},
+        clusters: [{type: ObjectId, ref: 'Cluster'}],
+        affinnityGroupSize: Number,
+        blockSize: Number,
+        streamBufferSize: Number,
+        dataCacheName: String,
+        metaCacheName: String,
+        defaultMode: {type: String, enum: ['PRIMARY', 'PROXY', 'DUAL_SYNC', 'DUAL_ASYNC']},
+        dualModeMaxPendingPutsSize: Number,
+        dualModePutExecutorService: String,
+        dualModePutExecutorServiceShutdown: Boolean,
+        fragmentizerConcurrentFiles: Number,
+        fragmentizerEnabled: Boolean,
+        fragmentizerThrottlingBlockLength: Number,
+        fragmentizerThrottlingDelay: Number,
+        ipcEndpointConfiguration: {
+            type: {type: String, enum: ['SHMEM', 'TCP']},
+            host: String,
+            port: Number,
+            memorySize: Number,
+            tokenDirectoryPath: String,
+            threadCount: Number
+        },
+        ipcEndpointEnabled: Boolean,
+        maxSpaceSize: Number,
+        maximumTaskRangeLength: Number,
+        managementPort: Number,
+        pathModes: [{path: String, mode: {type: String, enum: ['PRIMARY', 'PROXY', 'DUAL_SYNC', 'DUAL_ASYNC']}}],
+        perNodeBatchSize: Number,
+        perNodeParallelBatchCount: Number,
+        prefetchBlocks: Number,
+        sequentialReadsBeforePrefetch: Number,
+        trashPurgeTimeout: Number,
+        secondaryFileSystemEnabled: Boolean,
+        secondaryFileSystem: {
+            userName: String,
+            kind: {type: String, enum: ['Caching', 'Kerberos', 'Custom'], default: 'Caching'},
+            uri: String,
+            cfgPath: String,
+            cfgPaths: [String],
+            userNameMapper: {
+                kind: {type: String, enum: ['Chained', 'Basic', 'Kerberos', 'Custom']},
+                Chained: {
+                    mappers: [{
+                        kind: {type: String, enum: ['Basic', 'Kerberos', 'Custom']},
+                        Basic: {
+                            defaultUserName: String,
+                            useDefaultUserName: Boolean,
+                            mappings: [{
+                                name: String,
+                                value: String
+                            }]
+                        },
+                        Kerberos: {
+                            instance: String,
+                            realm: String
+                        },
+                        Custom: {
+                            className: String,
+                        }
+                    }]
+                },
+                Basic: {
+                    defaultUserName: String,
+                    useDefaultUserName: Boolean,
+                    mappings: [{
+                        name: String,
+                        value: String
+                    }]
+                },
+                Kerberos: {
+                    instance: String,
+                    realm: String
+                },
+                Custom: {
+                    className: String,
+                }
+            },
+            Kerberos: {
+                keyTab: String,
+                keyTabPrincipal: String,
+                reloginInterval: Number
+            },
+            Custom: {
+                className: String
+            }
+        },
+        colocateMetadata: Boolean,
+        relaxedConsistency: Boolean,
+        updateFileLengthOnFlush: Boolean
+    });
+
+    Igfs.index({name: 1, space: 1, clusters: 1}, {unique: true});
+
+
+    // Define Cluster schema.
+    const Cluster = new Schema({
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
+        name: {type: String},
+        activeOnStart: {type: Boolean, default: true},
+        localHost: String,
+        discovery: {
+            localAddress: String,
+            localPort: Number,
+            localPortRange: Number,
+            addressResolver: String,
+            socketTimeout: Number,
+            ackTimeout: Number,
+            maxAckTimeout: Number,
+            networkTimeout: Number,
+            joinTimeout: Number,
+            threadPriority: Number,
+            heartbeatFrequency: Number,
+            maxMissedHeartbeats: Number,
+            maxMissedClientHeartbeats: Number,
+            topHistorySize: Number,
+            listener: String,
+            dataExchange: String,
+            metricsProvider: String,
+            reconnectCount: Number,
+            statisticsPrintFrequency: Number,
+            ipFinderCleanFrequency: Number,
+            authenticator: String,
+            forceServerMode: Boolean,
+            clientReconnectDisabled: Boolean,
+            connectionRecoveryTimeout: Number,
+            reconnectDelay: Number,
+            soLinger: Number,
+            kind: {
+                type: String,
+                enum: ['Vm', 'Multicast', 'S3', 'Cloud', 'GoogleStorage', 'Jdbc', 'SharedFs', 'ZooKeeper', 'Kubernetes']
+            },
+            Vm: {
+                addresses: [String]
+            },
+            Multicast: {
+                multicastGroup: String,
+                multicastPort: Number,
+                responseWaitTime: Number,
+                addressRequestAttempts: Number,
+                localAddress: String,
+                addresses: [String]
+            },
+            S3: {
+                bucketName: String,
+                bucketEndpoint: String,
+                SSEAlgorithm: String,
+                clientConfiguration: {
+                    protocol: {type: String, enum: ['HTTP', 'HTTPS']},
+                    maxConnections: Number,
+                    userAgentPrefix: String,
+                    userAgentSuffix: String,
+                    localAddress: String,
+                    proxyHost: String,
+                    proxyPort: Number,
+                    proxyUsername: String,
+                    proxyDomain: String,
+                    proxyWorkstation: String,
+                    retryPolicy: {
+                        kind: {
+                            type: String,
+                            enum: ['Default', 'DefaultMaxRetries', 'DynamoDB', 'DynamoDBMaxRetries', 'Custom', 'CustomClass']
+                        },
+                        DefaultMaxRetries: {
+                            maxErrorRetry: Number
+                        },
+                        DynamoDBMaxRetries: {
+                            maxErrorRetry: Number
+                        },
+                        Custom: {
+                            retryCondition: String,
+                            backoffStrategy: String,
+                            maxErrorRetry: Number,
+                            honorMaxErrorRetryInClientConfig: Boolean
+                        },
+                        CustomClass: {
+                            className: String
+                        }
+                    },
+                    maxErrorRetry: Number,
+                    socketTimeout: Number,
+                    connectionTimeout: Number,
+                    requestTimeout: Number,
+                    useReaper: Boolean,
+                    useGzip: Boolean,
+                    signerOverride: String,
+                    preemptiveBasicProxyAuth: Boolean,
+                    connectionTTL: Number,
+                    connectionMaxIdleMillis: Number,
+                    useTcpKeepAlive: Boolean,
+                    dnsResolver: String,
+                    responseMetadataCacheSize: Number,
+                    secureRandom: String,
+                    cacheResponseMetadata: {type: Boolean, default: true},
+                    clientExecutionTimeout: Number,
+                    nonProxyHosts: String,
+                    socketSendBufferSizeHint: Number,
+                    socketReceiveBufferSizeHint: Number,
+                    useExpectContinue: {type: Boolean, default: true},
+                    useThrottleRetries: {type: Boolean, default: true}
+                }
+            },
+            Cloud: {
+                credential: String,
+                credentialPath: String,
+                identity: String,
+                provider: String,
+                regions: [String],
+                zones: [String]
+            },
+            GoogleStorage: {
+                projectName: String,
+                bucketName: String,
+                serviceAccountP12FilePath: String,
+                serviceAccountId: String,
+                addrReqAttempts: String
+            },
+            Jdbc: {
+                initSchema: Boolean,
+                dataSourceBean: String,
+                dialect: {
+                    type: String,
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                }
+            },
+            SharedFs: {
+                path: String
+            },
+            ZooKeeper: {
+                curator: String,
+                zkConnectionString: String,
+                retryPolicy: {
+                    kind: {
+                        type: String, enum: ['ExponentialBackoff', 'BoundedExponentialBackoff', 'UntilElapsed',
+                            'NTimes', 'OneTime', 'Forever', 'Custom']
+                    },
+                    ExponentialBackoff: {
+                        baseSleepTimeMs: Number,
+                        maxRetries: Number,
+                        maxSleepMs: Number
+                    },
+                    BoundedExponentialBackoff: {
+                        baseSleepTimeMs: Number,
+                        maxSleepTimeMs: Number,
+                        maxRetries: Number
+                    },
+                    UntilElapsed: {
+                        maxElapsedTimeMs: Number,
+                        sleepMsBetweenRetries: Number
+                    },
+                    NTimes: {
+                        n: Number,
+                        sleepMsBetweenRetries: Number
+                    },
+                    OneTime: {
+                        sleepMsBetweenRetry: Number
+                    },
+                    Forever: {
+                        retryIntervalMs: Number
+                    },
+                    Custom: {
+                        className: String
+                    }
+                },
+                basePath: String,
+                serviceName: String,
+                allowDuplicateRegistrations: Boolean
+            },
+            Kubernetes: {
+                serviceName: String,
+                namespace: String,
+                masterUrl: String,
+                accountToken: String
+            }
+        },
+        atomicConfiguration: {
+            backups: Number,
+            cacheMode: {type: String, enum: ['LOCAL', 'REPLICATED', 'PARTITIONED']},
+            atomicSequenceReserveSize: Number,
+            affinity: {
+                kind: {type: String, enum: ['Default', 'Rendezvous', 'Custom']},
+                Rendezvous: {
+                    affinityBackupFilter: String,
+                    partitions: Number,
+                    excludeNeighbors: Boolean
+                },
+                Custom: {
+                    className: String
+                }
+            },
+            groupName: String
+        },
+        binaryConfiguration: {
+            idMapper: String,
+            nameMapper: String,
+            serializer: String,
+            typeConfigurations: [{
+                typeName: String,
+                idMapper: String,
+                nameMapper: String,
+                serializer: String,
+                enum: Boolean,
+                enumValues: [String]
+            }],
+            compactFooter: Boolean
+        },
+        caches: [{type: ObjectId, ref: 'Cache'}],
+        models: [{type: ObjectId, ref: 'DomainModel'}],
+        clockSyncSamples: Number,
+        clockSyncFrequency: Number,
+        deploymentMode: {type: String, enum: ['PRIVATE', 'ISOLATED', 'SHARED', 'CONTINUOUS']},
+        discoveryStartupDelay: Number,
+        igfsThreadPoolSize: Number,
+        igfss: [{type: ObjectId, ref: 'Igfs'}],
+        includeEventTypes: [String],
+        eventStorage: {
+            kind: {type: String, enum: ['Memory', 'Custom']},
+            Memory: {
+                expireAgeMs: Number,
+                expireCount: Number,
+                filter: String
+            },
+            Custom: {
+                className: String
+            }
+        },
+        managementThreadPoolSize: Number,
+        marshaller: {
+            kind: {type: String, enum: ['OptimizedMarshaller', 'JdkMarshaller']},
+            OptimizedMarshaller: {
+                poolSize: Number,
+                requireSerializable: Boolean
+            }
+        },
+        marshalLocalJobs: Boolean,
+        marshallerCacheKeepAliveTime: Number,
+        marshallerCacheThreadPoolSize: Number,
+        metricsExpireTime: Number,
+        metricsHistorySize: Number,
+        metricsLogFrequency: Number,
+        metricsUpdateFrequency: Number,
+        networkTimeout: Number,
+        networkSendRetryDelay: Number,
+        networkSendRetryCount: Number,
+        communication: {
+            listener: String,
+            localAddress: String,
+            localPort: Number,
+            localPortRange: Number,
+            sharedMemoryPort: Number,
+            directBuffer: Boolean,
+            directSendBuffer: Boolean,
+            idleConnectionTimeout: Number,
+            connectTimeout: Number,
+            maxConnectTimeout: Number,
+            reconnectCount: Number,
+            socketSendBuffer: Number,
+            socketReceiveBuffer: Number,
+            messageQueueLimit: Number,
+            slowClientQueueLimit: Number,
+            tcpNoDelay: Boolean,
+            ackSendThreshold: Number,
+            unacknowledgedMessagesBufferSize: Number,
+            socketWriteTimeout: Number,
+            selectorsCount: Number,
+            addressResolver: String,
+            selectorSpins: Number,
+            connectionsPerNode: Number,
+            usePairedConnections: Boolean,
+            filterReachableAddresses: Boolean
+        },
+        connector: {
+            enabled: Boolean,
+            jettyPath: String,
+            host: String,
+            port: Number,
+            portRange: Number,
+            idleTimeout: Number,
+            idleQueryCursorTimeout: Number,
+            idleQueryCursorCheckFrequency: Number,
+            receiveBufferSize: Number,
+            sendBufferSize: Number,
+            sendQueueLimit: Number,
+            directBuffer: Boolean,
+            noDelay: Boolean,
+            selectorCount: Number,
+            threadPoolSize: Number,
+            messageInterceptor: String,
+            secretKey: String,
+            sslEnabled: Boolean,
+            sslClientAuth: Boolean,
+            sslFactory: String
+        },
+        peerClassLoadingEnabled: Boolean,
+        peerClassLoadingLocalClassPathExclude: [String],
+        peerClassLoadingMissedResourcesCacheSize: Number,
+        peerClassLoadingThreadPoolSize: Number,
+        publicThreadPoolSize: Number,
+        swapSpaceSpi: {
+            kind: {type: String, enum: ['FileSwapSpaceSpi']},
+            FileSwapSpaceSpi: {
+                baseDirectory: String,
+                readStripesNumber: Number,
+                maximumSparsity: Number,
+                maxWriteQueueSize: Number,
+                writeBufferSize: Number
+            }
+        },
+        systemThreadPoolSize: Number,
+        timeServerPortBase: Number,
+        timeServerPortRange: Number,
+        transactionConfiguration: {
+            defaultTxConcurrency: {type: String, enum: ['OPTIMISTIC', 'PESSIMISTIC']},
+            defaultTxIsolation: {type: String, enum: ['READ_COMMITTED', 'REPEATABLE_READ', 'SERIALIZABLE']},
+            defaultTxTimeout: Number,
+            pessimisticTxLogLinger: Number,
+            pessimisticTxLogSize: Number,
+            txSerializableEnabled: Boolean,
+            txManagerFactory: String,
+            useJtaSynchronization: Boolean,
+            txTimeoutOnPartitionMapExchange: Number, // 2.5
+            deadlockTimeout: Number // 2.8
+        },
+        sslEnabled: Boolean,
+        sslContextFactory: {
+            keyAlgorithm: String,
+            keyStoreFilePath: String,
+            keyStoreType: String,
+            protocol: String,
+            trustStoreFilePath: String,
+            trustStoreType: String,
+            trustManagers: [String],
+            cipherSuites: [String],
+            protocols: [String]
+        },
+        rebalanceThreadPoolSize: Number,
+        odbc: {
+            odbcEnabled: Boolean,
+            endpointAddress: String,
+            socketSendBufferSize: Number,
+            socketReceiveBufferSize: Number,
+            maxOpenCursors: Number,
+            threadPoolSize: Number
+        },
+        attributes: [{name: String, value: String}],
+        collision: {
+            kind: {type: String, enum: ['Noop', 'PriorityQueue', 'FifoQueue', 'JobStealing', 'Custom']},
+            PriorityQueue: {
+                parallelJobsNumber: Number,
+                waitingJobsNumber: Number,
+                priorityAttributeKey: String,
+                jobPriorityAttributeKey: String,
+                defaultPriority: Number,
+                starvationIncrement: Number,
+                starvationPreventionEnabled: Boolean
+            },
+            FifoQueue: {
+                parallelJobsNumber: Number,
+                waitingJobsNumber: Number
+            },
+            JobStealing: {
+                activeJobsThreshold: Number,
+                waitJobsThreshold: Number,
+                messageExpireTime: Number,
+                maximumStealingAttempts: Number,
+                stealingEnabled: Boolean,
+                stealingAttributes: [{name: String, value: String}],
+                externalCollisionListener: String
+            },
+            Custom: {
+                class: String
+            }
+        },
+        failoverSpi: [{
+            kind: {type: String, enum: ['JobStealing', 'Never', 'Always', 'Custom']},
+            JobStealing: {
+                maximumFailoverAttempts: Number
+            },
+            Always: {
+                maximumFailoverAttempts: Number
+            },
+            Custom: {
+                class: String
+            }
+        }],
+        logger: {
+            kind: {type: 'String', enum: ['Log4j2', 'Null', 'Java', 'JCL', 'SLF4J', 'Log4j', 'Custom']},
+            Log4j2: {
+                level: {type: String, enum: ['OFF', 'FATAL', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE', 'ALL']},
+                path: String
+            },
+            Log4j: {
+                mode: {type: String, enum: ['Default', 'Path']},
+                level: {type: String, enum: ['OFF', 'FATAL', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE', 'ALL']},
+                path: String
+            },
+            Custom: {
+                class: String
+            }
+        },
+        cacheKeyConfiguration: [{
+            typeName: String,
+            affinityKeyFieldName: String
+        }],
+        checkpointSpi: [{
+            kind: {type: String, enum: ['FS', 'Cache', 'S3', 'JDBC', 'Custom']},
+            FS: {
+                directoryPaths: [String],
+                checkpointListener: String
+            },
+            Cache: {
+                cache: {type: ObjectId, ref: 'Cache'},
+                checkpointListener: String
+            },
+            S3: {
+                awsCredentials: {
+                    kind: {type: String, enum: ['Basic', 'Properties', 'Anonymous', 'BasicSession', 'Custom']},
+                    Properties: {
+                        path: String
+                    },
+                    Custom: {
+                        className: String
+                    }
+                },
+                bucketNameSuffix: String,
+                bucketEndpoint: String,
+                SSEAlgorithm: String,
+                clientConfiguration: {
+                    protocol: {type: String, enum: ['HTTP', 'HTTPS']},
+                    maxConnections: Number,
+                    userAgentPrefix: String,
+                    userAgentSuffix: String,
+                    localAddress: String,
+                    proxyHost: String,
+                    proxyPort: Number,
+                    proxyUsername: String,
+                    proxyDomain: String,
+                    proxyWorkstation: String,
+                    retryPolicy: {
+                        kind: {
+                            type: String,
+                            enum: ['Default', 'DefaultMaxRetries', 'DynamoDB', 'DynamoDBMaxRetries', 'Custom']
+                        },
+                        DefaultMaxRetries: {
+                            maxErrorRetry: Number
+                        },
+                        DynamoDBMaxRetries: {
+                            maxErrorRetry: Number
+                        },
+                        Custom: {
+                            retryCondition: String,
+                            backoffStrategy: String,
+                            maxErrorRetry: Number,
+                            honorMaxErrorRetryInClientConfig: Boolean
+                        }
+                    },
+                    maxErrorRetry: Number,
+                    socketTimeout: Number,
+                    connectionTimeout: Number,
+                    requestTimeout: Number,
+                    useReaper: Boolean,
+                    useGzip: Boolean,
+                    signerOverride: String,
+                    preemptiveBasicProxyAuth: Boolean,
+                    connectionTTL: Number,
+                    connectionMaxIdleMillis: Number,
+                    useTcpKeepAlive: Boolean,
+                    dnsResolver: String,
+                    responseMetadataCacheSize: Number,
+                    secureRandom: String,
+                    cacheResponseMetadata: {type: Boolean, default: true},
+                    clientExecutionTimeout: Number,
+                    nonProxyHosts: String,
+                    socketSendBufferSizeHint: Number,
+                    socketReceiveBufferSizeHint: Number,
+                    useExpectContinue: {type: Boolean, default: true},
+                    useThrottleRetries: {type: Boolean, default: true}
+                },
+                checkpointListener: String
+            },
+            JDBC: {
+                dataSourceBean: String,
+                dialect: {
+                    type: String,
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                },
+                user: String,
+                checkpointTableName: String,
+                keyFieldName: String,
+                keyFieldType: String,
+                valueFieldName: String,
+                valueFieldType: String,
+                expireDateFieldName: String,
+                expireDateFieldType: String,
+                numberOfRetries: Number,
+                checkpointListener: String
+            },
+            Custom: {
+                className: String
+            }
+        }],
+        clientConnectorConfiguration: {
+            enabled: Boolean,
+            host: String,
+            port: Number,
+            portRange: Number,
+            socketSendBufferSize: Number,
+            socketReceiveBufferSize: Number,
+            tcpNoDelay: {type: Boolean, default: true},
+            maxOpenCursorsPerConnection: Number,
+            threadPoolSize: Number,
+            idleTimeout: Number,
+            jdbcEnabled: {type: Boolean, default: true},
+            odbcEnabled: {type: Boolean, default: true},
+            thinClientEnabled: {type: Boolean, default: true},
+            sslEnabled: Boolean,
+            useIgniteSslContextFactory: {type: Boolean, default: true},
+            sslClientAuth: Boolean,
+            sslContextFactory: String
+        },
+        loadBalancingSpi: [{
+            kind: {type: String, enum: ['RoundRobin', 'Adaptive', 'WeightedRandom', 'Custom']},
+            RoundRobin: {
+                perTask: Boolean
+            },
+            Adaptive: {
+                loadProbe: {
+                    kind: {type: String, enum: ['Job', 'CPU', 'ProcessingTime', 'Custom']},
+                    Job: {
+                        useAverage: Boolean
+                    },
+                    CPU: {
+                        useAverage: Boolean,
+                        useProcessors: Boolean,
+                        processorCoefficient: Number
+                    },
+                    ProcessingTime: {
+                        useAverage: Boolean
+                    },
+                    Custom: {
+                        className: String
+                    }
+                }
+            },
+            WeightedRandom: {
+                nodeWeight: Number,
+                useWeights: Boolean
+            },
+            Custom: {
+                className: String
+            }
+        }],
+        deploymentSpi: {
+            kind: {type: String, enum: ['URI', 'Local', 'Custom']},
+            URI: {
+                uriList: [String],
+                temporaryDirectoryPath: String,
+                scanners: [String],
+                listener: String,
+                checkMd5: Boolean,
+                encodeUri: Boolean
+            },
+            Local: {
+                listener: String
+            },
+            Custom: {
+                className: String
+            }
+        },
+        warmupClosure: String,
+        hadoopConfiguration: {
+            mapReducePlanner: {
+                kind: {type: String, enum: ['Weighted', 'Custom']},
+                Weighted: {
+                    localMapperWeight: Number,
+                    remoteMapperWeight: Number,
+                    localReducerWeight: Number,
+                    remoteReducerWeight: Number,
+                    preferLocalReducerThresholdWeight: Number
+                },
+                Custom: {
+                    className: String
+                }
+            },
+            finishedJobInfoTtl: Number,
+            maxParallelTasks: Number,
+            maxTaskQueueSize: Number,
+            nativeLibraryNames: [String]
+        },
+        serviceConfigurations: [{
+            name: String,
+            service: String,
+            maxPerNodeCount: Number,
+            totalCount: Number,
+            nodeFilter: {
+                kind: {type: String, enum: ['Default', 'Exclude', 'IGFS', 'OnNodes', 'Custom']},
+                Exclude: {
+                    nodeId: String
+                },
+                IGFS: {
+                    igfs: {type: ObjectId, ref: 'Igfs'}
+                },
+                Custom: {
+                    className: String
+                }
+            },
+            cache: {type: ObjectId, ref: 'Cache'},
+            affinityKey: String
+        }],
+        cacheSanityCheckEnabled: {type: Boolean, default: true},
+        classLoader: String,
+        consistentId: String,
+        failureDetectionTimeout: Number,
+        clientFailureDetectionTimeout: Number,
+        systemWorkerBlockedTimeout: Number,
+        workDirectory: String,
+        igniteHome: String,
+        lateAffinityAssignment: Boolean,
+        utilityCacheKeepAliveTime: Number,
+        asyncCallbackPoolSize: Number,
+        dataStreamerThreadPoolSize: Number,
+        queryThreadPoolSize: Number,
+        stripedPoolSize: Number,
+        serviceThreadPoolSize: Number,
+        utilityCacheThreadPoolSize: Number,
+        executorConfiguration: [{
+            name: String,
+            size: Number
+        }],
+        dataStorageConfiguration: {
+            systemRegionInitialSize: Number,
+            systemRegionMaxSize: Number,
+            pageSize: Number,
+            concurrencyLevel: Number,
+            defaultDataRegionConfiguration: {
+                name: String,
+                initialSize: Number,
+                maxSize: Number,
+                swapPath: String,
+                pageEvictionMode: {type: String, enum: ['DISABLED', 'RANDOM_LRU', 'RANDOM_2_LRU']},
+                evictionThreshold: Number,
+                emptyPagesPoolSize: Number,
+                metricsEnabled: Boolean,
+                metricsSubIntervalCount: Number,
+                metricsRateTimeInterval: Number,
+                persistenceEnabled: Boolean,
+                checkpointPageBufferSize: Number
+            },
+            dataRegionConfigurations: [{
+                name: String,
+                initialSize: Number,
+                maxSize: Number,
+                swapPath: String,
+                pageEvictionMode: {type: String, enum: ['DISABLED', 'RANDOM_LRU', 'RANDOM_2_LRU']},
+                evictionThreshold: Number,
+                emptyPagesPoolSize: Number,
+                metricsEnabled: Boolean,
+                metricsSubIntervalCount: Number,
+                metricsRateTimeInterval: Number,
+                persistenceEnabled: Boolean,
+                checkpointPageBufferSize: Number
+            }],
+            storagePath: String,
+            metricsEnabled: Boolean,
+            alwaysWriteFullPages: Boolean,
+            checkpointFrequency: Number,
+            checkpointThreads: Number,
+            checkpointWriteOrder: {type: String, enum: ['RANDOM', 'SEQUENTIAL']},
+            walPath: String,
+            walArchivePath: String,
+            walMode: {type: String, enum: ['DEFAULT', 'LOG_ONLY', 'BACKGROUND', 'NONE']},
+            walSegments: Number,
+            walSegmentSize: Number,
+            walHistorySize: Number,
+            walFlushFrequency: Number,
+            walFsyncDelayNanos: Number,
+            walRecordIteratorBufferSize: Number,
+            lockWaitTime: Number,
+            walBufferSize: Number,
+            walThreadLocalBufferSize: Number,
+            metricsSubIntervalCount: Number,
+            metricsRateTimeInterval: Number,
+            fileIOFactory: {type: String, enum: ['RANDOM', 'ASYNC']},
+            walAutoArchiveAfterInactivity: Number,
+            writeThrottlingEnabled: Boolean,
+            walCompactionEnabled: Boolean,
+            checkpointReadLockTimeout: Number,
+            maxWalArchiveSize: Number,
+            walCompactionLevel: Number
+        },
+        memoryConfiguration: {
+            systemCacheInitialSize: Number,
+            systemCacheMaxSize: Number,
+            pageSize: Number,
+            concurrencyLevel: Number,
+            defaultMemoryPolicyName: String,
+            defaultMemoryPolicySize: Number,
+            memoryPolicies: [{
+                name: String,
+                initialSize: Number,
+                maxSize: Number,
+                swapFilePath: String,
+                pageEvictionMode: {type: String, enum: ['DISABLED', 'RANDOM_LRU', 'RANDOM_2_LRU']},
+                evictionThreshold: Number,
+                emptyPagesPoolSize: Number,
+                metricsEnabled: Boolean,
+                subIntervals: Number,
+                rateTimeInterval: Number
+            }]
+        },
+        longQueryWarningTimeout: Number,
+        sqlConnectorConfiguration: {
+            enabled: Boolean,
+            host: String,
+            port: Number,
+            portRange: Number,
+            socketSendBufferSize: Number,
+            socketReceiveBufferSize: Number,
+            tcpNoDelay: {type: Boolean, default: true},
+            maxOpenCursorsPerConnection: Number,
+            threadPoolSize: Number
+        },
+        persistenceStoreConfiguration: {
+            enabled: Boolean,
+            persistentStorePath: String,
+            metricsEnabled: Boolean,
+            alwaysWriteFullPages: Boolean,
+            checkpointingFrequency: Number,
+            checkpointingPageBufferSize: Number,
+            checkpointingThreads: Number,
+            walStorePath: String,
+            walArchivePath: String,
+            walMode: {type: String, enum: ['DEFAULT', 'LOG_ONLY', 'BACKGROUND', 'NONE']},
+            walSegments: Number,
+            walSegmentSize: Number,
+            walHistorySize: Number,
+            walFlushFrequency: Number,
+            walFsyncDelayNanos: Number,
+            walRecordIteratorBufferSize: Number,
+            lockWaitTime: Number,
+            rateTimeInterval: Number,
+            tlbSize: Number,
+            subIntervals: Number,
+            walAutoArchiveAfterInactivity: Number
+        },
+        encryptionSpi: {
+            kind: {type: String, enum: ['Noop', 'Keystore', 'Custom']},
+            Keystore: {
+                keySize: Number,
+                masterKeyName: String,
+                keyStorePath: String
+            },
+            Custom: {
+                className: String
+            }
+        },
+        failureHandler: {
+            kind: {type: String, enum: ['RestartProcess', 'StopNodeOnHalt', 'StopNode', 'Noop', 'Custom']},
+            ignoredFailureTypes: [{type: String, enum: ['SEGMENTATION', 'SYSTEM_WORKER_TERMINATION',
+                    'SYSTEM_WORKER_BLOCKED', 'CRITICAL_ERROR', 'SYSTEM_CRITICAL_OPERATION_TIMEOUT']}],
+            StopNodeOnHalt: {
+                tryStop: Boolean,
+                timeout: Number
+            },
+            Custom: {
+                className: String
+            }
+        },
+        localEventListeners: [{
+            className: String,
+            eventTypes: [String]
+        }],
+        mvccVacuumThreadCount: Number,
+        mvccVacuumFrequency: Number,
+        authenticationEnabled: Boolean,
+        sqlQueryHistorySize: Number,
+        lifecycleBeans: [String],
+        addressResolver: String,
+        mBeanServer: String,
+        networkCompressionLevel: Number,
+        includeProperties: [String],
+        cacheStoreSessionListenerFactories: [String],
+        autoActivationEnabled: {type: Boolean, default: true},
+        sqlSchemas: [String],
+        communicationFailureResolver: String
+    });
+
+    Cluster.index({name: 1, space: 1}, {unique: true});
+
+    // Define Notebook schema.
+    const Notebook = new Schema({
+        space: {type: ObjectId, ref: 'Space', index: true, required: true},
+        name: String,
+        expandedParagraphs: [Number],
+        paragraphs: [{
+            name: String,
+            query: String,
+            editor: Boolean,
+            result: {type: String, enum: ['none', 'table', 'bar', 'pie', 'line', 'area']},
+            pageSize: Number,
+            timeLineSpan: String,
+            maxPages: Number,
+            hideSystemColumns: Boolean,
+            cacheName: String,
+            useAsDefaultSchema: Boolean,
+            chartsOptions: {barChart: {stacked: Boolean}, areaChart: {style: String}},
+            rate: {
+                value: Number,
+                unit: Number
+            },
+            qryType: String,
+            nonCollocatedJoins: {type: Boolean, default: false},
+            enforceJoinOrder: {type: Boolean, default: false},
+            lazy: {type: Boolean, default: false},
+            collocated: Boolean
+        }]
+    });
+
+    Notebook.index({name: 1, space: 1}, {unique: true});
+
+    // Define Activities schema.
+    const Activities = new Schema({
+        owner: {type: ObjectId, ref: 'Account'},
+        date: Date,
+        group: String,
+        action: String,
+        amount: {type: Number, default: 0}
+    });
+
+    Activities.index({owner: 1, group: 1, action: 1, date: 1}, {unique: true});
+
+    // Define Notifications schema.
+    const Notifications = new Schema({
+        owner: {type: ObjectId, ref: 'Account'},
+        date: Date,
+        message: String,
+        isShown: Boolean
+    });
+
+    return {
+        Space,
+        Account,
+        DomainModel,
+        Cache,
+        Igfs,
+        Cluster,
+        Notebook,
+        Activities,
+        Notifications
+    };
+};
diff --git a/modules/backend/app/settings.js b/modules/backend/app/settings.js
new file mode 100644
index 0000000..0079788
--- /dev/null
+++ b/modules/backend/app/settings.js
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const fs = require('fs');
+const _ = require('lodash');
+
+// Fire me up!
+
+/**
+ * Module with server-side configuration.
+ */
+module.exports = {
+    implements: 'settings',
+    inject: ['nconf'],
+    factory(nconf) {
+        /**
+         * Normalize a port into a number, string, or false.
+         */
+        const _normalizePort = function(val) {
+            const port = parseInt(val, 10);
+
+            // named pipe
+            if (isNaN(port))
+                return val;
+
+            // port number
+            if (port >= 0)
+                return port;
+
+            return false;
+        };
+
+        const mail = nconf.get('mail') || {};
+
+        const packaged = __dirname.startsWith('/snapshot/') || __dirname.startsWith('C:\\snapshot\\');
+
+        const dfltAgentDists = packaged ? 'libs/agent_dists' : 'agent_dists';
+        const dfltHost = packaged ? '0.0.0.0' : '127.0.0.1';
+        const dfltPort = packaged ? 80 : 3000;
+
+        // We need this function because nconf() can return String or Boolean.
+        // And in JS we cannot compare String with Boolean.
+        const _isTrue = (confParam) => {
+            const v = nconf.get(confParam);
+
+            return v === 'true' || v === true;
+        };
+
+        let activationEnabled = _isTrue('activation:enabled');
+
+        if (activationEnabled && _.isEmpty(mail)) {
+            activationEnabled = false;
+
+            console.warn('Mail server settings are required for account confirmation!');
+        }
+
+        const settings = {
+            agent: {
+                dists: nconf.get('agent:dists') || dfltAgentDists
+            },
+            packaged,
+            server: {
+                host: nconf.get('server:host') || dfltHost,
+                port: _normalizePort(nconf.get('server:port') || dfltPort),
+                disableSignup: _isTrue('server:disable:signup')
+            },
+            mail,
+            activation: {
+                enabled: activationEnabled,
+                timeout: nconf.get('activation:timeout') || 1800000,
+                sendTimeout: nconf.get('activation:sendTimeout') || 180000
+            },
+            mongoUrl: nconf.get('mongodb:url') || 'mongodb://127.0.0.1/console',
+            cookieTTL: 3600000 * 24 * 30,
+            sessionSecret: nconf.get('server:sessionSecret') || 'keyboard cat',
+            tokenLength: 20
+        };
+
+        // Configure SSL options.
+        if (_isTrue('server:ssl')) {
+            const sslOptions = {
+                enable301Redirects: true,
+                trustXFPHeader: true,
+                isServer: true
+            };
+
+            const setSslOption = (name, fromFile = false) => {
+                const v = nconf.get(`server:${name}`);
+
+                const hasOption = !!v;
+
+                if (hasOption)
+                    sslOptions[name] = fromFile ? fs.readFileSync(v) : v;
+
+                return hasOption;
+            };
+
+            const setSslOptionBoolean = (name) => {
+                const v = nconf.get(`server:${name}`);
+
+                if (v)
+                    sslOptions[name] = v === 'true' || v === true;
+            };
+
+            setSslOption('key', true);
+            setSslOption('cert', true);
+            setSslOption('ca', true);
+            setSslOption('passphrase');
+            setSslOption('ciphers');
+            setSslOption('secureProtocol');
+            setSslOption('clientCertEngine');
+            setSslOption('pfx', true);
+            setSslOption('crl');
+            setSslOption('dhparam');
+            setSslOption('ecdhCurve');
+            setSslOption('maxVersion');
+            setSslOption('minVersion');
+            setSslOption('secureOptions');
+            setSslOption('sessionIdContext');
+
+            setSslOptionBoolean('honorCipherOrder');
+            setSslOptionBoolean('requestCert');
+            setSslOptionBoolean('rejectUnauthorized');
+
+            // Special care for case, when user set password for something like "123456".
+            if (sslOptions.passphrase)
+                sslOptions.passphrase = sslOptions.passphrase.toString();
+
+            settings.server.SSLOptions = sslOptions;
+        }
+
+        return settings;
+    }
+};
diff --git a/modules/backend/config/settings.json.sample b/modules/backend/config/settings.json.sample
new file mode 100644
index 0000000..02bc327
--- /dev/null
+++ b/modules/backend/config/settings.json.sample
@@ -0,0 +1,36 @@
+{
+  "server": {
+    "port": 3000,
+    "sessionSecret": "CHANGE ME",
+    "ssl": false,
+    "key": "path to file with server.key",
+    "cert": "path to file with server.crt",
+    "ca": "path to file with ca.crt",
+    "passphrase": "password",
+    "ciphers": "ECDHE-RSA-AES128-GCM-SHA256",
+    "secureProtocol": "TLSv1_2_method",
+    "requestCert": false,
+    "rejectUnauthorized": false,
+    "disable": {
+      "signup": false
+    }
+  },
+  "mongodb": {
+    "url": "mongodb://localhost/console"
+  },
+  "activation": {
+      "enabled": false,
+      "timeout": 1800000,
+      "sendTimeout": 180000
+  },
+  "mail": {
+    "service": "gmail",
+    "from": "Some Company Web Console <some_username@some_company.com>",
+    "greeting": "Some Company Web Console",
+    "sign": "Kind regards,<br>Some Company Team",
+    "auth": {
+      "user": "some_username@some_company.com",
+      "pass": "CHANGE ME"
+    }
+  }
+}
diff --git a/modules/backend/errors/AppErrorException.js b/modules/backend/errors/AppErrorException.js
new file mode 100644
index 0000000..19a9b0d
--- /dev/null
+++ b/modules/backend/errors/AppErrorException.js
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+class AppErrorException extends Error {
+    constructor(message) {
+        super(message);
+
+        this.name = this.constructor.name;
+        this.code = 400;
+
+        if (typeof Error.captureStackTrace === 'function')
+            Error.captureStackTrace(this, this.constructor);
+        else
+            this.stack = (new Error(message)).stack;
+    }
+}
+
+module.exports = AppErrorException;
diff --git a/modules/backend/errors/AuthFailedException.js b/modules/backend/errors/AuthFailedException.js
new file mode 100644
index 0000000..9cab6ac
--- /dev/null
+++ b/modules/backend/errors/AuthFailedException.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const AppErrorException = require('./AppErrorException');
+
+class AuthFailedException extends AppErrorException {
+    constructor(message) {
+        super(message);
+
+        this.code = 401;
+    }
+}
+
+module.exports = AuthFailedException;
diff --git a/modules/backend/errors/DuplicateKeyException.js b/modules/backend/errors/DuplicateKeyException.js
new file mode 100644
index 0000000..536d53d
--- /dev/null
+++ b/modules/backend/errors/DuplicateKeyException.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const AppErrorException = require('./AppErrorException');
+
+class DuplicateKeyException extends AppErrorException {
+    constructor(message) {
+        super(message);
+    }
+}
+
+module.exports = DuplicateKeyException;
diff --git a/modules/backend/errors/IllegalAccessError.js b/modules/backend/errors/IllegalAccessError.js
new file mode 100644
index 0000000..7de9bb1
--- /dev/null
+++ b/modules/backend/errors/IllegalAccessError.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const AppErrorException = require('./AppErrorException');
+
+class IllegalAccessError extends AppErrorException {
+    constructor(message) {
+        super(message);
+
+        this.code = 403;
+    }
+}
+
+module.exports = IllegalAccessError;
diff --git a/modules/backend/errors/IllegalArgumentException.js b/modules/backend/errors/IllegalArgumentException.js
new file mode 100644
index 0000000..aeb4187
--- /dev/null
+++ b/modules/backend/errors/IllegalArgumentException.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const AppErrorException = require('./AppErrorException');
+
+class IllegalArgumentException extends AppErrorException {
+    constructor(message) {
+        super(message);
+    }
+}
+
+module.exports = IllegalArgumentException;
diff --git a/modules/backend/errors/MissingConfirmRegistrationException.js b/modules/backend/errors/MissingConfirmRegistrationException.js
new file mode 100644
index 0000000..a094a67
--- /dev/null
+++ b/modules/backend/errors/MissingConfirmRegistrationException.js
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const IllegalAccessError = require('./IllegalAccessError');
+
+class MissingConfirmRegistrationException extends IllegalAccessError {
+    constructor(email) {
+        super('User account email not activated');
+
+        this.data = {
+            errorCode: 10104,
+            message: this.message,
+            email
+        };
+    }
+}
+
+module.exports = MissingConfirmRegistrationException;
diff --git a/modules/backend/errors/MissingResourceException.js b/modules/backend/errors/MissingResourceException.js
new file mode 100644
index 0000000..aeac70e
--- /dev/null
+++ b/modules/backend/errors/MissingResourceException.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const AppErrorException = require('./AppErrorException');
+
+class MissingResourceException extends AppErrorException {
+    constructor(message) {
+        super(message);
+
+        this.code = 404;
+    }
+}
+
+module.exports = MissingResourceException;
diff --git a/modules/backend/errors/ServerErrorException.js b/modules/backend/errors/ServerErrorException.js
new file mode 100644
index 0000000..c2edb7f
--- /dev/null
+++ b/modules/backend/errors/ServerErrorException.js
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+class ServerErrorException extends Error {
+    constructor(message) {
+        super(message);
+
+        this.name = this.constructor.name;
+        this.code = 500;
+        this.message = message;
+
+        if (typeof Error.captureStackTrace === 'function')
+            Error.captureStackTrace(this, this.constructor);
+        else
+            this.stack = (new Error(message)).stack;
+    }
+}
+
+module.exports = ServerErrorException;
diff --git a/modules/backend/errors/index.js b/modules/backend/errors/index.js
new file mode 100644
index 0000000..cb8f043
--- /dev/null
+++ b/modules/backend/errors/index.js
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+const AppErrorException = require('./AppErrorException');
+const IllegalArgumentException = require('./IllegalArgumentException');
+const IllegalAccessError = require('./IllegalAccessError');
+const DuplicateKeyException = require('./DuplicateKeyException');
+const ServerErrorException = require('./ServerErrorException');
+const MissingConfirmRegistrationException = require('./MissingConfirmRegistrationException');
+const MissingResourceException = require('./MissingResourceException');
+const AuthFailedException = require('./AuthFailedException');
+
+module.exports = {
+    implements: 'errors',
+    factory: () => ({
+        AppErrorException,
+        IllegalAccessError,
+        IllegalArgumentException,
+        DuplicateKeyException,
+        ServerErrorException,
+        MissingConfirmRegistrationException,
+        MissingResourceException,
+        AuthFailedException
+    })
+};
diff --git a/modules/backend/index.js b/modules/backend/index.js
new file mode 100755
index 0000000..26584bc
--- /dev/null
+++ b/modules/backend/index.js
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const path = require('path');
+
+const appPath = require('app-module-path');
+appPath.addPath(__dirname);
+appPath.addPath(path.join(__dirname, 'node_modules'));
+
+const { migrate, init } = require('./launch-tools');
+
+const injector = require('./injector');
+
+injector.log.info = () => {};
+injector.log.debug = () => {};
+
+injector('mongo')
+    .then((mongo) => migrate(mongo.connection, 'Ignite', path.join(__dirname, 'migrations')))
+    .then(() => Promise.all([injector('settings'), injector('api-server'), injector('agents-handler'), injector('browsers-handler')]))
+    .then(init)
+    .catch((err) => {
+        console.error(err);
+
+        process.exit(1);
+    });
diff --git a/modules/backend/injector.js b/modules/backend/injector.js
new file mode 100644
index 0000000..c30609a
--- /dev/null
+++ b/modules/backend/injector.js
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+const fireUp = require('fire-up');
+
+module.exports = fireUp.newInjector({
+    basePath: __dirname,
+    modules: [
+        './app/**/*.js',
+        './errors/**/*.js',
+        './middlewares/**/*.js',
+        './routes/**/*.js',
+        './services/**/*.js'
+    ]
+});
diff --git a/modules/backend/launch-tools.js b/modules/backend/launch-tools.js
new file mode 100644
index 0000000..7b44aca
--- /dev/null
+++ b/modules/backend/launch-tools.js
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+const _ = require('lodash');
+const http = require('http');
+const https = require('https');
+const MigrateMongoose = require('migrate-mongoose-typescript');
+
+/**
+ * Event listener for HTTP server "error" event.
+ */
+const _onError = (addr, error) => {
+    if (error.syscall !== 'listen')
+        throw error;
+
+    // Handle specific listen errors with friendly messages.
+    switch (error.code) {
+        case 'EACCES':
+            console.error(`Requires elevated privileges for bind to ${addr}`);
+            process.exit(1);
+
+            break;
+        case 'EADDRINUSE':
+            console.error(`${addr} is already in use`);
+            process.exit(1);
+
+            break;
+        default:
+            throw error;
+    }
+};
+
+/**
+ * @param settings
+ * @param {ApiServer} apiSrv
+ * @param {AgentsHandler} agentsHnd
+ * @param {BrowsersHandler} browsersHnd
+ */
+const init = ([settings, apiSrv, agentsHnd, browsersHnd]) => {
+    // Start rest server.
+    const sslOptions = settings.server.SSLOptions;
+
+    console.log(`Starting ${sslOptions ? 'HTTPS' : 'HTTP'} server`);
+
+    const srv = sslOptions ? https.createServer(sslOptions) : http.createServer();
+
+    srv.listen(settings.server.port, settings.server.host);
+
+    const addr = `${settings.server.host}:${settings.server.port}`;
+
+    srv.on('error', _onError.bind(null, addr));
+    srv.on('listening', () => console.log(`Start listening on ${addr}`));
+
+    apiSrv.attach(srv);
+
+    agentsHnd.attach(srv, browsersHnd);
+    browsersHnd.attach(srv, agentsHnd);
+
+    // Used for automated test.
+    if (process.send)
+        process.send('running');
+};
+
+/**
+ * Run mongo model migration.
+ *
+ * @param connection Mongo connection.
+ * @param group Migrations group.
+ * @param migrationsPath Migrations path.
+ * @param collectionName Name of collection where migrations write info about applied scripts.
+ */
+const migrate = (connection, group, migrationsPath, collectionName) => {
+    const migrator = new MigrateMongoose({
+        migrationsPath,
+        connection,
+        collectionName,
+        autosync: true
+    });
+
+    console.log(`Running ${group} migrations...`);
+
+    return migrator.run('up')
+        .then(() => console.log(`All ${group} migrations finished successfully.`))
+        .catch((err) => {
+            const msg = _.get(err, 'message');
+
+            if (_.startsWith(msg, 'There are no migrations to run') || _.startsWith(msg, 'There are no pending migrations.')) {
+                console.log(`There are no ${group} migrations to run.`);
+
+                return;
+            }
+
+            throw err;
+        });
+};
+
+module.exports = { migrate, init };
diff --git a/modules/backend/middlewares/api.js b/modules/backend/middlewares/api.js
new file mode 100644
index 0000000..d4d832b
--- /dev/null
+++ b/modules/backend/middlewares/api.js
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+const _ = require('lodash');
+
+module.exports = {
+    implements: 'middlewares:api'
+};
+
+module.exports.factory = () => {
+    return (req, res, next) => {
+        // Set headers to avoid API caching in browser (esp. IE)
+        res.header('Cache-Control', 'must-revalidate');
+        res.header('Expires', '-1');
+        res.header('Last-Modified', new Date().toUTCString());
+
+        res.api = {
+            error(err) {
+                if (_.includes(['MongoError', 'MongooseError'], err.name))
+                    return res.status(500).send(err.message);
+
+                if (_.isObject(err.data))
+                    return res.status(err.httpCode || err.code || 500).json(err.data);
+
+                res.status(err.httpCode || err.code || 500).send(err.message);
+            },
+
+            ok(data) {
+                if (_.isNil(data))
+                    return res.sendStatus(404);
+
+                res.status(200).json(data);
+            },
+
+            done() {
+                res.sendStatus(200);
+            }
+        };
+
+        next();
+    };
+};
diff --git a/modules/backend/middlewares/demo.js b/modules/backend/middlewares/demo.js
new file mode 100644
index 0000000..537ede1
--- /dev/null
+++ b/modules/backend/middlewares/demo.js
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'middlewares:demo',
+    factory: () => {
+        return (req, res, next) => {
+            req.demo = () => req.header('IgniteDemoMode');
+
+            next();
+        };
+    }
+};
diff --git a/modules/backend/middlewares/host.js b/modules/backend/middlewares/host.js
new file mode 100644
index 0000000..4c21da2
--- /dev/null
+++ b/modules/backend/middlewares/host.js
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'middlewares:host',
+    factory: () => {
+        return (req, res, next) => {
+            req.origin = function() {
+                if (req.headers.origin)
+                    return req.headers.origin;
+
+                const proto = req.headers['x-forwarded-proto'] || req.protocol;
+
+                const host = req.headers['x-forwarded-host'] || req.get('host');
+
+                return `${proto}://${host}`;
+            };
+
+            next();
+        };
+    }
+};
diff --git a/modules/backend/middlewares/user.js b/modules/backend/middlewares/user.js
new file mode 100644
index 0000000..8923211
--- /dev/null
+++ b/modules/backend/middlewares/user.js
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'middlewares:user',
+    factory: () => {
+        return (req, res, next) => {
+            req.currentUserId = function() {
+                if (req.session.viewedUser && req.user.admin)
+                    return req.session.viewedUser._id;
+
+                return req.user._id;
+            };
+
+            next();
+        };
+    }
+};
diff --git a/modules/backend/migrations/1502249492000-invalidate_rename.js b/modules/backend/migrations/1502249492000-invalidate_rename.js
new file mode 100644
index 0000000..50b1438
--- /dev/null
+++ b/modules/backend/migrations/1502249492000-invalidate_rename.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+exports.up = function up(done) {
+    this('Cache').updateMany({}, { $rename: {invalidate: 'isInvalidate'}})
+        .then(() => done())
+        .catch(done);
+};
+
+exports.down = function down(done) {
+    this('Cache').updateMany({}, { $rename: {isInvalidate: 'invalidate'}})
+        .then(() => done())
+        .catch(done);
+};
diff --git a/modules/backend/migrations/1502432624000-cache-index.js b/modules/backend/migrations/1502432624000-cache-index.js
new file mode 100644
index 0000000..147e2ad
--- /dev/null
+++ b/modules/backend/migrations/1502432624000-cache-index.js
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+const recreateIndex = require('./migration-utils').recreateIndex;
+
+exports.up = function up(done) {
+    recreateIndex(done, this('Cache').collection,
+        'name_1_space_1',
+        {name: 1, space: 1},
+        {name: 1, space: 1, clusters: 1});
+};
+
+exports.down = function down(done) {
+    recreateIndex(done, this('Cache').collection,
+        'name_1_space_1_clusters_1',
+        {name: 1, space: 1, clusters: 1},
+        {name: 1, space: 1});
+};
diff --git a/modules/backend/migrations/1504672035000-igfs-index.js b/modules/backend/migrations/1504672035000-igfs-index.js
new file mode 100644
index 0000000..e802ca9
--- /dev/null
+++ b/modules/backend/migrations/1504672035000-igfs-index.js
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+const recreateIndex = require('./migration-utils').recreateIndex;
+
+exports.up = function up(done) {
+    recreateIndex(done, this('Igfs').collection,
+        'name_1_space_1',
+        {name: 1, space: 1},
+        {name: 1, space: 1, clusters: 1});
+};
+
+exports.down = function down(done) {
+    recreateIndex(done, this('Igfs').collection,
+        'name_1_space_1_clusters_1',
+        {name: 1, space: 1, clusters: 1},
+        {name: 1, space: 1});
+};
diff --git a/modules/backend/migrations/1505114649000-models-index.js b/modules/backend/migrations/1505114649000-models-index.js
new file mode 100644
index 0000000..c007b01
--- /dev/null
+++ b/modules/backend/migrations/1505114649000-models-index.js
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+const recreateIndex = require('./migration-utils').recreateIndex;
+
+exports.up = function up(done) {
+    recreateIndex(done, this('DomainModel').collection,
+        'valueType_1_space_1',
+        {valueType: 1, space: 1},
+        {valueType: 1, space: 1, clusters: 1});
+};
+
+exports.down = function down(done) {
+    recreateIndex(done, this('DomainModel').collection,
+        'valueType_1_space_1_clusters_1',
+        {valueType: 1, space: 1, clusters: 1},
+        {valueType: 1, space: 1});
+};
diff --git a/modules/backend/migrations/1508395969410-init-registered-date.js b/modules/backend/migrations/1508395969410-init-registered-date.js
new file mode 100644
index 0000000..227d743
--- /dev/null
+++ b/modules/backend/migrations/1508395969410-init-registered-date.js
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+const _ = require('lodash');
+
+exports.up = function up(done) {
+    const accountsModel = this('Account');
+
+    accountsModel.find({}).lean().exec()
+        .then((accounts) => _.reduce(accounts, (start, account) => start
+            .then(() => accountsModel.updateOne({_id: account._id}, {$set: {registered: account.lastLogin}}).exec()), Promise.resolve()))
+        .then(() => done())
+        .catch(done);
+};
+
+exports.down = function down(done) {
+    this('Account').updateMany({}, {$unset: {registered: 1}}).exec()
+        .then(() => done())
+        .catch(done);
+};
diff --git a/modules/backend/migrations/1516948939797-migrate-configs.js b/modules/backend/migrations/1516948939797-migrate-configs.js
new file mode 100644
index 0000000..c5bd619
--- /dev/null
+++ b/modules/backend/migrations/1516948939797-migrate-configs.js
@@ -0,0 +1,399 @@
+/*
+ * 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.
+ */
+
+const _ = require('lodash');
+
+const log = require('./migration-utils').log;
+const error = require('./migration-utils').error;
+
+const getClusterForMigration = require('./migration-utils').getClusterForMigration;
+const getCacheForMigration = require('./migration-utils').getCacheForMigration;
+
+const _debug = false;
+const DUPLICATE_KEY_ERROR = 11000;
+
+let dup = 1;
+
+function makeDup(name) {
+    return name + `_dup_${dup++}`;
+}
+
+function linkCacheToCluster(clustersModel, cluster, cachesModel, cache, domainsModel) {
+    return clustersModel.updateOne({_id: cluster._id}, {$addToSet: {caches: cache._id}}).exec()
+        .then(() => cachesModel.updateOne({_id: cache._id}, {clusters: [cluster._id]}).exec())
+        .then(() => {
+            if (_.isEmpty(cache.domains))
+                return Promise.resolve();
+
+            return _.reduce(cache.domains, (start, domain) => start.then(() => {
+                return domainsModel.updateOne({_id: domain}, {clusters: [cluster._id]}).exec()
+                    .then(() => clustersModel.updateOne({_id: cluster._id}, {$addToSet: {models: domain}}).exec());
+            }), Promise.resolve());
+        })
+        .catch((err) => error(`Failed link cache to cluster [cache=${cache.name}, cluster=${cluster.name}]`, err));
+}
+
+function cloneCache(clustersModel, cachesModel, domainsModel, cache) {
+    const cacheId = cache._id;
+    const clusters = cache.clusters;
+
+    cache.clusters = [];
+
+    if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind === null)
+        delete cache.cacheStoreFactory.kind;
+
+    return _.reduce(clusters, (start, cluster, idx) => start.then(() => {
+        if (idx > 0) {
+            delete cache._id;
+
+            const newCache = _.clone(cache);
+            const domainIds = newCache.domains;
+
+            newCache.clusters = [cluster];
+            newCache.domains = [];
+
+            return clustersModel.updateMany({_id: {$in: newCache.clusters}}, {$pull: {caches: cacheId}}).exec()
+                .then(() => cachesModel.create(newCache))
+                .catch((err) => {
+                    if (err.code === DUPLICATE_KEY_ERROR) {
+                        const retryWith = makeDup(newCache.name);
+
+                        error(`Failed to clone cache, will change cache name and retry [cache=${newCache.name}, retryWith=${retryWith}]`);
+
+                        newCache.name = retryWith;
+
+                        return cachesModel.create(newCache);
+                    }
+
+                    return Promise.reject(err);
+                })
+                .then((clone) => clustersModel.updateMany({_id: {$in: newCache.clusters}}, {$addToSet: {caches: clone._id}}).exec()
+                    .then(() => clone))
+                .then((clone) => {
+                    if (_.isEmpty(domainIds))
+                        return Promise.resolve();
+
+                    return _.reduce(domainIds, (start, domainId) => start.then(() => {
+                        return domainsModel.findOne({_id: domainId}).lean().exec()
+                            .then((domain) => {
+                                delete domain._id;
+
+                                const newDomain = _.clone(domain);
+
+                                newDomain.caches = [clone._id];
+                                newDomain.clusters = [cluster];
+
+                                return domainsModel.create(newDomain)
+                                    .catch((err) => {
+                                        if (err.code === DUPLICATE_KEY_ERROR) {
+                                            const retryWith = makeDup(newDomain.valueType);
+
+                                            error(`Failed to clone domain, will change type name and retry [cache=${newCache.name}, valueType=${newDomain.valueType}, retryWith=${retryWith}]`);
+
+                                            newDomain.valueType = retryWith;
+
+                                            return domainsModel.create(newDomain);
+                                        }
+                                    })
+                                    .then((createdDomain) => {
+                                        return clustersModel.updateOne({_id: cluster}, {$addToSet: {models: createdDomain._id}}).exec()
+                                            .then(() => cachesModel.updateOne({_id: clone.id}, {$addToSet: {domains: createdDomain._id}}));
+                                    })
+                                    .catch((err) => error('Failed to clone domain during cache clone', err));
+                            })
+                            .catch((err) => error(`Failed to duplicate domain model[domain=${domainId}], cache=${clone.name}]`, err));
+                    }), Promise.resolve());
+                })
+                .catch((err) => error(`Failed to clone cache[id=${cacheId}, name=${cache.name}]`, err));
+        }
+
+        return cachesModel.updateOne({_id: cacheId}, {clusters: [cluster]}).exec()
+            .then(() => clustersModel.updateOne({_id: cluster}, {$addToSet: {models: {$each: cache.domains}}}).exec());
+    }), Promise.resolve());
+}
+
+function migrateCache(clustersModel, cachesModel, domainsModel, cache) {
+    const clustersCnt = _.size(cache.clusters);
+
+    if (clustersCnt < 1) {
+        if (_debug)
+            log(`Found cache not linked to cluster [cache=${cache.name}]`);
+
+        return getClusterForMigration(clustersModel, cache.space)
+            .then((clusterLostFound) => linkCacheToCluster(clustersModel, clusterLostFound, cachesModel, cache, domainsModel));
+    }
+
+    if (clustersCnt > 1) {
+        if (_debug)
+            log(`Found cache linked to many clusters [cache=${cache.name}, clustersCnt=${clustersCnt}]`);
+
+        return cloneCache(clustersModel, cachesModel, domainsModel, cache);
+    }
+
+    // Nothing to migrate, cache linked to cluster 1-to-1.
+    return Promise.resolve();
+}
+
+function migrateCaches(clustersModel, cachesModel, domainsModel) {
+    return cachesModel.find({}).lean().exec()
+        .then((caches) => {
+            const cachesCnt = _.size(caches);
+
+            if (cachesCnt > 0) {
+                log(`Caches to migrate: ${cachesCnt}`);
+
+                return _.reduce(caches, (start, cache) => start.then(() => migrateCache(clustersModel, cachesModel, domainsModel, cache)), Promise.resolve())
+                    .then(() => log('Caches migration finished.'));
+            }
+
+            return Promise.resolve();
+
+        })
+        .catch((err) => error('Caches migration failed', err));
+}
+
+function linkIgfsToCluster(clustersModel, cluster, igfsModel, igfs) {
+    return clustersModel.updateOne({_id: cluster._id}, {$addToSet: {igfss: igfs._id}}).exec()
+        .then(() => igfsModel.updateOne({_id: igfs._id}, {clusters: [cluster._id]}).exec())
+        .catch((err) => error(`Failed link IGFS to cluster [IGFS=${igfs.name}, cluster=${cluster.name}]`, err));
+}
+
+function cloneIgfs(clustersModel, igfsModel, igfs) {
+    const igfsId = igfs._id;
+    const clusters = igfs.clusters;
+
+    delete igfs._id;
+    igfs.clusters = [];
+
+    return _.reduce(clusters, (start, cluster, idx) => start.then(() => {
+        const newIgfs = _.clone(igfs);
+
+        newIgfs.clusters = [cluster];
+
+        if (idx > 0) {
+            return clustersModel.updateMany({_id: {$in: newIgfs.clusters}}, {$pull: {igfss: igfsId}}).exec()
+                .then(() => igfsModel.create(newIgfs))
+                .then((clone) => clustersModel.updateMany({_id: {$in: newIgfs.clusters}}, {$addToSet: {igfss: clone._id}}).exec())
+                .catch((err) => error(`Failed to clone IGFS: id=${igfsId}, name=${igfs.name}]`, err));
+        }
+
+        return igfsModel.updateOne({_id: igfsId}, {clusters: [cluster]}).exec();
+    }), Promise.resolve());
+}
+
+function migrateIgfs(clustersModel, igfsModel, igfs) {
+    const clustersCnt = _.size(igfs.clusters);
+
+    if (clustersCnt < 1) {
+        if (_debug)
+            log(`Found IGFS not linked to cluster [IGFS=${igfs.name}]`);
+
+        return getClusterForMigration(clustersModel, igfs.space)
+            .then((clusterLostFound) => linkIgfsToCluster(clustersModel, clusterLostFound, igfsModel, igfs));
+    }
+
+    if (clustersCnt > 1) {
+        if (_debug)
+            log(`Found IGFS linked to many clusters [IGFS=${igfs.name}, clustersCnt=${clustersCnt}]`);
+
+        return cloneIgfs(clustersModel, igfsModel, igfs);
+    }
+
+    // Nothing to migrate, IGFS linked to cluster 1-to-1.
+    return Promise.resolve();
+}
+
+function migrateIgfss(clustersModel, igfsModel) {
+    return igfsModel.find({}).lean().exec()
+        .then((igfss) => {
+            const igfsCnt = _.size(igfss);
+
+            if (igfsCnt > 0) {
+                log(`IGFS to migrate: ${igfsCnt}`);
+
+                return _.reduce(igfss, (start, igfs) => start.then(() => migrateIgfs(clustersModel, igfsModel, igfs)), Promise.resolve())
+                    .then(() => log('IGFS migration finished.'));
+            }
+
+            return Promise.resolve();
+        })
+        .catch((err) => error('IGFS migration failed', err));
+}
+
+function linkDomainToCluster(clustersModel, cluster, domainsModel, domain) {
+    return clustersModel.updateOne({_id: cluster._id}, {$addToSet: {models: domain._id}}).exec()
+        .then(() => domainsModel.updateOne({_id: domain._id}, {clusters: [cluster._id]}).exec())
+        .catch((err) => error(`Failed link domain model to cluster [domain=${domain._id}, cluster=${cluster.name}]`, err));
+}
+
+function linkDomainToCache(cachesModel, cache, domainsModel, domain) {
+    return cachesModel.updateOne({_id: cache._id}, {$addToSet: {domains: domain._id}}).exec()
+        .then(() => domainsModel.updateOne({_id: domain._id}, {caches: [cache._id]}).exec())
+        .catch((err) => error(`Failed link domain model to cache [cache=${cache.name}, domain=${domain._id}]`, err));
+}
+
+function migrateDomain(clustersModel, cachesModel, domainsModel, domain) {
+    const cachesCnt = _.size(domain.caches);
+
+    if (cachesCnt < 1) {
+        if (_debug)
+            log(`Found domain model not linked to cache [domain=${domain._id}]`);
+
+        return getClusterForMigration(clustersModel, domain.space)
+            .then((clusterLostFound) => linkDomainToCluster(clustersModel, clusterLostFound, domainsModel, domain))
+            .then(() => getCacheForMigration(clustersModel, cachesModel, domain.space))
+            .then((cacheLostFound) => linkDomainToCache(cachesModel, cacheLostFound, domainsModel, domain))
+            .catch((err) => error(`Failed to migrate not linked domain [domain=${domain._id}]`, err));
+    }
+
+    if (_.isEmpty(domain.clusters)) {
+        const cachesCnt = _.size(domain.caches);
+
+        if (_debug)
+            log(`Found domain model without cluster: [domain=${domain._id}, cachesCnt=${cachesCnt}]`);
+
+        const grpByClusters = {};
+
+        return cachesModel.find({_id: {$in: domain.caches}}).lean().exec()
+            .then((caches) => {
+                if (caches) {
+                    _.forEach(caches, (cache) => {
+                        const c = _.get(grpByClusters, cache.clusters[0]);
+
+                        if (c)
+                            c.push(cache._id);
+                        else
+                            grpByClusters[cache.clusters[0]] = [cache._id];
+                    });
+
+                    return _.reduce(_.keys(grpByClusters), (start, cluster, idx) => start.then(() => {
+                        const domainId = domain._id;
+
+                        const clusterCaches = grpByClusters[cluster];
+
+                        if (idx > 0) {
+                            delete domain._id;
+                            domain.caches = clusterCaches;
+
+                            return domainsModel.create(domain)
+                                .then((clonedDomain) => {
+                                    return cachesModel.updateOne({_id: {$in: clusterCaches}}, {$addToSet: {domains: clonedDomain._id}}).exec()
+                                        .then(() => clonedDomain);
+                                })
+                                .then((clonedDomain) => linkDomainToCluster(clustersModel, {_id: cluster, name: `stub${idx}`}, domainsModel, clonedDomain))
+                                .then(() => {
+                                    return cachesModel.updateMany({_id: {$in: clusterCaches}}, {$pull: {domains: domainId}}).exec();
+                                });
+                        }
+
+                        return domainsModel.updateOne({_id: domainId}, {caches: clusterCaches}).exec()
+                            .then(() => linkDomainToCluster(clustersModel, {_id: cluster, name: `stub${idx}`}, domainsModel, domain));
+                    }), Promise.resolve());
+                }
+
+                error(`Found domain with orphaned caches: [domain=${domain._id}, caches=${domain.caches}]`);
+
+                return Promise.resolve();
+            })
+            .catch((err) => error(`Failed to migrate domain [domain=${domain._id}]`, err));
+    }
+
+    // Nothing to migrate, other domains will be migrated with caches.
+    return Promise.resolve();
+}
+
+function migrateDomains(clustersModel, cachesModel, domainsModel) {
+    return domainsModel.find({}).lean().exec()
+        .then((domains) => {
+            const domainsCnt = _.size(domains);
+
+            if (domainsCnt > 0) {
+                log(`Domain models to migrate: ${domainsCnt}`);
+
+                return _.reduce(domains, (start, domain) => start.then(() => migrateDomain(clustersModel, cachesModel, domainsModel, domain)), Promise.resolve())
+                    .then(() => log('Domain models migration finished.'));
+            }
+
+            return Promise.resolve();
+        })
+        .catch((err) => error('Domain models migration failed', err));
+}
+
+function deduplicate(title, model, name) {
+    return model.find({}).lean().exec()
+        .then((items) => {
+            const sz = _.size(items);
+
+            if (sz > 0) {
+                log(`Deduplication of ${title} started...`);
+
+                let cnt = 0;
+
+                return _.reduce(items, (start, item) => start.then(() => {
+                    const data = item[name];
+
+                    const dataSz = _.size(data);
+
+                    if (dataSz < 2)
+                        return Promise.resolve();
+
+                    const deduped = _.uniqWith(data, _.isEqual);
+
+                    if (dataSz !== _.size(deduped)) {
+                        return model.updateOne({_id: item._id}, {$set: {[name]: deduped}})
+                            .then(() => cnt++);
+                    }
+
+                    return Promise.resolve();
+                }), Promise.resolve())
+                    .then(() => log(`Deduplication of ${title} finished: ${cnt}.`));
+            }
+
+            return Promise.resolve();
+        });
+}
+
+exports.up = function up(done) {
+    const clustersModel = this('Cluster');
+    const cachesModel = this('Cache');
+    const domainsModel = this('DomainModel');
+    const igfsModel = this('Igfs');
+
+    process.on('unhandledRejection', function(reason, p) {
+        console.log('Unhandled rejection at:', p, 'reason:', reason);
+    });
+
+    Promise.resolve()
+        .then(() => deduplicate('Cluster caches', clustersModel, 'caches'))
+        .then(() => deduplicate('Cluster IGFS', clustersModel, 'igfss'))
+        .then(() => deduplicate('Cache clusters', cachesModel, 'clusters'))
+        .then(() => deduplicate('Cache domains', cachesModel, 'domains'))
+        .then(() => deduplicate('IGFS clusters', igfsModel, 'clusters'))
+        .then(() => deduplicate('Domain model caches', domainsModel, 'caches'))
+        .then(() => migrateCaches(clustersModel, cachesModel, domainsModel))
+        .then(() => migrateIgfss(clustersModel, igfsModel))
+        .then(() => migrateDomains(clustersModel, cachesModel, domainsModel))
+        .then(() => log(`Duplicates counter: ${dup}`))
+        .then(() => done())
+        .catch(done);
+};
+
+exports.down = function down(done) {
+    log('Model migration can not be reverted');
+
+    done();
+};
diff --git a/modules/backend/migrations/1547440382485-account-make-email-unique.js b/modules/backend/migrations/1547440382485-account-make-email-unique.js
new file mode 100644
index 0000000..3a6e453
--- /dev/null
+++ b/modules/backend/migrations/1547440382485-account-make-email-unique.js
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+const _ = require('lodash');
+
+const log = require('./migration-utils').log;
+
+function deduplicateAccounts(model) {
+    const accountsModel = model('Account');
+    const spaceModel = model('Space');
+
+    return accountsModel.aggregate([
+        {$group: {_id: '$email', count: {$sum: 1}}},
+        {$match: {count: {$gt: 1}}}
+    ]).exec()
+        .then((accounts) => _.map(accounts, '_id'))
+        .then((emails) => Promise.all(
+            _.map(emails, (email) => accountsModel.find({email}, {_id: 1, email: 1, lastActivity: 1, lastLogin: 1}).lean().exec())
+        ))
+        .then((promises) => {
+            const duplicates = _.flatMap(promises, (accounts) => _.sortBy(accounts, [(a) => a.lastActivity || '', 'lastLogin']).slice(0, -1));
+
+            if (_.isEmpty(duplicates))
+                log('Duplicates not found!');
+            else {
+                log(`Duplicates found: ${_.size(duplicates)}`);
+
+                _.forEach(duplicates, (dup) => log(`  ID: ${dup._id}, e-mail: ${dup.email}`));
+            }
+
+            return _.map(duplicates, '_id');
+        })
+        .then((accountIds) => {
+            if (_.isEmpty(accountIds))
+                return Promise.resolve();
+
+            return spaceModel.find({owner: {$in: accountIds}}, {_id: 1}).lean().exec()
+                .then((spaces) => _.map(spaces, '_id'))
+                .then((spaceIds) =>
+                    Promise.all([
+                        model('Cluster').deleteMany({space: {$in: spaceIds}}).exec(),
+                        model('Cache').deleteMany({space: {$in: spaceIds}}).exec(),
+                        model('DomainModel').deleteMany({space: {$in: spaceIds}}).exec(),
+                        model('Igfs').deleteMany({space: {$in: spaceIds}}).exec(),
+                        model('Notebook').deleteMany({space: {$in: spaceIds}}).exec(),
+                        model('Activities').deleteMany({owner: accountIds}).exec(),
+                        model('Notifications').deleteMany({owner: accountIds}).exec(),
+                        spaceModel.deleteMany({owner: accountIds}).exec(),
+                        accountsModel.deleteMany({_id: accountIds}).exec()
+                    ])
+                )
+                .then(() => {
+                    const conditions = _.map(accountIds, (accountId) => ({session: {$regex: `"${accountId}"`}}));
+
+                    return accountsModel.db.collection('sessions').deleteMany({$or: conditions});
+                });
+        });
+}
+
+exports.up = function up(done) {
+    deduplicateAccounts((name) => this(name))
+        .then(() => this('Account').collection.createIndex({email: 1}, {unique: true, background: false}))
+        .then(() => done())
+        .catch(done);
+};
+
+exports.down = function down(done) {
+    log('Account migration can not be reverted');
+
+    done();
+};
diff --git a/modules/backend/migrations/README.txt b/modules/backend/migrations/README.txt
new file mode 100644
index 0000000..e907fad
--- /dev/null
+++ b/modules/backend/migrations/README.txt
@@ -0,0 +1,4 @@
+Ignite Web Console
+======================================
+
+This folder contains scripts for model migration.
diff --git a/modules/backend/migrations/migration-utils.js b/modules/backend/migrations/migration-utils.js
new file mode 100644
index 0000000..81c9095
--- /dev/null
+++ b/modules/backend/migrations/migration-utils.js
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+function log(msg) {
+    console.log(`[${new Date().toISOString()}] [INFO ] ${msg}`);
+}
+
+function error(msg, err) {
+    console.log(`[${new Date().toISOString()}] [ERROR] ${msg}.` + (err ? ` Error: ${err}` : ''));
+}
+
+function recreateIndex0(done, model, oldIdxName, oldIdx, newIdx) {
+    return model.indexExists(oldIdxName)
+        .then((exists) => {
+            if (exists) {
+                return model.dropIndex(oldIdx)
+                    .then(() => model.createIndex(newIdx, {unique: true, background: false}));
+            }
+        })
+        .then(() => done())
+        .catch((err) => {
+            if (err.code === 12587) {
+                log(`Background operation in progress for: ${oldIdxName}, will retry in 3 seconds.`);
+
+                setTimeout(() => recreateIndex0(done, model, oldIdxName, oldIdx, newIdx), 3000);
+            }
+            else {
+                log(`Failed to recreate index: ${err}`);
+
+                done();
+            }
+        });
+}
+
+function recreateIndex(done, model, oldIdxName, oldIdx, newIdx) {
+    setTimeout(() => recreateIndex0(done, model, oldIdxName, oldIdx, newIdx), 1000);
+}
+
+const LOST_AND_FOUND = 'LOST_AND_FOUND';
+
+function getClusterForMigration(clustersModel, space) {
+    return clustersModel.findOne({space, name: LOST_AND_FOUND}).lean().exec()
+        .then((cluster) => {
+            if (cluster)
+                return cluster;
+
+            return clustersModel.create({
+                space,
+                name: LOST_AND_FOUND,
+                connector: {noDelay: true},
+                communication: {tcpNoDelay: true},
+                igfss: [],
+                caches: [],
+                binaryConfiguration: {
+                    compactFooter: true,
+                    typeConfigurations: []
+                },
+                discovery: {
+                    kind: 'Multicast',
+                    Multicast: {addresses: ['127.0.0.1:47500..47510']},
+                    Vm: {addresses: ['127.0.0.1:47500..47510']}
+                }
+            });
+        });
+}
+
+function getCacheForMigration(clustersModel, cachesModel, space) {
+    return cachesModel.findOne({space, name: LOST_AND_FOUND})
+        .then((cache) => {
+            if (cache)
+                return cache;
+
+            return getClusterForMigration(clustersModel, space)
+                .then((cluster) => {
+                    return cachesModel.create({
+                        space,
+                        name: LOST_AND_FOUND,
+                        clusters: [cluster._id],
+                        domains: [],
+                        cacheMode: 'PARTITIONED',
+                        atomicityMode: 'ATOMIC',
+                        readFromBackup: true,
+                        copyOnRead: true,
+                        readThrough: false,
+                        writeThrough: false,
+                        sqlFunctionClasses: [],
+                        writeBehindCoalescing: true,
+                        cacheStoreFactory: {
+                            CacheHibernateBlobStoreFactory: {hibernateProperties: []},
+                            CacheJdbcBlobStoreFactory: {connectVia: 'DataSource'}
+                        },
+                        nearConfiguration: {},
+                        evictionPolicy: {}
+                    });
+                })
+                .then((cache) => {
+                    return clustersModel.updateOne({_id: cache.clusters[0]}, {$addToSet: {caches: cache._id}}).exec()
+                        .then(() => cache);
+                });
+        });
+}
+
+module.exports = {
+    log,
+    error,
+    recreateIndex,
+    getClusterForMigration,
+    getCacheForMigration
+};
+
+
+
+
diff --git a/modules/backend/package-lock.json b/modules/backend/package-lock.json
new file mode 100644
index 0000000..28051fa
--- /dev/null
+++ b/modules/backend/package-lock.json
@@ -0,0 +1,8115 @@
+{
+  "name": "ignite-web-console",
+  "version": "8.7.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.0.0"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      },
+      "dependencies": {
+        "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==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.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"
+          }
+        },
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "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==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "@babel/parser": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz",
+      "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA=="
+    },
+    "@mrmlnc/readdir-enhanced": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+      "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+      "requires": {
+        "call-me-maybe": "^1.0.1",
+        "glob-to-regexp": "^0.3.0"
+      }
+    },
+    "@nodelib/fs.stat": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+      "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
+    },
+    "accepts": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "requires": {
+        "mime-types": "~2.1.18",
+        "negotiator": "0.6.1"
+      }
+    },
+    "acorn": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
+      "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
+      "dev": true
+    },
+    "acorn-jsx": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+      "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+      "dev": true
+    },
+    "after": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
+    },
+    "agent-base": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+      "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+      "dev": true,
+      "requires": {
+        "es6-promisify": "^5.0.0"
+      }
+    },
+    "ajv": {
+      "version": "6.10.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
+      "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
+      "requires": {
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ansi-colors": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
+      "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
+      "dev": true
+    },
+    "ansi-escapes": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+      "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4="
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+    },
+    "ansi-styles": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+    },
+    "anymatch": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+      "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+      "optional": true,
+      "requires": {
+        "micromatch": "^2.1.5",
+        "normalize-path": "^2.0.0"
+      }
+    },
+    "app-module-path": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz",
+      "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU="
+    },
+    "archetype": {
+      "version": "0.8.8",
+      "resolved": "https://registry.npmjs.org/archetype/-/archetype-0.8.8.tgz",
+      "integrity": "sha512-isdIbFfT3zXVan34hmxIwI8A5/8lo9MaYmwXF1iYWCnJS1GvKKnZ4GrXoOUgKdUMCiB/wdguRXeStCUQhFjexg==",
+      "requires": {
+        "lodash.clonedeep": "4.x",
+        "lodash.set": "4.x",
+        "lodash.unset": "4.x",
+        "mpath": "0.5.1",
+        "standard-error": "1.1.0"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "arr-diff": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+      "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+      "optional": true,
+      "requires": {
+        "arr-flatten": "^1.0.1"
+      }
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
+    },
+    "arr-union": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+    },
+    "array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+    },
+    "array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "requires": {
+        "array-uniq": "^1.0.1"
+      }
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+    },
+    "array-unique": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+      "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+      "optional": true
+    },
+    "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=="
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+    },
+    "assertion-error": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+      "dev": true
+    },
+    "assign-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+    },
+    "astral-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+      "dev": true
+    },
+    "async": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
+      "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
+      "requires": {
+        "lodash": "^4.17.10"
+      }
+    },
+    "async-each": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+      "optional": true
+    },
+    "async-limiter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+    },
+    "atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+    },
+    "aws4": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+    },
+    "babel-cli": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz",
+      "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=",
+      "requires": {
+        "babel-core": "^6.26.0",
+        "babel-polyfill": "^6.26.0",
+        "babel-register": "^6.26.0",
+        "babel-runtime": "^6.26.0",
+        "chokidar": "^1.6.1",
+        "commander": "^2.11.0",
+        "convert-source-map": "^1.5.0",
+        "fs-readdir-recursive": "^1.0.0",
+        "glob": "^7.1.2",
+        "lodash": "^4.17.4",
+        "output-file-sync": "^1.1.2",
+        "path-is-absolute": "^1.0.1",
+        "slash": "^1.0.0",
+        "source-map": "^0.5.6",
+        "v8flags": "^2.1.1"
+      }
+    },
+    "babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "requires": {
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
+      }
+    },
+    "babel-core": {
+      "version": "6.26.3",
+      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
+      "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
+      "requires": {
+        "babel-code-frame": "^6.26.0",
+        "babel-generator": "^6.26.0",
+        "babel-helpers": "^6.24.1",
+        "babel-messages": "^6.23.0",
+        "babel-register": "^6.26.0",
+        "babel-runtime": "^6.26.0",
+        "babel-template": "^6.26.0",
+        "babel-traverse": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "convert-source-map": "^1.5.1",
+        "debug": "^2.6.9",
+        "json5": "^0.5.1",
+        "lodash": "^4.17.4",
+        "minimatch": "^3.0.4",
+        "path-is-absolute": "^1.0.1",
+        "private": "^0.1.8",
+        "slash": "^1.0.0",
+        "source-map": "^0.5.7"
+      },
+      "dependencies": {
+        "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"
+          }
+        }
+      }
+    },
+    "babel-generator": {
+      "version": "6.26.1",
+      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+      "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+      "requires": {
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "detect-indent": "^4.0.0",
+        "jsesc": "^1.3.0",
+        "lodash": "^4.17.4",
+        "source-map": "^0.5.7",
+        "trim-right": "^1.0.1"
+      }
+    },
+    "babel-helper-builder-binary-assignment-operator-visitor": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+      "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+      "requires": {
+        "babel-helper-explode-assignable-expression": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-call-delegate": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+      "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+      "requires": {
+        "babel-helper-hoist-variables": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-define-map": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+      "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+      "requires": {
+        "babel-helper-function-name": "^6.24.1",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-helper-explode-assignable-expression": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+      "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-function-name": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+      "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+      "requires": {
+        "babel-helper-get-function-arity": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-get-function-arity": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+      "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-hoist-variables": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+      "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-optimise-call-expression": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+      "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-regex": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+      "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-helper-remap-async-to-generator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
+      "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
+      "requires": {
+        "babel-helper-function-name": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-replace-supers": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+      "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+      "requires": {
+        "babel-helper-optimise-call-expression": "^6.24.1",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helpers": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+      "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-messages": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-check-es2015-constants": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+      "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-syntax-async-functions": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+      "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
+    },
+    "babel-plugin-syntax-exponentiation-operator": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+      "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4="
+    },
+    "babel-plugin-syntax-trailing-function-commas": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
+      "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="
+    },
+    "babel-plugin-transform-async-to-generator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
+      "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
+      "requires": {
+        "babel-helper-remap-async-to-generator": "^6.24.1",
+        "babel-plugin-syntax-async-functions": "^6.8.0",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-arrow-functions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+      "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoped-functions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+      "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoping": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+      "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-template": "^6.26.0",
+        "babel-traverse": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-plugin-transform-es2015-classes": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+      "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+      "requires": {
+        "babel-helper-define-map": "^6.24.1",
+        "babel-helper-function-name": "^6.24.1",
+        "babel-helper-optimise-call-expression": "^6.24.1",
+        "babel-helper-replace-supers": "^6.24.1",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-computed-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+      "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-destructuring": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+      "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-duplicate-keys": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+      "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-for-of": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+      "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-function-name": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+      "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+      "requires": {
+        "babel-helper-function-name": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-literals": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+      "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-amd": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+      "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+      "requires": {
+        "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-commonjs": {
+      "version": "6.26.2",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
+      "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==",
+      "requires": {
+        "babel-plugin-transform-strict-mode": "^6.24.1",
+        "babel-runtime": "^6.26.0",
+        "babel-template": "^6.26.0",
+        "babel-types": "^6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-systemjs": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+      "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+      "requires": {
+        "babel-helper-hoist-variables": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-umd": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+      "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+      "requires": {
+        "babel-plugin-transform-es2015-modules-amd": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-object-super": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+      "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+      "requires": {
+        "babel-helper-replace-supers": "^6.24.1",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-parameters": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+      "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+      "requires": {
+        "babel-helper-call-delegate": "^6.24.1",
+        "babel-helper-get-function-arity": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-shorthand-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+      "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-spread": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+      "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-sticky-regex": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+      "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+      "requires": {
+        "babel-helper-regex": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-template-literals": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+      "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-typeof-symbol": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+      "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-unicode-regex": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+      "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+      "requires": {
+        "babel-helper-regex": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "regexpu-core": "^2.0.0"
+      }
+    },
+    "babel-plugin-transform-exponentiation-operator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+      "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+      "requires": {
+        "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1",
+        "babel-plugin-syntax-exponentiation-operator": "^6.8.0",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-regenerator": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+      "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+      "requires": {
+        "regenerator-transform": "^0.10.0"
+      }
+    },
+    "babel-plugin-transform-runtime": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
+      "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-strict-mode": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+      "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-polyfill": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
+      "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "core-js": "^2.5.0",
+        "regenerator-runtime": "^0.10.5"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.10.5",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+          "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
+        }
+      }
+    },
+    "babel-preset-es2015": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+      "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+      "requires": {
+        "babel-plugin-check-es2015-constants": "^6.22.0",
+        "babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
+        "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
+        "babel-plugin-transform-es2015-block-scoping": "^6.24.1",
+        "babel-plugin-transform-es2015-classes": "^6.24.1",
+        "babel-plugin-transform-es2015-computed-properties": "^6.24.1",
+        "babel-plugin-transform-es2015-destructuring": "^6.22.0",
+        "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1",
+        "babel-plugin-transform-es2015-for-of": "^6.22.0",
+        "babel-plugin-transform-es2015-function-name": "^6.24.1",
+        "babel-plugin-transform-es2015-literals": "^6.22.0",
+        "babel-plugin-transform-es2015-modules-amd": "^6.24.1",
+        "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
+        "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1",
+        "babel-plugin-transform-es2015-modules-umd": "^6.24.1",
+        "babel-plugin-transform-es2015-object-super": "^6.24.1",
+        "babel-plugin-transform-es2015-parameters": "^6.24.1",
+        "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
+        "babel-plugin-transform-es2015-spread": "^6.22.0",
+        "babel-plugin-transform-es2015-sticky-regex": "^6.24.1",
+        "babel-plugin-transform-es2015-template-literals": "^6.22.0",
+        "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0",
+        "babel-plugin-transform-es2015-unicode-regex": "^6.24.1",
+        "babel-plugin-transform-regenerator": "^6.24.1"
+      }
+    },
+    "babel-preset-es2016": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz",
+      "integrity": "sha1-+QC/k+LrwNJ235uKtZck6/2Vn4s=",
+      "requires": {
+        "babel-plugin-transform-exponentiation-operator": "^6.24.1"
+      }
+    },
+    "babel-preset-es2017": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz",
+      "integrity": "sha1-WXvq37n38gi8/YoS6bKym4svFNE=",
+      "requires": {
+        "babel-plugin-syntax-trailing-function-commas": "^6.22.0",
+        "babel-plugin-transform-async-to-generator": "^6.24.1"
+      }
+    },
+    "babel-preset-latest": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-latest/-/babel-preset-latest-6.24.1.tgz",
+      "integrity": "sha1-Z33gaRVKdIXC0lxXfAL2JLhbheg=",
+      "requires": {
+        "babel-preset-es2015": "^6.24.1",
+        "babel-preset-es2016": "^6.24.1",
+        "babel-preset-es2017": "^6.24.1"
+      }
+    },
+    "babel-register": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+      "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+      "requires": {
+        "babel-core": "^6.26.0",
+        "babel-runtime": "^6.26.0",
+        "core-js": "^2.5.0",
+        "home-or-tmp": "^2.0.0",
+        "lodash": "^4.17.4",
+        "mkdirp": "^0.5.1",
+        "source-map-support": "^0.4.15"
+      }
+    },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "babel-template": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-traverse": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-traverse": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+      "requires": {
+        "babel-code-frame": "^6.26.0",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "debug": "^2.6.8",
+        "globals": "^9.18.0",
+        "invariant": "^2.2.2",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-types": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "esutils": "^2.0.2",
+        "lodash": "^4.17.4",
+        "to-fast-properties": "^1.0.3"
+      }
+    },
+    "babylon": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+      "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
+    },
+    "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="
+    },
+    "base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "requires": {
+        "cache-base": "^1.0.1",
+        "class-utils": "^0.3.5",
+        "component-emitter": "^1.2.1",
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.1",
+        "mixin-deep": "^1.2.0",
+        "pascalcase": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        },
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        },
+        "kind-of": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+        }
+      }
+    },
+    "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.3.0",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
+      "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="
+    },
+    "base64id": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY="
+    },
+    "basic-auth": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+      "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+      "requires": {
+        "safe-buffer": "5.1.2"
+      }
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "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"
+      }
+    },
+    "binary-extensions": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+      "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+      "optional": true
+    },
+    "bl": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+      "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
+      "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.5.4",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz",
+      "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw=="
+    },
+    "body-parser": {
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+      "requires": {
+        "bytes": "3.1.0",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "on-finished": "~2.3.0",
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
+      }
+    },
+    "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"
+      }
+    },
+    "braces": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+      "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+      "optional": true,
+      "requires": {
+        "expand-range": "^1.8.1",
+        "preserve": "^0.2.0",
+        "repeat-element": "^1.1.2"
+      }
+    },
+    "browser-stdout": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+      "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+      "dev": true
+    },
+    "bson": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz",
+      "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg=="
+    },
+    "buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+      "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+      "requires": {
+        "base64-js": "^1.0.2",
+        "ieee754": "^1.1.4"
+      }
+    },
+    "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==",
+      "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=="
+    },
+    "buffer-crc32": {
+      "version": "0.2.13",
+      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
+    },
+    "buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
+    },
+    "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=="
+    },
+    "byline": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
+      "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE="
+    },
+    "bytes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+    },
+    "cache-base": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+      "requires": {
+        "collection-visit": "^1.0.0",
+        "component-emitter": "^1.2.1",
+        "get-value": "^2.0.6",
+        "has-value": "^1.0.0",
+        "isobject": "^3.0.1",
+        "set-value": "^2.0.0",
+        "to-object-path": "^0.3.0",
+        "union-value": "^1.0.0",
+        "unset-value": "^1.0.0"
+      },
+      "dependencies": {
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        }
+      }
+    },
+    "call-me-maybe": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
+      "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms="
+    },
+    "callsite": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+      "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
+    },
+    "callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true
+    },
+    "camelcase": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+      "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+    },
+    "chai": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
+      "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
+      "dev": true,
+      "requires": {
+        "assertion-error": "^1.1.0",
+        "check-error": "^1.0.2",
+        "deep-eql": "^3.0.1",
+        "get-func-name": "^2.0.0",
+        "pathval": "^1.1.0",
+        "type-detect": "^4.0.5"
+      }
+    },
+    "chalk": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+      "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+      "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"
+      }
+    },
+    "chardet": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+      "dev": true
+    },
+    "check-error": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+      "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+      "dev": true
+    },
+    "chokidar": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+      "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+      "optional": true,
+      "requires": {
+        "anymatch": "^1.3.0",
+        "async-each": "^1.0.0",
+        "fsevents": "^1.0.0",
+        "glob-parent": "^2.0.0",
+        "inherits": "^2.0.1",
+        "is-binary-path": "^1.0.0",
+        "is-glob": "^2.0.0",
+        "path-is-absolute": "^1.0.0",
+        "readdirp": "^2.0.0"
+      }
+    },
+    "class-utils": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+      "requires": {
+        "arr-union": "^3.1.0",
+        "define-property": "^0.2.5",
+        "isobject": "^3.0.0",
+        "static-extend": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        }
+      }
+    },
+    "cli-cursor": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+      "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+      "requires": {
+        "restore-cursor": "^1.0.1"
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
+    },
+    "cliui": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+      "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+      "requires": {
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wrap-ansi": "^2.0.0"
+      }
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+    },
+    "collection-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+      "requires": {
+        "map-visit": "^1.0.0",
+        "object-visit": "^1.0.0"
+      }
+    },
+    "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.3.3",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
+      "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="
+    },
+    "combined-stream": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "commander": {
+      "version": "2.20.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
+    },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "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.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+    },
+    "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="
+    },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "connect-mongodb-session": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/connect-mongodb-session/-/connect-mongodb-session-2.1.1.tgz",
+      "integrity": "sha512-k8NF+C32tJZuR3sSFfdz56e1NKzxejWlD/X5PVYBIZQ8/dzqkMGTKxcdGXsBreU5M48WZ+vYGrJSruSRTzFu4Q==",
+      "requires": {
+        "archetype": "0.8.x",
+        "mongodb": "~3.1.8"
+      }
+    },
+    "content-disposition": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+    },
+    "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=="
+    },
+    "convert-source-map": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
+      "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
+      "requires": {
+        "safe-buffer": "~5.1.1"
+      }
+    },
+    "cookie": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+    },
+    "cookie-parser": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz",
+      "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==",
+      "requires": {
+        "cookie": "0.3.1",
+        "cookie-signature": "1.0.6"
+      }
+    },
+    "cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+    },
+    "cookiejar": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
+      "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==",
+      "dev": true
+    },
+    "copy-descriptor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+    },
+    "core-js": {
+      "version": "2.6.5",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
+      "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
+    },
+    "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="
+    },
+    "cross-env": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz",
+      "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^6.0.5",
+        "is-windows": "^1.0.0"
+      }
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dev": true,
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+    },
+    "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="
+    },
+    "decompress": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
+      "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
+      "requires": {
+        "decompress-tar": "^4.0.0",
+        "decompress-tarbz2": "^4.0.0",
+        "decompress-targz": "^4.0.0",
+        "decompress-unzip": "^4.0.1",
+        "graceful-fs": "^4.1.10",
+        "make-dir": "^1.0.0",
+        "pify": "^2.3.0",
+        "strip-dirs": "^2.0.0"
+      }
+    },
+    "decompress-tar": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
+      "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
+      "requires": {
+        "file-type": "^5.2.0",
+        "is-stream": "^1.1.0",
+        "tar-stream": "^1.5.2"
+      }
+    },
+    "decompress-tarbz2": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
+      "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
+      "requires": {
+        "decompress-tar": "^4.1.0",
+        "file-type": "^6.1.0",
+        "is-stream": "^1.1.0",
+        "seek-bzip": "^1.0.5",
+        "unbzip2-stream": "^1.0.9"
+      },
+      "dependencies": {
+        "file-type": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
+          "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg=="
+        }
+      }
+    },
+    "decompress-targz": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
+      "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
+      "requires": {
+        "decompress-tar": "^4.1.1",
+        "file-type": "^5.2.0",
+        "is-stream": "^1.1.0"
+      }
+    },
+    "decompress-unzip": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
+      "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
+      "requires": {
+        "file-type": "^3.8.0",
+        "get-stream": "^2.2.0",
+        "pify": "^2.3.0",
+        "yauzl": "^2.4.2"
+      },
+      "dependencies": {
+        "file-type": {
+          "version": "3.9.0",
+          "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+          "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
+        }
+      }
+    },
+    "dedent": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+      "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
+      "dev": true
+    },
+    "deep-eql": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+      "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+      "dev": true,
+      "requires": {
+        "type-detect": "^4.0.0"
+      }
+    },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
+    },
+    "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"
+      }
+    },
+    "define-property": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+      "requires": {
+        "is-descriptor": "^1.0.2",
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        },
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        },
+        "kind-of": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+        }
+      }
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+    },
+    "detect-indent": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+      "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+      "requires": {
+        "repeating": "^2.0.0"
+      }
+    },
+    "diff": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
+    },
+    "dir-glob": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
+      "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
+      "requires": {
+        "arrify": "^1.0.1",
+        "path-type": "^3.0.0"
+      },
+      "dependencies": {
+        "path-type": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+          "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+          "requires": {
+            "pify": "^3.0.0"
+          }
+        },
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+        }
+      }
+    },
+    "doctrine": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "dev": true,
+      "requires": {
+        "esutils": "^2.0.2"
+      }
+    },
+    "dotenv": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz",
+      "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow=="
+    },
+    "ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "requires": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+    },
+    "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
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+    },
+    "end-of-stream": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "engine.io": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
+      "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+      "requires": {
+        "accepts": "~1.3.4",
+        "base64id": "1.0.0",
+        "cookie": "0.3.1",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.0",
+        "ws": "~3.3.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"
+          }
+        }
+      }
+    },
+    "engine.io-client": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
+      "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+      "requires": {
+        "component-emitter": "1.2.1",
+        "component-inherit": "0.0.3",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.1",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "ws": "~3.3.1",
+        "xmlhttprequest-ssl": "~1.5.4",
+        "yeast": "0.1.2"
+      },
+      "dependencies": {
+        "component-emitter": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "engine.io-parser": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
+      "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+      "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==",
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es-abstract": {
+      "version": "1.13.0",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+      "dev": true,
+      "requires": {
+        "es-to-primitive": "^1.2.0",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "is-callable": "^1.1.4",
+        "is-regex": "^1.0.4",
+        "object-keys": "^1.0.12"
+      }
+    },
+    "es-to-primitive": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+      "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+      "dev": true,
+      "requires": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      }
+    },
+    "es6-promise": {
+      "version": "4.2.6",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
+      "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==",
+      "dev": true
+    },
+    "es6-promisify": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+      "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+      "dev": true,
+      "requires": {
+        "es6-promise": "^4.0.3"
+      }
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+    },
+    "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="
+    },
+    "escodegen": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz",
+      "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==",
+      "requires": {
+        "esprima": "^3.1.3",
+        "estraverse": "^4.2.0",
+        "esutils": "^2.0.2",
+        "optionator": "^0.8.1",
+        "source-map": "~0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "optional": true
+        }
+      }
+    },
+    "eslint": {
+      "version": "5.16.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz",
+      "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "ajv": "^6.9.1",
+        "chalk": "^2.1.0",
+        "cross-spawn": "^6.0.5",
+        "debug": "^4.0.1",
+        "doctrine": "^3.0.0",
+        "eslint-scope": "^4.0.3",
+        "eslint-utils": "^1.3.1",
+        "eslint-visitor-keys": "^1.0.0",
+        "espree": "^5.0.1",
+        "esquery": "^1.0.1",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^5.0.1",
+        "functional-red-black-tree": "^1.0.1",
+        "glob": "^7.1.2",
+        "globals": "^11.7.0",
+        "ignore": "^4.0.6",
+        "import-fresh": "^3.0.0",
+        "imurmurhash": "^0.1.4",
+        "inquirer": "^6.2.2",
+        "js-yaml": "^3.13.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.3.0",
+        "lodash": "^4.17.11",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.8.2",
+        "path-is-inside": "^1.0.2",
+        "progress": "^2.0.0",
+        "regexpp": "^2.0.1",
+        "semver": "^5.5.1",
+        "strip-ansi": "^4.0.0",
+        "strip-json-comments": "^2.0.1",
+        "table": "^5.2.3",
+        "text-table": "^0.2.0"
+      },
+      "dependencies": {
+        "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": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "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==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.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"
+          }
+        },
+        "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"
+          }
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "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"
+          }
+        },
+        "globals": {
+          "version": "11.11.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz",
+          "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==",
+          "dev": true
+        },
+        "ignore": {
+          "version": "4.0.6",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+          "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+          "dev": true
+        },
+        "inquirer": {
+          "version": "6.3.1",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz",
+          "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==",
+          "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.11",
+            "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": {
+            "ansi-regex": {
+              "version": "4.1.0",
+              "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+              "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+              "dev": true
+            },
+            "strip-ansi": {
+              "version": "5.2.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+              "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^4.1.0"
+              }
+            }
+          }
+        },
+        "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
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "run-async": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+          "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+          "dev": true,
+          "requires": {
+            "is-promise": "^2.1.0"
+          }
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "eslint-formatter-friendly": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-formatter-friendly/-/eslint-formatter-friendly-6.0.0.tgz",
+      "integrity": "sha512-fOBwGn2r8BPQ1KSKyVzjXP8VFxJ2tWKxxn2lIF+k1ezN/pFB44HDlrn5kBm1vxbyyRa/LC+1vHJwc7WETUAZ2Q==",
+      "dev": true,
+      "requires": {
+        "babel-code-frame": "6.26.0",
+        "chalk": "^2.0.1",
+        "extend": "^3.0.0",
+        "strip-ansi": "^4.0.0",
+        "text-table": "^0.2.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
+        },
+        "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==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.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"
+          }
+        },
+        "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"
+          }
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "eslint-scope": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+      "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "eslint-utils": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
+      "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
+      "dev": true
+    },
+    "eslint-visitor-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+      "dev": true
+    },
+    "espree": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
+      "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==",
+      "dev": true,
+      "requires": {
+        "acorn": "^6.0.7",
+        "acorn-jsx": "^5.0.0",
+        "eslint-visitor-keys": "^1.0.0"
+      }
+    },
+    "esprima": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+      "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
+    },
+    "esquery": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
+      "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.0.0"
+      }
+    },
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.1.0"
+      }
+    },
+    "estraverse": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+    },
+    "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"
+          }
+        }
+      }
+    },
+    "exit-hook": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
+      "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g="
+    },
+    "expand-brackets": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+      "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+      "optional": true,
+      "requires": {
+        "is-posix-bracket": "^0.1.0"
+      }
+    },
+    "expand-range": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+      "optional": true,
+      "requires": {
+        "fill-range": "^2.1.0"
+      }
+    },
+    "expand-template": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
+      "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg=="
+    },
+    "express": {
+      "version": "4.16.4",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+      "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+      "requires": {
+        "accepts": "~1.3.5",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.18.3",
+        "content-disposition": "0.5.2",
+        "content-type": "~1.0.4",
+        "cookie": "0.3.1",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "1.1.1",
+        "fresh": "0.5.2",
+        "merge-descriptors": "1.0.1",
+        "methods": "~1.1.2",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.2",
+        "path-to-regexp": "0.1.7",
+        "proxy-addr": "~2.0.4",
+        "qs": "6.5.2",
+        "range-parser": "~1.2.0",
+        "safe-buffer": "5.1.2",
+        "send": "0.16.2",
+        "serve-static": "1.13.2",
+        "setprototypeof": "1.1.0",
+        "statuses": "~1.4.0",
+        "type-is": "~1.6.16",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      },
+      "dependencies": {
+        "body-parser": {
+          "version": "1.18.3",
+          "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+          "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+          "requires": {
+            "bytes": "3.0.0",
+            "content-type": "~1.0.4",
+            "debug": "2.6.9",
+            "depd": "~1.1.2",
+            "http-errors": "~1.6.3",
+            "iconv-lite": "0.4.23",
+            "on-finished": "~2.3.0",
+            "qs": "6.5.2",
+            "raw-body": "2.3.3",
+            "type-is": "~1.6.16"
+          }
+        },
+        "bytes": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+          "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+        },
+        "http-errors": {
+          "version": "1.6.3",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+          "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+          "requires": {
+            "depd": "~1.1.2",
+            "inherits": "2.0.3",
+            "setprototypeof": "1.1.0",
+            "statuses": ">= 1.4.0 < 2"
+          }
+        },
+        "iconv-lite": {
+          "version": "0.4.23",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+          "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        },
+        "qs": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+        },
+        "raw-body": {
+          "version": "2.3.3",
+          "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+          "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+          "requires": {
+            "bytes": "3.0.0",
+            "http-errors": "1.6.3",
+            "iconv-lite": "0.4.23",
+            "unpipe": "1.0.0"
+          }
+        },
+        "setprototypeof": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+          "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+        },
+        "statuses": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+          "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+        }
+      }
+    },
+    "express-mongo-sanitize": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/express-mongo-sanitize/-/express-mongo-sanitize-1.3.2.tgz",
+      "integrity": "sha1-+6QE9sBBV3y+7sTdkFfO+7Q53lo="
+    },
+    "express-session": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.1.tgz",
+      "integrity": "sha512-pWvUL8Tl5jUy1MLH7DhgUlpoKeVPUTe+y6WQD9YhcN0C5qAhsh4a8feVjiUXo3TFhIy191YGZ4tewW9edbl2xQ==",
+      "requires": {
+        "cookie": "0.3.1",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "~2.0.0",
+        "on-headers": "~1.0.2",
+        "parseurl": "~1.3.2",
+        "safe-buffer": "5.1.2",
+        "uid-safe": "~2.1.5"
+      },
+      "dependencies": {
+        "depd": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+          "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
+        }
+      }
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+    },
+    "extend-shallow": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+      "requires": {
+        "assign-symbols": "^1.0.0",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "external-editor": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
+      "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
+      "dev": true,
+      "requires": {
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
+      }
+    },
+    "extglob": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+      "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+      "optional": true,
+      "requires": {
+        "is-extglob": "^1.0.0"
+      }
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+    },
+    "fast-deep-equal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+    },
+    "fast-glob": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz",
+      "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==",
+      "requires": {
+        "@mrmlnc/readdir-enhanced": "^2.2.1",
+        "@nodelib/fs.stat": "^1.1.2",
+        "glob-parent": "^3.1.0",
+        "is-glob": "^4.0.0",
+        "merge2": "^1.2.3",
+        "micromatch": "^3.1.10"
+      },
+      "dependencies": {
+        "arr-diff": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+        },
+        "array-unique": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+        },
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "expand-brackets": {
+          "version": "2.1.4",
+          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+          "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+          "requires": {
+            "debug": "^2.3.3",
+            "define-property": "^0.2.5",
+            "extend-shallow": "^2.0.1",
+            "posix-character-classes": "^0.1.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "define-property": {
+              "version": "0.2.5",
+              "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+              "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+              "requires": {
+                "is-descriptor": "^0.1.0"
+              }
+            },
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            },
+            "is-accessor-descriptor": {
+              "version": "0.1.6",
+              "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+              "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+              "requires": {
+                "kind-of": "^3.0.2"
+              },
+              "dependencies": {
+                "kind-of": {
+                  "version": "3.2.2",
+                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                  "requires": {
+                    "is-buffer": "^1.1.5"
+                  }
+                }
+              }
+            },
+            "is-data-descriptor": {
+              "version": "0.1.4",
+              "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+              "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+              "requires": {
+                "kind-of": "^3.0.2"
+              },
+              "dependencies": {
+                "kind-of": {
+                  "version": "3.2.2",
+                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                  "requires": {
+                    "is-buffer": "^1.1.5"
+                  }
+                }
+              }
+            },
+            "is-descriptor": {
+              "version": "0.1.6",
+              "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+              "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+              "requires": {
+                "is-accessor-descriptor": "^0.1.6",
+                "is-data-descriptor": "^0.1.4",
+                "kind-of": "^5.0.0"
+              }
+            },
+            "kind-of": {
+              "version": "5.1.0",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+              "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+            }
+          }
+        },
+        "extglob": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+          "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+          "requires": {
+            "array-unique": "^0.3.2",
+            "define-property": "^1.0.0",
+            "expand-brackets": "^2.1.4",
+            "extend-shallow": "^2.0.1",
+            "fragment-cache": "^0.2.1",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "define-property": {
+              "version": "1.0.0",
+              "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+              "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+              "requires": {
+                "is-descriptor": "^1.0.0"
+              }
+            },
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        },
+        "is-extglob": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+          "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+        },
+        "is-glob": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+          "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+          "requires": {
+            "is-extglob": "^2.1.1"
+          }
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        },
+        "kind-of": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        }
+      }
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
+    },
+    "fd-slicer": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+      "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+      "requires": {
+        "pend": "~1.2.0"
+      }
+    },
+    "figures": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+      "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+      "requires": {
+        "escape-string-regexp": "^1.0.5",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "flat-cache": "^2.0.1"
+      }
+    },
+    "file-type": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+      "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY="
+    },
+    "filename-regex": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+      "optional": true
+    },
+    "fill-range": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
+      "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
+      "optional": true,
+      "requires": {
+        "is-number": "^2.1.0",
+        "isobject": "^2.0.0",
+        "randomatic": "^3.0.0",
+        "repeat-element": "^1.1.2",
+        "repeat-string": "^1.5.2"
+      }
+    },
+    "finalhandler": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+      "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.2",
+        "statuses": "~1.4.0",
+        "unpipe": "~1.0.0"
+      },
+      "dependencies": {
+        "statuses": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+          "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+        }
+      }
+    },
+    "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"
+      },
+      "dependencies": {
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        }
+      }
+    },
+    "find-package-json": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/find-package-json/-/find-package-json-1.2.0.tgz",
+      "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==",
+      "dev": true
+    },
+    "find-up": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+      "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+      "requires": {
+        "path-exists": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "fire-up": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fire-up/-/fire-up-1.0.0.tgz",
+      "integrity": "sha1-cyXaXgqCyH77X39wM6uil1EB/0I=",
+      "requires": {
+        "bluebird": "^3.3.4",
+        "lodash": "^4.7.0",
+        "simple-glob": "0.1.1"
+      }
+    },
+    "flat": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
+      "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
+      "dev": true,
+      "requires": {
+        "is-buffer": "~2.0.3"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+          "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
+          "dev": true
+        }
+      }
+    },
+    "flat-cache": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "dev": true,
+      "requires": {
+        "flatted": "^2.0.0",
+        "rimraf": "2.6.3",
+        "write": "1.0.3"
+      }
+    },
+    "flatted": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
+      "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==",
+      "dev": true
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+    },
+    "for-own": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+      "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+      "optional": true,
+      "requires": {
+        "for-in": "^1.0.1"
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+    },
+    "form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "formidable": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+      "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
+      "dev": true
+    },
+    "forwarded": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+    },
+    "fragment-cache": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+      "requires": {
+        "map-cache": "^0.2.2"
+      }
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+    },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "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=="
+    },
+    "fs-extra": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz",
+      "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=",
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "jsonfile": "^2.1.0"
+      }
+    },
+    "fs-readdir-recursive": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+      "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA=="
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+    },
+    "fsevents": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz",
+      "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==",
+      "optional": true,
+      "requires": {
+        "nan": "^2.12.1",
+        "node-pre-gyp": "^0.12.0"
+      },
+      "dependencies": {
+        "abbrev": {
+          "version": "1.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "bundled": true
+        },
+        "aproba": {
+          "version": "1.2.0",
+          "bundled": true,
+          "optional": true
+        },
+        "are-we-there-yet": {
+          "version": "1.1.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "delegates": "^1.0.0",
+            "readable-stream": "^2.0.6"
+          }
+        },
+        "balanced-match": {
+          "version": "1.0.0",
+          "bundled": true
+        },
+        "brace-expansion": {
+          "version": "1.1.11",
+          "bundled": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "chownr": {
+          "version": "1.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "code-point-at": {
+          "version": "1.1.0",
+          "bundled": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true
+        },
+        "core-util-is": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "debug": {
+          "version": "4.1.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "deep-extend": {
+          "version": "0.6.0",
+          "bundled": true,
+          "optional": true
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "detect-libc": {
+          "version": "1.0.3",
+          "bundled": true,
+          "optional": true
+        },
+        "fs-minipass": {
+          "version": "1.2.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.2.1"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "gauge": {
+          "version": "2.7.4",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "aproba": "^1.0.3",
+            "console-control-strings": "^1.0.0",
+            "has-unicode": "^2.0.0",
+            "object-assign": "^4.1.0",
+            "signal-exit": "^3.0.0",
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1",
+            "wide-align": "^1.1.0"
+          }
+        },
+        "glob": {
+          "version": "7.1.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "has-unicode": {
+          "version": "2.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "iconv-lite": {
+          "version": "0.4.24",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        },
+        "ignore-walk": {
+          "version": "3.0.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minimatch": "^3.0.4"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
+          }
+        },
+        "inherits": {
+          "version": "2.0.3",
+          "bundled": true
+        },
+        "ini": {
+          "version": "1.3.5",
+          "bundled": true,
+          "optional": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "bundled": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "bundled": true
+        },
+        "minipass": {
+          "version": "2.3.5",
+          "bundled": true,
+          "requires": {
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.0"
+          }
+        },
+        "minizlib": {
+          "version": "1.2.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.2.1"
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "bundled": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "needle": {
+          "version": "2.3.0",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "debug": "^4.1.0",
+            "iconv-lite": "^0.4.4",
+            "sax": "^1.2.4"
+          }
+        },
+        "node-pre-gyp": {
+          "version": "0.12.0",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "detect-libc": "^1.0.2",
+            "mkdirp": "^0.5.1",
+            "needle": "^2.2.1",
+            "nopt": "^4.0.1",
+            "npm-packlist": "^1.1.6",
+            "npmlog": "^4.0.2",
+            "rc": "^1.2.7",
+            "rimraf": "^2.6.1",
+            "semver": "^5.3.0",
+            "tar": "^4"
+          }
+        },
+        "nopt": {
+          "version": "4.0.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "npm-bundled": {
+          "version": "1.0.6",
+          "bundled": true,
+          "optional": true
+        },
+        "npm-packlist": {
+          "version": "1.4.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "ignore-walk": "^3.0.1",
+            "npm-bundled": "^1.0.1"
+          }
+        },
+        "npmlog": {
+          "version": "4.1.2",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "are-we-there-yet": "~1.1.2",
+            "console-control-strings": "~1.1.0",
+            "gauge": "~2.7.3",
+            "set-blocking": "~2.0.0"
+          }
+        },
+        "number-is-nan": {
+          "version": "1.0.1",
+          "bundled": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "os-homedir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "os-tmpdir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "osenv": {
+          "version": "0.1.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "os-homedir": "^1.0.0",
+            "os-tmpdir": "^1.0.0"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "rc": {
+          "version": "1.2.8",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "deep-extend": "^0.6.0",
+            "ini": "~1.3.0",
+            "minimist": "^1.2.0",
+            "strip-json-comments": "~2.0.1"
+          },
+          "dependencies": {
+            "minimist": {
+              "version": "1.2.0",
+              "bundled": true,
+              "optional": true
+            }
+          }
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "bundled": true,
+          "optional": 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"
+          }
+        },
+        "rimraf": {
+          "version": "2.6.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "bundled": true
+        },
+        "safer-buffer": {
+          "version": "2.1.2",
+          "bundled": true,
+          "optional": true
+        },
+        "sax": {
+          "version": "1.2.4",
+          "bundled": true,
+          "optional": true
+        },
+        "semver": {
+          "version": "5.7.0",
+          "bundled": true,
+          "optional": true
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "signal-exit": {
+          "version": "3.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "bundled": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "bundled": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "tar": {
+          "version": "4.4.8",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "chownr": "^1.1.1",
+            "fs-minipass": "^1.2.5",
+            "minipass": "^2.3.4",
+            "minizlib": "^1.1.1",
+            "mkdirp": "^0.5.0",
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.2"
+          }
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "wide-align": {
+          "version": "1.1.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "string-width": "^1.0.2 || 2"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true
+        },
+        "yallist": {
+          "version": "3.0.3",
+          "bundled": 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
+    },
+    "functional-red-black-tree": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+      "dev": true
+    },
+    "generaterr": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/generaterr/-/generaterr-1.5.0.tgz",
+      "integrity": "sha1-sM62zFFk3yoGEzjMNAqGFTlcUvw="
+    },
+    "get-caller-file": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+      "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
+    },
+    "get-func-name": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+      "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+      "dev": true
+    },
+    "get-port": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz",
+      "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==",
+      "dev": true
+    },
+    "get-stream": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
+      "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
+      "requires": {
+        "object-assign": "^4.0.1",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "get-value": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+    },
+    "getos": {
+      "version": "2.8.4",
+      "resolved": "https://registry.npmjs.org/getos/-/getos-2.8.4.tgz",
+      "integrity": "sha1-e4YD02GcKOOMsP56T2PDrLgNUWM=",
+      "requires": {
+        "async": "2.1.4"
+      },
+      "dependencies": {
+        "async": {
+          "version": "2.1.4",
+          "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz",
+          "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=",
+          "requires": {
+            "lodash": "^4.14.0"
+          }
+        }
+      }
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "glob": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "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"
+      },
+      "dependencies": {
+        "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"
+          }
+        }
+      }
+    },
+    "glob-base": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+      "optional": true,
+      "requires": {
+        "glob-parent": "^2.0.0",
+        "is-glob": "^2.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+      "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+      "requires": {
+        "is-glob": "^2.0.0"
+      }
+    },
+    "glob-to-regexp": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz",
+      "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs="
+    },
+    "globals": {
+      "version": "9.18.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
+    },
+    "globby": {
+      "version": "8.0.2",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz",
+      "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==",
+      "requires": {
+        "array-union": "^1.0.1",
+        "dir-glob": "2.0.0",
+        "fast-glob": "^2.0.2",
+        "glob": "^7.1.2",
+        "ignore": "^3.3.5",
+        "pify": "^3.0.0",
+        "slash": "^1.0.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+        }
+      }
+    },
+    "graceful-fs": {
+      "version": "4.1.15",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA=="
+    },
+    "graceful-readlink": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
+    },
+    "growl": {
+      "version": "1.10.5",
+      "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+      "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+      "dev": true
+    },
+    "har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+    },
+    "har-validator": {
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "requires": {
+        "ajv": "^6.5.5",
+        "har-schema": "^2.0.0"
+      }
+    },
+    "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=",
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "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"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
+        }
+      }
+    },
+    "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-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+      "dev": true
+    },
+    "has-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+      "requires": {
+        "get-value": "^2.0.6",
+        "has-values": "^1.0.0",
+        "isobject": "^3.0.0"
+      },
+      "dependencies": {
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        }
+      }
+    },
+    "has-values": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+      "requires": {
+        "is-number": "^3.0.0",
+        "kind-of": "^4.0.0"
+      },
+      "dependencies": {
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true
+    },
+    "home-or-tmp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
+      "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.1"
+      }
+    },
+    "hosted-git-info": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="
+    },
+    "http-errors": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+      "requires": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.3",
+        "setprototypeof": "1.1.1",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.0"
+      }
+    },
+    "http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "https-proxy-agent": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+      "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+      "dev": true,
+      "requires": {
+        "agent-base": "^4.1.0",
+        "debug": "^3.1.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"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        }
+      }
+    },
+    "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"
+      }
+    },
+    "ieee754": {
+      "version": "1.1.13",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+      "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+    },
+    "ignore": {
+      "version": "3.3.10",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+      "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="
+    },
+    "immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
+    },
+    "import-fresh": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz",
+      "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "dependencies": {
+        "resolve-from": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+          "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+          "dev": true
+        }
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "in-publish": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
+      "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E="
+    },
+    "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=",
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+    },
+    "inquirer": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
+      "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
+      "requires": {
+        "ansi-escapes": "^1.1.0",
+        "ansi-regex": "^2.0.0",
+        "chalk": "^1.0.0",
+        "cli-cursor": "^1.0.1",
+        "cli-width": "^2.0.0",
+        "figures": "^1.3.5",
+        "lodash": "^4.3.0",
+        "readline2": "^1.0.1",
+        "run-async": "^0.1.0",
+        "rx-lite": "^3.1.2",
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.0",
+        "through": "^2.3.6"
+      }
+    },
+    "into-stream": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-4.0.0.tgz",
+      "integrity": "sha512-i29KNyE5r0Y/UQzcQ0IbZO1MYJ53Jn0EcFRZPj5FzWKYH17kDFEOwuA+3jroymOI06SW1dEDnly9A1CAreC5dg==",
+      "requires": {
+        "from2": "^2.1.1",
+        "p-is-promise": "^2.0.0"
+      }
+    },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "invert-kv": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+    },
+    "ipaddr.js": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+      "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
+    },
+    "is-accessor-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+      "requires": {
+        "kind-of": "^3.0.2"
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+    },
+    "is-binary-path": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+      "optional": true,
+      "requires": {
+        "binary-extensions": "^1.0.0"
+      }
+    },
+    "is-buffer": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+    },
+    "is-callable": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+      "dev": true
+    },
+    "is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "requires": {
+        "kind-of": "^3.0.2"
+      }
+    },
+    "is-date-object": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+      "dev": true
+    },
+    "is-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "requires": {
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+        }
+      }
+    },
+    "is-dotfile": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+      "optional": true
+    },
+    "is-equal-shallow": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+      "optional": true,
+      "requires": {
+        "is-primitive": "^2.0.0"
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+    },
+    "is-extglob": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+      "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-fullwidth-code-point": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-glob": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+      "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+      "requires": {
+        "is-extglob": "^1.0.0"
+      }
+    },
+    "is-natural-number": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
+      "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg="
+    },
+    "is-number": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+      "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+      "optional": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      }
+    },
+    "is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "requires": {
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        }
+      }
+    },
+    "is-posix-bracket": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+      "optional": true
+    },
+    "is-primitive": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+      "optional": true
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
+    "is-regex": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.1"
+      }
+    },
+    "is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+    },
+    "is-symbol": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+      "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+      "dev": true,
+      "requires": {
+        "has-symbols": "^1.0.0"
+      }
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+    },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+    },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "isobject": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+      "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+      "optional": true,
+      "requires": {
+        "isarray": "1.0.0"
+      }
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+    },
+    "js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+    },
+    "js-yaml": {
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "dependencies": {
+        "esprima": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+          "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+          "dev": true
+        }
+      }
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+    },
+    "jsesc": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+      "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+    },
+    "json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+      "dev": true
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+    },
+    "json5": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+      "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
+    },
+    "jsonfile": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+      "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+      "requires": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      }
+    },
+    "jszip": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.1.tgz",
+      "integrity": "sha512-iCMBbo4eE5rb1VCpm5qXOAaUiRKRUKiItn8ah2YQQx9qymmSAY98eyQfioChEYcVQLh0zxJ3wS4A0mh90AVPvw==",
+      "requires": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "set-immediate-shim": "~1.0.1"
+      }
+    },
+    "kareem": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.0.tgz",
+      "integrity": "sha512-6hHxsp9e6zQU8nXsP+02HGWXwTkOEw6IROhF2ZA28cYbUk4eJ6QbtZvdqZOdD9YPKghG3apk5eOCvs+tLl3lRg=="
+    },
+    "kind-of": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+      "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+      "requires": {
+        "is-buffer": "^1.1.5"
+      }
+    },
+    "lcid": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+      "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+      "requires": {
+        "invert-kv": "^1.0.0"
+      }
+    },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "requires": {
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
+      }
+    },
+    "lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "requires": {
+        "immediate": "~3.0.5"
+      }
+    },
+    "load-json-file": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^2.2.0",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "strip-bom": "^2.0.0"
+      }
+    },
+    "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"
+      },
+      "dependencies": {
+        "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
+        }
+      }
+    },
+    "lockfile": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz",
+      "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==",
+      "dev": true,
+      "requires": {
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "lodash": {
+      "version": "4.17.11",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+    },
+    "lodash.assign": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
+    },
+    "lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
+    },
+    "lodash.set": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
+      "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
+    },
+    "lodash.unset": {
+      "version": "4.5.2",
+      "resolved": "https://registry.npmjs.org/lodash.unset/-/lodash.unset-4.5.2.tgz",
+      "integrity": "sha1-Nw0dPoW3Kn4bDN8tJyEhMG8j5O0="
+    },
+    "log-symbols": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.1"
+      },
+      "dependencies": {
+        "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==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.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"
+          }
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      }
+    },
+    "lru-cache": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
+      "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI="
+    },
+    "make-dir": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+      "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+      "requires": {
+        "pify": "^3.0.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+        }
+      }
+    },
+    "make-error": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+      "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g=="
+    },
+    "map-age-cleaner": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+      "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+      "dev": true,
+      "requires": {
+        "p-defer": "^1.0.0"
+      }
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+    },
+    "map-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+      "requires": {
+        "object-visit": "^1.0.0"
+      }
+    },
+    "math-random": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
+      "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==",
+      "optional": true
+    },
+    "md5-file": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.1.1.tgz",
+      "integrity": "sha1-2zySwJu9pcLeiD+lSQ3XEf3burk="
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+    },
+    "mem": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+      "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+      "dev": true,
+      "requires": {
+        "map-age-cleaner": "^0.1.1",
+        "mimic-fn": "^2.0.0",
+        "p-is-promise": "^2.0.0"
+      },
+      "dependencies": {
+        "mimic-fn": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+          "dev": true
+        }
+      }
+    },
+    "memory-pager": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+      "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
+      "optional": true
+    },
+    "merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+    },
+    "merge2": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz",
+      "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA=="
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+    },
+    "micromatch": {
+      "version": "2.3.11",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+      "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+      "optional": true,
+      "requires": {
+        "arr-diff": "^2.0.0",
+        "array-unique": "^0.2.1",
+        "braces": "^1.8.2",
+        "expand-brackets": "^0.1.4",
+        "extglob": "^0.3.1",
+        "filename-regex": "^2.0.0",
+        "is-extglob": "^1.0.0",
+        "is-glob": "^2.0.1",
+        "kind-of": "^3.0.2",
+        "normalize-path": "^2.0.1",
+        "object.omit": "^2.0.0",
+        "parse-glob": "^3.0.4",
+        "regex-cache": "^0.4.2"
+      }
+    },
+    "migrate-mongoose-typescript": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/migrate-mongoose-typescript/-/migrate-mongoose-typescript-3.3.4.tgz",
+      "integrity": "sha512-0CE8HldEfCNWhQzLOBmn7QqNR1Pb9ynaW5w1BABuUkIYTH7uI08lYq0YUd1OgZuk9xPfzV5SYBxATbR2jFiRrA==",
+      "requires": {
+        "babel-cli": "^6.26.0",
+        "babel-core": "^6.26.3",
+        "babel-plugin-transform-runtime": "^6.23.0",
+        "babel-polyfill": "^6.26.0",
+        "babel-preset-latest": "^6.24.1",
+        "babel-register": "^6.26.0",
+        "bluebird": "^3.5.1",
+        "colors": "^1.2.4",
+        "dotenv": "^5.0.1",
+        "inquirer": "^0.12.0",
+        "mkdirp": "^0.5.1",
+        "mongoose": "^5.3.2",
+        "ts-node": "^6.0.3",
+        "yargs": "^4.8.1"
+      }
+    },
+    "mime": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+      "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+    },
+    "mime-db": {
+      "version": "1.40.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+    },
+    "mime-types": {
+      "version": "2.1.24",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+      "requires": {
+        "mime-db": "1.40.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
+    },
+    "minimatch": {
+      "version": "0.2.14",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
+      "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
+      "requires": {
+        "lru-cache": "2",
+        "sigmund": "~1.0.0"
+      }
+    },
+    "minimist": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+    },
+    "mixin-deep": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
+      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+      "requires": {
+        "for-in": "^1.0.2",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "requires": {
+        "minimist": "0.0.8"
+      }
+    },
+    "mocha": {
+      "version": "6.1.4",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz",
+      "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==",
+      "dev": true,
+      "requires": {
+        "ansi-colors": "3.2.3",
+        "browser-stdout": "1.3.1",
+        "debug": "3.2.6",
+        "diff": "3.5.0",
+        "escape-string-regexp": "1.0.5",
+        "find-up": "3.0.0",
+        "glob": "7.1.3",
+        "growl": "1.10.5",
+        "he": "1.2.0",
+        "js-yaml": "3.13.1",
+        "log-symbols": "2.2.0",
+        "minimatch": "3.0.4",
+        "mkdirp": "0.5.1",
+        "ms": "2.1.1",
+        "node-environment-flags": "1.0.5",
+        "object.assign": "4.1.0",
+        "strip-json-comments": "2.0.1",
+        "supports-color": "6.0.0",
+        "which": "1.3.1",
+        "wide-align": "1.1.3",
+        "yargs": "13.2.2",
+        "yargs-parser": "13.0.0",
+        "yargs-unparser": "1.5.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
+        },
+        "cliui": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+          "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+          "dev": true,
+          "requires": {
+            "string-width": "^2.1.1",
+            "strip-ansi": "^4.0.0",
+            "wrap-ansi": "^2.0.0"
+          },
+          "dependencies": {
+            "string-width": {
+              "version": "2.1.1",
+              "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+              "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+              "dev": true,
+              "requires": {
+                "is-fullwidth-code-point": "^2.0.0",
+                "strip-ansi": "^4.0.0"
+              }
+            }
+          }
+        },
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^3.0.0"
+          }
+        },
+        "get-caller-file": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+          "dev": true
+        },
+        "invert-kv": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+          "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+          "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
+        },
+        "lcid": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+          "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+          "dev": true,
+          "requires": {
+            "invert-kv": "^2.0.0"
+          }
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        },
+        "os-locale": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+          "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+          "dev": true,
+          "requires": {
+            "execa": "^1.0.0",
+            "lcid": "^2.0.0",
+            "mem": "^4.0.0"
+          }
+        },
+        "require-main-filename": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          },
+          "dependencies": {
+            "ansi-regex": {
+              "version": "4.1.0",
+              "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+              "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+              "dev": true
+            },
+            "strip-ansi": {
+              "version": "5.2.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+              "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^4.1.0"
+              }
+            }
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
+          "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        },
+        "which-module": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+          "dev": true
+        },
+        "y18n": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+          "dev": true
+        },
+        "yargs": {
+          "version": "13.2.2",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
+          "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
+          "dev": true,
+          "requires": {
+            "cliui": "^4.0.0",
+            "find-up": "^3.0.0",
+            "get-caller-file": "^2.0.1",
+            "os-locale": "^3.1.0",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^2.0.0",
+            "set-blocking": "^2.0.0",
+            "string-width": "^3.0.0",
+            "which-module": "^2.0.0",
+            "y18n": "^4.0.0",
+            "yargs-parser": "^13.0.0"
+          }
+        },
+        "yargs-parser": {
+          "version": "13.0.0",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
+          "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^5.0.0",
+            "decamelize": "^1.2.0"
+          }
+        }
+      }
+    },
+    "mocha-teamcity-reporter": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/mocha-teamcity-reporter/-/mocha-teamcity-reporter-2.5.2.tgz",
+      "integrity": "sha512-zaJHKye3DSui3e9FdRKyt7fj9JxQxvlmSUu1Jow0VTyiYu6VsETY57Q4gwb2PWPZZgAugluamSnMCYC17hutGg==",
+      "dev": true,
+      "requires": {
+        "mocha": ">=3.5.0 < 6"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.15.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+          "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "glob": {
+          "version": "7.1.2",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+          "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"
+          }
+        },
+        "he": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+          "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+          "dev": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "mocha": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
+          "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
+          "dev": true,
+          "requires": {
+            "browser-stdout": "1.3.1",
+            "commander": "2.15.1",
+            "debug": "3.1.0",
+            "diff": "3.5.0",
+            "escape-string-regexp": "1.0.5",
+            "glob": "7.1.2",
+            "growl": "1.10.5",
+            "he": "1.1.1",
+            "minimatch": "3.0.4",
+            "mkdirp": "0.5.1",
+            "supports-color": "5.4.0"
+          }
+        },
+        "supports-color": {
+          "version": "5.4.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+          "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "mongodb": {
+      "version": "3.1.13",
+      "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.13.tgz",
+      "integrity": "sha512-sz2dhvBZQWf3LRNDhbd30KHVzdjZx9IKC0L+kSZ/gzYquCF5zPOgGqRz6sSCqYZtKP2ekB4nfLxhGtzGHnIKxA==",
+      "requires": {
+        "mongodb-core": "3.1.11",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "mongodb-core": {
+      "version": "3.1.11",
+      "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.11.tgz",
+      "integrity": "sha512-rD2US2s5qk/ckbiiGFHeu+yKYDXdJ1G87F6CG3YdaZpzdOm5zpoAZd/EKbPmFO6cQZ+XVXBXBJ660sSI0gc6qg==",
+      "requires": {
+        "bson": "^1.1.0",
+        "require_optional": "^1.0.1",
+        "safe-buffer": "^5.1.2",
+        "saslprep": "^1.0.0"
+      }
+    },
+    "mongodb-download": {
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/mongodb-download/-/mongodb-download-2.2.7.tgz",
+      "integrity": "sha512-39/eiEmCqig0gCR3tNbmbTk6rIpWzEGqcXT0BE645stlA+DY7WlrIWZGEG51BcI3MUdGzqVYFj+qLoRw+HsJSA==",
+      "requires": {
+        "debug": "^2.2.0",
+        "decompress": "^4.0.0",
+        "fs-extra": "^2.0.0",
+        "getos": "^2.7.0",
+        "md5-file": "3.1.1",
+        "request": "^2.79.0",
+        "request-promise": "^4.1.1",
+        "semver": "^5.6.0",
+        "yargs": "^3.26.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+          "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+        },
+        "window-size": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
+          "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY="
+        },
+        "yargs": {
+          "version": "3.32.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
+          "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
+          "requires": {
+            "camelcase": "^2.0.1",
+            "cliui": "^3.0.3",
+            "decamelize": "^1.1.1",
+            "os-locale": "^1.4.0",
+            "string-width": "^1.0.1",
+            "window-size": "^0.1.4",
+            "y18n": "^3.2.0"
+          }
+        }
+      }
+    },
+    "mongodb-memory-server": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-5.1.0.tgz",
+      "integrity": "sha512-CN4fjt90fi6A3PSJIx6xYxIRqpxF1rJoz4BcJv6LmGyRAOAvCbr3SqRbfXJMS26wTDyHylXtW32PhdykDohogA==",
+      "dev": true,
+      "requires": {
+        "mongodb-memory-server-core": "5.1.0"
+      }
+    },
+    "mongodb-memory-server-core": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/mongodb-memory-server-core/-/mongodb-memory-server-core-5.1.0.tgz",
+      "integrity": "sha512-M/GWVvFze0geP2smoy0ns+Yz5l4BRP6Y66OKc+w9zlX422ydQEA04bLQjooPqoaBTrV90xuDj5E+zejn/YkPew==",
+      "dev": true,
+      "requires": {
+        "camelcase": "^5.3.1",
+        "debug": "^4.1.1",
+        "decompress": "^4.2.0",
+        "dedent": "^0.7.0",
+        "find-cache-dir": "^2.0.0",
+        "find-package-json": "^1.2.0",
+        "get-port": "^4.2.0",
+        "getos": "^3.1.1",
+        "https-proxy-agent": "^2.2.1",
+        "lockfile": "^1.0.4",
+        "md5-file": "^4.0.0",
+        "mkdirp": "^0.5.1",
+        "mongodb": ">=3.0.0",
+        "tmp": "^0.0.33",
+        "uuid": "^3.2.1"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "getos": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/getos/-/getos-3.1.1.tgz",
+          "integrity": "sha512-oUP1rnEhAr97rkitiszGP9EgDVYnmchgFzfqRzSkgtfv7ai6tEi7Ko8GgjNXts7VLWEqrTWyhsOKLe5C5b/Zkg==",
+          "dev": true,
+          "requires": {
+            "async": "2.6.1"
+          }
+        },
+        "md5-file": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-4.0.0.tgz",
+          "integrity": "sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==",
+          "dev": true
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        }
+      }
+    },
+    "mongodb-prebuilt": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/mongodb-prebuilt/-/mongodb-prebuilt-6.5.0.tgz",
+      "integrity": "sha512-rwTWbV4w8uxYJAhq2tQd+lrAjOYsxo/eXJb5rvNCGEJZlddoThYOHlkfLQ4w7PagauQZN3XBEW55GhkPUadN6w==",
+      "requires": {
+        "debug": "^2.2.0",
+        "glob": "^7.1.1",
+        "mongodb-download": "^2.2.7",
+        "spawn-sync": "1.0.15",
+        "yargs": "^3.26.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+          "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+        },
+        "window-size": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
+          "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY="
+        },
+        "yargs": {
+          "version": "3.32.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
+          "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
+          "requires": {
+            "camelcase": "^2.0.1",
+            "cliui": "^3.0.3",
+            "decamelize": "^1.1.1",
+            "os-locale": "^1.4.0",
+            "string-width": "^1.0.1",
+            "window-size": "^0.1.4",
+            "y18n": "^3.2.0"
+          }
+        }
+      }
+    },
+    "mongoose": {
+      "version": "5.5.4",
+      "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.5.4.tgz",
+      "integrity": "sha512-xzS7fJtXGjCOZozCtlyFS8graMub1L9knp37+1dJCDmWzOtXVHeLjV2XIC9tX0sE54cxeG5rHvSmIkLpeHjjmA==",
+      "requires": {
+        "async": "2.6.1",
+        "bson": "~1.1.1",
+        "kareem": "2.3.0",
+        "mongodb": "3.2.2",
+        "mongodb-core": "3.2.2",
+        "mongoose-legacy-pluralize": "1.0.2",
+        "mpath": "0.5.2",
+        "mquery": "3.2.0",
+        "ms": "2.1.1",
+        "regexp-clone": "0.0.1",
+        "safe-buffer": "5.1.2",
+        "sift": "7.0.1",
+        "sliced": "1.0.1"
+      },
+      "dependencies": {
+        "mongodb": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.2.2.tgz",
+          "integrity": "sha512-xQ6apOOV+w7VFApdaJpWhYhzartpjIDFQjG0AwgJkLh7dBs7PTsq4A3Bia2QWpDohmAzTBIdQVLMqqLy0mwt3Q==",
+          "requires": {
+            "mongodb-core": "3.2.2",
+            "safe-buffer": "^5.1.2"
+          }
+        },
+        "mongodb-core": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.2.tgz",
+          "integrity": "sha512-YRgC39MuzKL0uoGoRdTmV1e9m47NbMnYmuEx4IOkgWAGXPSEzRY7cwb3N0XMmrDMnD9vp7MysNyAriIIeGgIQg==",
+          "requires": {
+            "bson": "^1.1.1",
+            "require_optional": "^1.0.1",
+            "safe-buffer": "^5.1.2",
+            "saslprep": "^1.0.0"
+          }
+        },
+        "mpath": {
+          "version": "0.5.2",
+          "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.2.tgz",
+          "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw=="
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+        }
+      }
+    },
+    "mongoose-legacy-pluralize": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
+      "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
+    },
+    "morgan": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
+      "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
+      "requires": {
+        "basic-auth": "~2.0.0",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "on-finished": "~2.3.0",
+        "on-headers": "~1.0.1"
+      }
+    },
+    "mpath": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.1.tgz",
+      "integrity": "sha512-H8OVQ+QEz82sch4wbODFOz+3YQ61FYz/z3eJ5pIdbMEaUzDqA268Wd+Vt4Paw9TJfvDgVKaayC0gBzMIw2jhsg=="
+    },
+    "mquery": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.0.tgz",
+      "integrity": "sha512-qPJcdK/yqcbQiKoemAt62Y0BAc0fTEKo1IThodBD+O5meQRJT/2HSe5QpBNwaa4CjskoGrYWsEyjkqgiE0qjhg==",
+      "requires": {
+        "bluebird": "3.5.1",
+        "debug": "3.1.0",
+        "regexp-clone": "0.0.1",
+        "safe-buffer": "5.1.2",
+        "sliced": "1.0.1"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "3.5.1",
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+          "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "multistream": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/multistream/-/multistream-2.1.1.tgz",
+      "integrity": "sha512-xasv76hl6nr1dEy3lPvy7Ej7K/Lx3O/FCvwge8PeVJpciPPoNCbaANcNiBug3IpdvTveZUcAV0DJzdnUDMesNQ==",
+      "requires": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.5"
+      }
+    },
+    "mute-stream": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
+      "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA="
+    },
+    "nan": {
+      "version": "2.13.2",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
+      "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
+      "optional": true
+    },
+    "nanomatch": {
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "fragment-cache": "^0.2.1",
+        "is-windows": "^1.0.2",
+        "kind-of": "^6.0.2",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "arr-diff": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+        },
+        "array-unique": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+        },
+        "kind-of": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+        }
+      }
+    },
+    "natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+      "dev": true
+    },
+    "nconf": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz",
+      "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==",
+      "requires": {
+        "async": "^1.4.0",
+        "ini": "^1.3.0",
+        "secure-keys": "^1.0.0",
+        "yargs": "^3.19.0"
+      },
+      "dependencies": {
+        "async": {
+          "version": "1.5.2",
+          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
+        },
+        "camelcase": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+          "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+        },
+        "window-size": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
+          "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY="
+        },
+        "yargs": {
+          "version": "3.32.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
+          "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
+          "requires": {
+            "camelcase": "^2.0.1",
+            "cliui": "^3.0.3",
+            "decamelize": "^1.1.1",
+            "os-locale": "^1.4.0",
+            "string-width": "^1.0.1",
+            "window-size": "^0.1.4",
+            "y18n": "^3.2.0"
+          }
+        }
+      }
+    },
+    "negotiator": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "node-environment-flags": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
+      "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
+      "dev": true,
+      "requires": {
+        "object.getownpropertydescriptors": "^2.0.3",
+        "semver": "^5.7.0"
+      }
+    },
+    "nodemailer": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.1.1.tgz",
+      "integrity": "sha512-/x5MRIh56VyuuhLfcz+DL2SlBARpZpgQIf2A4Ao4hMb69MHSgDIMPwYmFwesGT1lkRDZ0eBSoym5+JoIZ3N+cQ=="
+    },
+    "normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "normalize-path": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+      "requires": {
+        "remove-trailing-separator": "^1.0.1"
+      }
+    },
+    "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"
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+    },
+    "oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+    },
+    "object-component": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+      "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
+    },
+    "object-copy": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+      "requires": {
+        "copy-descriptor": "^0.1.0",
+        "define-property": "^0.2.5",
+        "kind-of": "^3.0.3"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "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-visit": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+      "requires": {
+        "isobject": "^3.0.0"
+      },
+      "dependencies": {
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        }
+      }
+    },
+    "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.0.3",
+      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+      "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.5.1"
+      }
+    },
+    "object.omit": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+      "optional": true,
+      "requires": {
+        "for-own": "^0.1.4",
+        "is-extendable": "^0.1.1"
+      }
+    },
+    "object.pick": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+      "requires": {
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+        }
+      }
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "on-headers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+      "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+      "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="
+    },
+    "optionator": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+      "requires": {
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.4",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "wordwrap": "~1.0.0"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+    },
+    "os-locale": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+      "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+      "requires": {
+        "lcid": "^1.0.0"
+      }
+    },
+    "os-shim": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
+      "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc="
+    },
+    "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="
+    },
+    "output-file-sync": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz",
+      "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=",
+      "requires": {
+        "graceful-fs": "^4.1.4",
+        "mkdirp": "^0.5.1",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "p-defer": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+      "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+      "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": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+      "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
+    },
+    "p-limit": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+      "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+      "dev": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "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-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
+    },
+    "pako": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz",
+      "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw=="
+    },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
+    "parse-glob": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+      "optional": true,
+      "requires": {
+        "glob-base": "^0.3.0",
+        "is-dotfile": "^1.0.0",
+        "is-extglob": "^1.0.0",
+        "is-glob": "^2.0.0"
+      }
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "requires": {
+        "error-ex": "^1.2.0"
+      }
+    },
+    "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"
+      }
+    },
+    "parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+    },
+    "pascalcase": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+    },
+    "passport": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz",
+      "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=",
+      "requires": {
+        "passport-strategy": "1.x.x",
+        "pause": "0.0.1"
+      }
+    },
+    "passport-local": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
+      "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
+      "requires": {
+        "passport-strategy": "1.x.x"
+      }
+    },
+    "passport-local-mongoose": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/passport-local-mongoose/-/passport-local-mongoose-5.0.1.tgz",
+      "integrity": "sha512-VUY5DgBdpjt1tjunJJ1EXV5b2nhMDkXJuhTjyiK660IgIp7kONMyWEe9tGHf8I9tZudXuTF+47JNQLIzU+Hjbw==",
+      "requires": {
+        "debug": "^3.1.0",
+        "generaterr": "^1.5.0",
+        "passport-local": "^1.0.0",
+        "scmp": "^2.0.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"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+        }
+      }
+    },
+    "passport-strategy": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
+      "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
+    },
+    "passport.socketio": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/passport.socketio/-/passport.socketio-3.7.0.tgz",
+      "integrity": "sha1-LuX6/paV1CgcjN3T/pdezRjmcm4=",
+      "requires": {
+        "xtend": "^4.0.0"
+      }
+    },
+    "path-dirname": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+    },
+    "path-exists": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+      "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+      "requires": {
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "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="
+    },
+    "path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
+    },
+    "path-to-regexp": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+    },
+    "path-type": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "pathval": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+      "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+      "dev": true
+    },
+    "pause": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
+      "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
+    },
+    "pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "pkg": {
+      "version": "4.3.7",
+      "resolved": "https://registry.npmjs.org/pkg/-/pkg-4.3.7.tgz",
+      "integrity": "sha512-/BvtFft1nKKtnTuOm/0es0sk1cOs7ZtWgJpqdtszJ4348jYJ8owVyCB/iuGhI3YJFX/ZFIv4Rmra9ETUgpnnfA==",
+      "requires": {
+        "@babel/parser": "7.2.3",
+        "babel-runtime": "6.26.0",
+        "chalk": "2.4.2",
+        "escodegen": "1.11.0",
+        "fs-extra": "7.0.1",
+        "globby": "8.0.2",
+        "into-stream": "4.0.0",
+        "minimist": "1.2.0",
+        "multistream": "2.1.1",
+        "pkg-fetch": "2.5.7",
+        "progress": "2.0.3",
+        "resolve": "1.6.0",
+        "stream-meter": "1.0.4"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "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"
+          }
+        },
+        "fs-extra": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+          "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "jsonfile": "^4.0.0",
+            "universalify": "^0.1.0"
+          }
+        },
+        "jsonfile": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+          "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+          "requires": {
+            "graceful-fs": "^4.1.6"
+          }
+        },
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+        },
+        "resolve": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz",
+          "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==",
+          "requires": {
+            "path-parse": "^1.0.5"
+          }
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "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"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^3.0.0"
+          }
+        }
+      }
+    },
+    "pkg-fetch": {
+      "version": "2.5.7",
+      "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-2.5.7.tgz",
+      "integrity": "sha512-fm9aVV3ZRdFYTyFYcSHuKMuxPCVQ0MD9tbVxbvQzFTg1gwvV0KqWrFoj5enVVha94yP83I50XEBa90X8L9fE8w==",
+      "requires": {
+        "babel-runtime": "~6.26.0",
+        "byline": "~5.0.0",
+        "chalk": "~2.4.1",
+        "expand-template": "~1.1.1",
+        "fs-extra": "~6.0.1",
+        "in-publish": "~2.0.0",
+        "minimist": "~1.2.0",
+        "progress": "~2.0.0",
+        "request": "~2.88.0",
+        "request-progress": "~3.0.0",
+        "semver": "~5.6.0",
+        "unique-temp-dir": "~1.0.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "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"
+          }
+        },
+        "fs-extra": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz",
+          "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==",
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "jsonfile": "^4.0.0",
+            "universalify": "^0.1.0"
+          }
+        },
+        "jsonfile": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+          "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+          "requires": {
+            "graceful-fs": "^4.1.6"
+          }
+        },
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+        },
+        "semver": {
+          "version": "5.6.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+          "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "posix-character-classes": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+    },
+    "prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
+    },
+    "preserve": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+      "optional": true
+    },
+    "private": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+      "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+    },
+    "process-nextick-args": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+    },
+    "progress": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
+    },
+    "proxy-addr": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+      "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+      "requires": {
+        "forwarded": "~0.1.2",
+        "ipaddr.js": "1.9.0"
+      }
+    },
+    "psl": {
+      "version": "1.1.31",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
+      "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
+    },
+    "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"
+      }
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+    },
+    "qs": {
+      "version": "6.7.0",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+      "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+    },
+    "random-bytes": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+      "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+    },
+    "randomatic": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
+      "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
+      "optional": true,
+      "requires": {
+        "is-number": "^4.0.0",
+        "kind-of": "^6.0.0",
+        "math-random": "^1.0.1"
+      },
+      "dependencies": {
+        "is-number": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
+          "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
+          "optional": true
+        },
+        "kind-of": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+          "optional": true
+        }
+      }
+    },
+    "range-parser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+    },
+    "raw-body": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+      "requires": {
+        "bytes": "3.1.0",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "unpipe": "1.0.0"
+      }
+    },
+    "read-pkg": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "requires": {
+        "load-json-file": "^1.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^1.0.0"
+      }
+    },
+    "read-pkg-up": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+      "requires": {
+        "find-up": "^1.0.0",
+        "read-pkg": "^1.0.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "readdirp": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+      "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+      "optional": true,
+      "requires": {
+        "graceful-fs": "^4.1.11",
+        "micromatch": "^3.1.10",
+        "readable-stream": "^2.0.2"
+      },
+      "dependencies": {
+        "arr-diff": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+          "optional": true
+        },
+        "array-unique": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+        },
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "optional": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "expand-brackets": {
+          "version": "2.1.4",
+          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+          "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+          "optional": true,
+          "requires": {
+            "debug": "^2.3.3",
+            "define-property": "^0.2.5",
+            "extend-shallow": "^2.0.1",
+            "posix-character-classes": "^0.1.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "define-property": {
+              "version": "0.2.5",
+              "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+              "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+              "optional": true,
+              "requires": {
+                "is-descriptor": "^0.1.0"
+              }
+            },
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            },
+            "is-accessor-descriptor": {
+              "version": "0.1.6",
+              "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+              "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+              "optional": true,
+              "requires": {
+                "kind-of": "^3.0.2"
+              },
+              "dependencies": {
+                "kind-of": {
+                  "version": "3.2.2",
+                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                  "optional": true,
+                  "requires": {
+                    "is-buffer": "^1.1.5"
+                  }
+                }
+              }
+            },
+            "is-data-descriptor": {
+              "version": "0.1.4",
+              "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+              "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+              "optional": true,
+              "requires": {
+                "kind-of": "^3.0.2"
+              },
+              "dependencies": {
+                "kind-of": {
+                  "version": "3.2.2",
+                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                  "optional": true,
+                  "requires": {
+                    "is-buffer": "^1.1.5"
+                  }
+                }
+              }
+            },
+            "is-descriptor": {
+              "version": "0.1.6",
+              "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+              "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+              "optional": true,
+              "requires": {
+                "is-accessor-descriptor": "^0.1.6",
+                "is-data-descriptor": "^0.1.4",
+                "kind-of": "^5.0.0"
+              }
+            },
+            "kind-of": {
+              "version": "5.1.0",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+              "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+              "optional": true
+            }
+          }
+        },
+        "extglob": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+          "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+          "optional": true,
+          "requires": {
+            "array-unique": "^0.3.2",
+            "define-property": "^1.0.0",
+            "expand-brackets": "^2.1.4",
+            "extend-shallow": "^2.0.1",
+            "fragment-cache": "^0.2.1",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "define-property": {
+              "version": "1.0.0",
+              "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+              "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+              "optional": true,
+              "requires": {
+                "is-descriptor": "^1.0.0"
+              }
+            },
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "optional": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "optional": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "optional": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "optional": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "optional": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "optional": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "isobject": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+          "optional": true
+        },
+        "kind-of": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "optional": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        }
+      }
+    },
+    "readline2": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
+      "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=",
+      "requires": {
+        "code-point-at": "^1.0.0",
+        "is-fullwidth-code-point": "^1.0.0",
+        "mute-stream": "0.0.5"
+      }
+    },
+    "regenerate": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+      "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
+    },
+    "regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+    },
+    "regenerator-transform": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+      "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+      "requires": {
+        "babel-runtime": "^6.18.0",
+        "babel-types": "^6.19.0",
+        "private": "^0.1.6"
+      }
+    },
+    "regex-cache": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "optional": true,
+      "requires": {
+        "is-equal-shallow": "^0.1.3"
+      }
+    },
+    "regex-not": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+      "requires": {
+        "extend-shallow": "^3.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
+    "regexp-clone": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz",
+      "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk="
+    },
+    "regexpp": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+      "dev": true
+    },
+    "regexpu-core": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+      "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+      "requires": {
+        "regenerate": "^1.2.1",
+        "regjsgen": "^0.2.0",
+        "regjsparser": "^0.1.4"
+      }
+    },
+    "regjsgen": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="
+    },
+    "regjsparser": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+      "requires": {
+        "jsesc": "~0.5.0"
+      },
+      "dependencies": {
+        "jsesc": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+        }
+      }
+    },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+    },
+    "repeat-element": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+    },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "requires": {
+        "is-finite": "^1.0.0"
+      }
+    },
+    "request": {
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "requires": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+        }
+      }
+    },
+    "request-progress": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+      "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=",
+      "requires": {
+        "throttleit": "^1.0.0"
+      }
+    },
+    "request-promise": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz",
+      "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==",
+      "requires": {
+        "bluebird": "^3.5.0",
+        "request-promise-core": "1.1.2",
+        "stealthy-require": "^1.1.1",
+        "tough-cookie": "^2.3.3"
+      }
+    },
+    "request-promise-core": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz",
+      "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==",
+      "requires": {
+        "lodash": "^4.17.11"
+      }
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+    },
+    "require-main-filename": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+    },
+    "require_optional": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
+      "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
+      "requires": {
+        "resolve-from": "^2.0.0",
+        "semver": "^5.1.0"
+      }
+    },
+    "resolve": {
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz",
+      "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==",
+      "requires": {
+        "path-parse": "^1.0.6"
+      }
+    },
+    "resolve-from": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
+      "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
+    },
+    "resolve-url": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
+    },
+    "restore-cursor": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+      "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+      "requires": {
+        "exit-hook": "^1.0.0",
+        "onetime": "^1.0.0"
+      }
+    },
+    "ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
+    },
+    "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"
+      }
+    },
+    "run-async": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
+      "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=",
+      "requires": {
+        "once": "^1.3.0"
+      }
+    },
+    "rx-lite": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
+      "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI="
+    },
+    "rxjs": {
+      "version": "6.5.1",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz",
+      "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "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=="
+    },
+    "safe-regex": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+      "requires": {
+        "ret": "~0.1.10"
+      }
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "saslprep": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz",
+      "integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==",
+      "optional": true,
+      "requires": {
+        "sparse-bitfield": "^3.0.3"
+      }
+    },
+    "scmp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.0.0.tgz",
+      "integrity": "sha1-JHEQ7yLM+JexOj8KvdtSeCOTzWo="
+    },
+    "secure-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz",
+      "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o="
+    },
+    "seek-bzip": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
+      "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
+      "requires": {
+        "commander": "~2.8.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.8.1",
+          "resolved": "https://registry.npmjs.org/comman