diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..50ca329
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.sh eol=lf
diff --git a/.gitignore b/.gitignore
index a1c2a23..3740410 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,23 +1,115 @@
-# Compiled class file
+### Custom entries ###
+*.tsv
+*.env
+*.prefs
+*.java2
*.class
-
-# Log file
-*.log
-
-# BlueJ files
-*.ctxt
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
+*.classpath
+*.properties
+*.lst
*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
+*.original
+*.project
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
+# Created by https://www.gitignore.io/api/maven
+
+### Maven ###
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+
+
+# End of https://www.gitignore.io/api/maven
+
+
+
+# Created by https://www.gitignore.io/api/intellij
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+.idea/sonarlint
+
+.idea/misc.xml
+# End of https://www.gitignore.io/api/intellij
diff --git a/README.md b/README.md
index 72f1506..4e0388b 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,235 @@
+# SpringDAL
-# Contributing
+A RESTful DAL (Database Abstraction Layer) reference implementation written using Spring.
-This project welcomes contributions and suggestions. Most contributions require you to agree to a
-Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
-the rights to use your contribution. For details, visit https://cla.microsoft.com.
+# Introduction
-When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
-a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
-provided by the bot. You will only need to do this once across all repos using our CLA.
+This project provides a reference implementation for of Java-based microservices with REST APIs that read and write data stored in Azure Cosmos DB. The services are hosted in containers running in Azure App Service for Containers, (FUTURE: with Azure Redis providing caching). HA/DR is provided by hosting the microservices in multiple regions, as well as CosmosDB's native geo-redundancy. Traffic Manager is used to route traffic based on geo-proximity, and Application Gateway provides path-based routing, service authentication and DDoS protection.
-This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
-For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
-contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
+Cosmos DB is configured to use the NoSQL MongoDB API.
+
+In order to demonstrate Cosmos DB performance with large amounts of data, the project imports historial movie data from [IMDb](https://www.imdb.com/interfaces/). See (https://datasets.imdbws.com/.) The datasets include 8.9 million peple, 5.3 million movies and 30 million relationships between them.
+
+## Architecture
+
+This solution provides a robust foundation on which enterprise engineering (EE) teams may build and deploy production-ready microservices solutions.
+
+We built the solution to provide a common enterprise-ready foundation for Azure-based applications with the following architecture:
+
+- Java-based microservices
+- Data stored in Cosmos DB
+- Redis-based caching
+- High Availability & Disaster Recovery (HA/DR)
+- A full CI/CD pipeline
+- Robust but simple codebase that follows common enterprise-engineering best practices
+- Load and failure simulators to validate scale, resiliency and failover
+
+### Why We Chose App Services
+
+We decided to host our application using Azure App Services instead of using Azure Kuberenetes Cluster. We made this decision because Azure App Services gave us better control over scaling the app accross regions. It also required less configuration with our traffic manager and load balancer architecture. Furthermore, Azure App Services has an easy-to-use, built-in load testing service that we utilize to test the container scaling of our app. Out of the box, Azure App Services offers auto-scaling, authentication, and deployment slots. In the future, because Azure App Services is a PaaS provider, we can implement Platform Chaos to initiate chaos testing services too. While this approach does not provide as much control of the server itself, the deployed docker container will keep the JVM consistent across deployments.
+
+If you'd like to learn more you can read these articles:
+ - [Container? Why not App Services?](https://blogs.msdn.microsoft.com/premier_developer/2018/06/15/container-why-not-app-services/)
+ - [Azure Deployment Models](https://stackify.com/azure-deployment-models/)
+
+## Key Benefits
+
+Key technologies and concepts demonstrated:
+
+| Benefit | Supporting Solution
+|---|---
+| Common, standard technologies |
Java programming language Spring Boot Framework, one of the most widely used EE frameworks for Java MongoDB NoSQL API (via Azure Cosmos DB) Redis Cache
+| Production-ready codebase | High quality codebase that is easily enhanced, well-documented and meets typical enterprise code quality standards
+| Well-designed RESTful API | Solution follows RESTful design best-practices
+| Enhanced productivity via Docker| Micros-services implemented in Docker containers, which are hosted by the Azure App Service for Containers PaaS service. Developer productivity enhance due to service isolation and easy service updates
+| Example of well-designed CI/CD pipeline | Full continuous integration/continuous delivery (CI/CD) is implemented using Azure DevOps with a pipeline of environments that support dev, testing and production
+| Automated infrastructure deployment | Azure ARM templates App Service for Containers Azure container registry
+| High Availability/Disaster Recovery (HA/DR) | Full geo-replication of microservices and data, with automatic failover in the event of an issue in any region: Cosmos DB deployed to multiple regions with active-active read/write Session consistency to assure that user experience is consistent across failover Stateless microservices deployed to multiple regions Health monitoring to detect errors that require failover Azure Traffic Manager redirects traffic to healthy region
+| Demonstrates insfrastructure best practices | Application auto-scaling Minimize network latency through geo-based DNS routing API authentication Distributed denial of service (DDoS) protection & mitigation
+| Load and performance testing | The solution includes an integrated traffic simulator to demonstrate that the solution auto-scales properly, maintaining application performance as scale increases
+| Proves application resiliency through chaos testing | A Chaos Monkey-style solution to shut down different portions of the architecture in order to validate that resilience measures keep everything runing in the event of any single failure
+
+## Getting Started With Azure
+
+Follow these instructions to begin using the solution
+
+### Pre-Requisites
+
+- Clone the reference solution to your computer:
+```
+git clone https://@dev.azure.com/csebostoncrew/ProjectJackson/_git/ProjectJackson
+```
+
+- Install [Java 8 (version 1.8)](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
+- Install [the latest Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
+- Install MongoDB:
+ - Windows: [Install MongoDB Community Edition on Windows](https://docs.mongodb.com/v3.2/tutorial/install-mongodb-on-windows/)
+ - MacOS: From a command line, run `brew install mongodb`
+ - Linux: From command line, run `apt-get install mongodb`
+
+Temporary instructions before we have automated deployments running:
+
+### Create Azure Resources
+
+- [Create a resource group](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-portal#manage-resource-groups)
+- [Add a Cosmos DB instance](https://docs.microsoft.com/en-us/azure/cosmos-db/create-mongodb-java#create-a-database-account) to the resource group
+
+*OPTIONAL: Enable the MongoDB Aggregation Pipeline*
+
+The aggregation pipeline must be enabled in order to support aggregation queries like `count()`:
+
+- From the Cosmos DB resource view, click the "Preview Features" option (just below "Connection String")
+- Click the "Enable" button next to "MongoDB Aggregation Pipeline"
+
+### Set up your environment variables
+
+- Open the Cosmos Connection String blade
+- Open the `data/importdata.sh` file.
+- Make sure the Cosmos DB resource is already created as mentioned above, for the next steps to be successful.
+- From Bash command line, run `load_env.sh`. It will will write/load any needed variables to the `vars.env` file.
+ - `RESOURCE_GROUP` - the Azure resource group name
+ - `COSMOSDB_NAME` - the CosmosDB collection name (which is case sensitive)
+ - `COSMOSDB_PASSWORD` - the CosmosDB's password (needed for when you load the data into Cosmos)
+- Load `vars.env` into your environment or VM where the app is being built locally.
+ - `source vars.env`
+ - or in your chosen IDE, set your environment variables within your project.
+- NB: there will also be a DB_NAME and DB_CONNSTR for the Spring application (see the database section below in Application Configuration)
+
+### Prepare the command line
+
+- Switch into the project `data` directory: `cd data`
+- Log into Azure: `az login`
+- If you have multiple subscriptions, confirm that the project subscription is active:
+
+``` Bash
+az account show
+az account set --subscription
+```
+
+### Import the sample IMDb data to Cosmos DB
+
+- Open a Bash command line
+- Download and prepare the required IMDb data files:
+
+``` Bash
+data/getdata.sh
+```
+
+- Before starting to import data make sure the step `Set up your environment variables` is completed.
+- Import the data into Cosmos collections
+
+``` Bash
+data/importdata.sh
+```
+
+### TIP: Explore the data from the MongoDB command-line
+
+- Copy the Cosmos DB connection string from the "Connection String" blade
+- Start the MongoDB CLI with this command: `mongo `
+- Begin executing MongoDB commands, such as:
+
+``` Mongo
+use moviesdb
+show collections
+db.titles.count()
+db.titles.find ({primaryTitle: "Casablanca"})
+```
+
+## Application Configuration
+
+We use [Profiles](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html) for configuration.
+Currently `development` and `production` are possible values for the `spring.profiles.active` property.
+By default, `development` is assumed. Note: `default` is technically it's own profile, that is the same as `development`.
+
+### Authentication
+
+> Note: If you're running with the `development` profile, this is __optional__.
+
+To configure authentication, you'll need to specify your authentication provider's `jwt` or `jwk` key uri. For more information see [the spring docs](https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-security-oauth2-resource-server).
+
+The `OAUTH_KEYSET_URI` environment variable must be set to that uri. For Microsoft Azure, that value can always be `https://login.microsoftonline.com/common/discovery/keys` - this is because a common key set is used for all Azure Active Directory applications.
+
+The `OAUTH_RES_ID` environment variable should (but optionally may not be) set to the application id from the oauth2 provider. If this is omitted the authentication layer will validate whether the token is created by the given provider, but not that it is issued for your specific application.
+
+Learn more about how to configure an Azure Active Directory application [here](./docs/azureActiveDirectory.md).
+
+### Database
+
+> Note: If you're running with the `development` profile, this is __optional__.
+
+To configure communications with a database, the following environment variables are used:
+
++ `DB_CONNSTR` - a mongo [database connection string](https://docs.mongodb.com/manual/reference/connection-string/) (ex: `mongodb://db.com/myDb`)
++ `DB_NAME` - a mongo database name (ex: `myDb`)
++ `EXCLUDE_FILTER` - [optional] a (regex capable) list of classes to exclude from loading (ex: `TitleRepository,PersonRepository`)
+
+### Mock Data
+
+By default, when running with the `development` profile, test data is auto-loaded into the embedded mongo instance.
+However, __if you set the above environment variables, that configuration will take precedence__.
+
+This mock data contains about 8 entries from each collection, and can be found in the `src/main/resources/testdata` folder. There are related entries across each collection to prove out the custom API routes.
+
+### Logging
+
+Spring uses [Commons Logging](https://commons.apache.org/logging) under the hood, more details can be found
+[here](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html).
+To configure logging, the following environment variables can be used:
+
+> Note: These values should be a [valid log level](a valid [log level](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html#boot-features-custom-log-levels))
+
++ `logging.level.root` - Configures the logging level for the whole application, including frameworks
++ `logging.level.com.microsoft.cse.*` - Configures the logging level for our application, excluding frameworks
++ `logging.level.org.zalando.logbook` - Configures the logging of HTTP requests/responses to the console. *Set to TRACE*
++ `logging.level.org.springframework.data.mongodb.core.MongoTemplate` - Configures the logging of a MongoDB query. *Set to DEBUG* to see how any constructed query gets data from MongoDB
+
+To configure [application insights](https://docs.microsoft.com/en-us/azure/application-insights/app-insights-overview) logging, the following environment variable must be set:
+
++ `APPLICATION_INSIGHTS_IKEY` - an [application insights telemetry key](https://docs.microsoft.com/en-us/azure/application-insights/app-insights-java-get-started#1-get-an-application-insights-instrumentation-key)
+
+## Building
+
+> Note: Before running, please make sure everything is [configured](#configuration) to your liking!
+
+To build, use `mvn compile`. To run, use `mvn spring-boot:run`. To run in production, first set the `spring.profiles.active` environment variable to `production` (as per [the above section](#configuration)).
+
+### API Routes
+
+We're using three kinds of models: `Person`, `Title`, and `Principal`. The `Person` model represents a person who participates in media, either in front of the camera or behind the scenes. The `Title` represents what it sounds like - the title of the piece of media, be it a movie, a TV series, or some other kind of similar media. Finally, the `Principal` model and its derivative child class `PrincipalWithName` represent the intersection of Person and Title, ie. what a particular person does or plays in a specific title.
+
+To meaninfully access this IMDb dataset and these models, there are a few routes one can access on the API.
+
++ `/people`
+ + `POST` - Creates a person, and returns information and ID of new person
+ + `GET` - Returns a small number of people entries
++ `/people/{nconst}` > nconst is the unique identifier
+ + `GET` - Gets the person associated with ID, and returns information about the person
+ + `PUT` - Updates a person for a given ID, and returns information about updated person
+ + `DELETE` - Deletes a person with a given ID, and returns the success/failure code
++ `/people/{nconst}/titles` > nconst is the unique identifier
+ + `GET` - Gets the titles in the dataset associated with the person with specified ID and returns them in an array
++ `/titles`
+ + `POST` - Creates a title, and returns the information and ID of the new titles
+ + `GET` - returns a small number of title entries
++ `/titles/{tconst}` > tconst is the unique identifier
+ + `GET` - Gets the title of piece given the ID, and returns information about that title
+ + `PUT` - Updates the title of a piece given the ID, and returns that updated information based on ID
+ + `DELETE` - Deletes the piece of media given the ID, and returns the success/failure code
++ `/titles/{tconst}/people` > tconst is the unique identifier
+ + `GET` - Gets the people in the dataset associated with the given title, and returns that list
++ `/titles/{tconst}/cast` > tconst is the unique identifier
+ + `GET` - Gets the people in the dataset associated with the given title who act, and returns that list
++ `/titles/{tconst}/crew` > tconst is the unique identifier
+ + `GET` - Gets the people in the dataset associated with the given title who participate behind the scenes, and returns that list
+
+For more details, check out the [Swagger documentation](https://dev.azure.com/csebostoncrew/_git/ProjectJackson?path=%2Fswagger.yml).
+
+TODO: Any `upcoming feature` endpoints.
+
+## Testing
+
+To run the tests, use `mvn test`. This project strives to unit test each behavior, and integration test end to end scenarios.
+
+## Contribute
+
+TODO: Explain how other users and developers can contribute to make your code better.
diff --git a/api/.idea/compiler.xml b/api/.idea/compiler.xml
new file mode 100644
index 0000000..cd5890e
--- /dev/null
+++ b/api/.idea/compiler.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/.idea/encodings.xml b/api/.idea/encodings.xml
new file mode 100644
index 0000000..b26911b
--- /dev/null
+++ b/api/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/.idea/misc.xml b/api/.idea/misc.xml
new file mode 100644
index 0000000..5043f3f
--- /dev/null
+++ b/api/.idea/misc.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/.idea/modules.xml b/api/.idea/modules.xml
new file mode 100644
index 0000000..5b5d7ae
--- /dev/null
+++ b/api/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/.idea/vcs.xml b/api/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/api/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/Dockerfile b/api/Dockerfile
new file mode 100644
index 0000000..b0e60e3
--- /dev/null
+++ b/api/Dockerfile
@@ -0,0 +1,17 @@
+# Start with a base image containing Java runtime
+FROM openjdk:8-jdk-alpine
+
+# Add a volume pointing to /tmp
+VOLUME /tmp
+
+# Make port 8080 available to the world outside this container
+EXPOSE 8080
+
+# The application's jar file
+ARG JAR_FILE=target/spring-dal-0.0.1-SNAPSHOT.jar
+
+# Add the application's jar to the container
+ADD ${JAR_FILE} spring-dal.jar
+
+# Run the jar file
+ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/spring-dal.jar"]
\ No newline at end of file
diff --git a/api/SpringDAL.iml b/api/SpringDAL.iml
new file mode 100644
index 0000000..6fecac2
--- /dev/null
+++ b/api/SpringDAL.iml
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/azure-pipelines.yml b/api/azure-pipelines.yml
new file mode 100644
index 0000000..c47fd45
--- /dev/null
+++ b/api/azure-pipelines.yml
@@ -0,0 +1,33 @@
+# Maven
+# Build your Java project and run tests with Apache Maven.
+# Add steps that analyze code, save build artifacts, deploy, and more:
+# https://docs.microsoft.com/azure/devops/pipelines/languages/java
+
+trigger:
+ branches:
+ include:
+ - master
+ paths:
+ include:
+ - api/*
+
+pool:
+ vmImage: 'Ubuntu 16.04'
+
+steps:
+- script: |
+ echo Starting the build
+ cd api/
+ mvn test
+ mvn package
+ displayName: 'Maven test and build'
+- script: |
+ cd api/
+ docker build -t $ACR_SERVER/$ACR_CONTAINER_TAG .
+ displayName: 'Docker Build'
+- script: |
+ docker login $(ACR_SERVER) -u $(ACR_USERNAME) -p $(ACR_PASSWORD)
+ displayName: 'Docker Login'
+- script: |
+ docker push $ACR_SERVER/$ACR_CONTAINER_TAG
+ displayName: 'Docker Push'
\ No newline at end of file
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100644
index 0000000..798ac42
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,109 @@
+
+
+ 4.0.0
+
+ com.microsoft.cse
+ spring-dal
+ 0.0.1-SNAPSHOT
+ jar
+
+ SpringDAL
+ Spring DAL RESTful reference
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.6.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-rest
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+
+ org.springframework.boot
+ spring-boot-starter-oauth2-resource-server
+ 2.1.0.RELEASE
+
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ 2.1.0.RELEASE
+
+
+
+ com.microsoft.azure
+ applicationinsights-web
+ 2.2.1
+
+
+
+ org.zalando
+ logbook-spring-boot-starter
+ 1.11.1
+
+
+
+
+ de.flapdoodle.embed
+ de.flapdoodle.embed.mongo
+ 2.0.0
+
+
+
+
+
+
+ oss-sonartype
+ sonartype
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.1.0
+
+
+
+
+ src/main/resources
+
+
+
+
+
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/SpringDAL.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/SpringDAL.java
new file mode 100644
index 0000000..fff359a
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/SpringDAL.java
@@ -0,0 +1,22 @@
+package com.microsoft.cse.reference.spring.dal;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+
+@SpringBootApplication
+@EnableMongoRepositories
+@EnableAutoConfiguration(exclude = {EmbeddedMongoAutoConfiguration.class})
+@EnableResourceServer
+public class SpringDAL {
+ /**
+ * Application entry point. Scans for spring beans and automatically loads them
+ * @param args passed arguments
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(SpringDAL.class, args);
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/CORSConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/CORSConfig.java
new file mode 100644
index 0000000..19e368b
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/CORSConfig.java
@@ -0,0 +1,41 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.core.env.Environment;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+@Configuration
+public class CORSConfig {
+
+ @Autowired
+ Environment env;
+
+ @Bean
+ public FilterRegistrationBean corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = new CorsConfiguration();
+
+ config.addAllowedOrigin(env.getProperty(Constants.ENV_ALLOWED_ORIGIN));
+ config.addAllowedHeader("*");
+ config.addAllowedMethod(HttpMethod.GET);
+ config.addAllowedMethod(HttpMethod.HEAD);
+ config.addAllowedMethod(HttpMethod.POST);
+ config.addAllowedMethod(HttpMethod.PUT);
+ config.addAllowedMethod(HttpMethod.PATCH);
+ config.addAllowedMethod(HttpMethod.DELETE);
+ config.addAllowedMethod(HttpMethod.OPTIONS);
+ config.addAllowedMethod(HttpMethod.TRACE);
+
+ source.registerCorsConfiguration("/**", config);
+ final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
+ bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
+ return bean;
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/Constants.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/Constants.java
new file mode 100644
index 0000000..f450804
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/Constants.java
@@ -0,0 +1,101 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+public class Constants {
+ /**
+ * The constant that represents our application name
+ */
+ public static final String APP_NAME = "SpringDAL";
+
+ /**
+ * The constant environment variable that we look to for the oauth2 resource id
+ * For more info, see: https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-security-oauth2-resource-server
+ */
+ public static final String ENV_OAUTH_RES_ID = "OAUTH_RES_ID";
+
+ /**
+ * The constant environment variable that we look to for the oauth2 keyset uri
+ * For more info, see: https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-security-oauth2-resource-server
+ */
+ public static final String ENV_OAUTH_KEYSET_URI = "OAUTH_KEYSET_URI";
+
+ /**
+ * The constant environment variable that we look to for production db connection string
+ */
+ public static final String ENV_DB_CONNSTR = "DB_CONNSTR";
+
+ /**
+ * The constant environment variable that we look to for production db name
+ */
+ public static final String ENV_DB_NAME = "DB_NAME";
+
+ /**
+ * The constant environment variable that we look to for exclusion filters
+ * Note: this value may be a comma separated list (ie: ClassA,ClassB)
+ * Note: regex is supported in each entry
+ */
+ public static final String ENV_EXCLUDE_FILTER = "EXCLUDE_FILTER";
+
+ /**
+ * The constant environment variable that we look to for app insights telemetry key
+ * for more information, see the following:
+ * https://docs.microsoft.com/en-us/azure/application-insights/app-insights-java-get-started#1-get-an-application-insights-instrumentation-key
+ */
+ public static final String ENV_APPINSIGHTS_KEY = "APPLICATION_INSIGHTS_IKEY";
+
+ /**
+ * The constant environment variable that we look to for the allowed origins strings for CORS
+ */
+ public static final String ENV_ALLOWED_ORIGIN = "ALLOWED_ORIGIN";
+
+ /**
+ * Error message used to indicate we couldn't read database configuration
+ */
+ public static final String ERR_DB_CONF = "Failed to read database information from configuration";
+
+ /**
+ * Error message used to indicate we couldn't read test data
+ */
+ public static final String ERR_TEST_DATA_FAIL = "Failed to read test data";
+
+ /**
+ * Error message used to indicate we couldn't properly parse test data
+ */
+ public static final String ERR_TEST_DATA_FORMAT = "Json structure must be a top-level array";
+
+ /**
+ * Status message that is used to display our database connection information
+ * Note: should String.format({0}=database info)
+ */
+ public static final String STATUS_DB_CONN_INFO = "Successfully read database configuration %s";
+
+ /**
+ * Status message that is used to indicate we've loaded test data
+ */
+ public static final String STATUS_TEST_DATA_USED = "Successfully loaded test data";
+
+ /**
+ * Status message that is used to indicate we've configured appInsights
+ */
+ public static final String STATUS_APPINSIGHTS_SUCCESS = "Successfully configured appInsights telemetry key";
+
+ /**
+ * Status message that is used to indicate we've failed to configure appInsights:
+ * Note: this isn't an ERR, as appInsights is optional in all cases today
+ */
+ public static final String STATUS_APPINSIGHTS_FAILURE = "Unable to configure appInsights telemetry key";
+
+ /**
+ * The collection from which we pull Person objects
+ */
+ public static final String DB_PERSON_COLLECTION = "names";
+
+ /**
+ * The collection from which we pull Principal objects
+ */
+ public static final String DB_PRINCIPAL_COLLECTION = "principals_mapping";
+
+ /**
+ * The collection from which we pull Title objects
+ */
+ public static final String DB_TITLE_COLLECTION = "titles";
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DatabaseInformation.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DatabaseInformation.java
new file mode 100644
index 0000000..21ade53
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DatabaseInformation.java
@@ -0,0 +1,40 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+/**
+ * Represents a read-only database information object used for connection
+ */
+public class DatabaseInformation {
+ private String connStr;
+ private String name;
+
+ /**
+ * Create an instance of database information with the given connStr and name
+ * @param connStr the connection string
+ * @param name the name
+ */
+ public DatabaseInformation(String connStr, String name) {
+ this.connStr = connStr;
+ this.name = name;
+ }
+
+ /**
+ * The connection string with which to connect to the database
+ * @return connection string
+ */
+ public String getConnectionString() {
+ return this.connStr;
+ }
+
+ /**
+ * The name with which to connect to the database
+ * @return name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String toString() {
+ return '[' + this.getConnectionString() + "]/" + this.getName();
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DevelopmentConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DevelopmentConfig.java
new file mode 100644
index 0000000..c0c6282
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DevelopmentConfig.java
@@ -0,0 +1,78 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+import java.io.IOException;
+
+@Configuration
+@Profile({"development", "default"})
+public class DevelopmentConfig extends WebSecurityConfigurerAdapter implements IApplicationConfig {
+ @Autowired
+ Environment env;
+
+ Logger logger = LoggerFactory.getLogger(DevelopmentConfig.class);
+
+ Net embeddedBindInformation;
+ MongodExecutable embeddedMongoInstance;
+
+ @Override
+ public DatabaseInformation getDatabaseInformation() throws Exception {
+ String connStr = env.getProperty(Constants.ENV_DB_CONNSTR);
+ String name;
+ if (connStr == null) {
+ if (this.embeddedMongoInstance == null) {
+ // we need to try to startup embedded mongo
+ this.embeddedBindInformation = new Net();
+ this.embeddedMongoInstance = this.setupMongoEmbed(this.embeddedBindInformation);
+ }
+
+ connStr = "mongodb://localhost:" + this.embeddedBindInformation.getPort();
+ name = "test";
+ } else {
+ name = env.getRequiredProperty(Constants.ENV_DB_NAME);
+ }
+
+ return new DatabaseInformation(connStr, name);
+ }
+
+ @Override
+ public void configure(WebSecurity webSecurity) throws Exception {
+ // In development mode, we ignore all webSecurity features
+ // effectively disabling oauth2 token requirements
+ webSecurity.ignoring().antMatchers("/**");
+ }
+
+ /**
+ * Attempts to start a mongo instance, using embedMongo
+ * @param bind the net info to bind to
+ * @return the instance
+ * @throws IOException indicates a failure
+ */
+ private MongodExecutable setupMongoEmbed(Net bind) throws IOException {
+ MongodStarter starter;
+ starter = MongodStarter.getDefaultInstance();
+
+ IMongodConfig mongodConfig = new MongodConfigBuilder()
+ .version(Version.Main.DEVELOPMENT)
+ .net(bind)
+ .build();
+
+ MongodExecutable mongodExecutable = starter.prepare(mongodConfig);
+ MongodProcess mongod = mongodExecutable.start();
+ return mongodExecutable;
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DevelopmentEmbeddedData.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DevelopmentEmbeddedData.java
new file mode 100644
index 0000000..26529d2
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/DevelopmentEmbeddedData.java
@@ -0,0 +1,94 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.bson.Document;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.stereotype.Component;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Responsible for populating test data in development deployments
+ */
+@Component
+@Profile({"default", "development"})
+public class DevelopmentEmbeddedData {
+ @Autowired
+ MongoTemplate mongoInterface;
+
+ Logger logger = LoggerFactory.getLogger(MongoConfig.class);
+
+ @EventListener
+ public void onApplicationEvent(ContextRefreshedEvent event) {
+ try {
+ // load all the testdata sets into their given collections
+ mongoInterface.insert(parseTestData("testdata/titles.testdata.json"), Constants.DB_TITLE_COLLECTION);
+ mongoInterface.insert(parseTestData("testdata/names.testdata.json"), Constants.DB_PERSON_COLLECTION);
+ mongoInterface.insert(parseTestData("testdata/principals_mapping.testdata.json"), Constants.DB_PRINCIPAL_COLLECTION);
+
+ logger.info(Constants.STATUS_TEST_DATA_USED);
+ } catch (IOException e) {
+ logger.error(Constants.ERR_TEST_DATA_FAIL, e);
+ }
+ }
+
+ /**
+ * Parse test data from a resources file
+ * @param resourcePath
+ * @return
+ * @throws IOException
+ */
+ private List parseTestData(String resourcePath) throws IOException {
+ ClassPathResource resource = new ClassPathResource(resourcePath);
+ InputStream inputStream = resource.getInputStream();
+
+ // first we read the data
+ StringBuilder textBuilder = new StringBuilder();
+ try (Reader reader = new BufferedReader(new InputStreamReader
+ (inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) {
+ int c = 0;
+ while ((c = reader.read()) != -1) {
+ textBuilder.append((char) c);
+ }
+ }
+
+ String jsonData = textBuilder.toString();
+
+ // then we convert that data to a json node
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jsonNode = mapper.readTree(jsonData);
+
+ // we ensure it is an array of documents to insert
+ if (!jsonNode.isArray()) {
+ throw new InvalidObjectException(Constants.ERR_TEST_DATA_FORMAT);
+ }
+
+ // we parse and store the elements of the array
+ Iterator it = jsonNode.elements();
+ ArrayList results = new ArrayList();
+
+ while (it.hasNext()) {
+ JsonNode node = it.next();
+
+ Document parsed = Document.parse(node.toString());
+
+ results.add(parsed);
+ }
+
+ // return those elements
+ return results;
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/IApplicationConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/IApplicationConfig.java
new file mode 100644
index 0000000..069a73c
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/IApplicationConfig.java
@@ -0,0 +1,10 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+public interface IApplicationConfig {
+ /**
+ * Get the database information object that describes the database we'll connect to
+ * @return Database information object
+ * @throws Exception Thrown when we cannot get this information (usually due to misconfiguration)
+ */
+ DatabaseInformation getDatabaseInformation() throws Exception;
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/MongoConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/MongoConfig.java
new file mode 100644
index 0000000..42d83a5
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/MongoConfig.java
@@ -0,0 +1,63 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientURI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
+import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+
+import java.util.List;
+
+/**
+ * Configures the mongo driver based on our application configuration
+ */
+@Configuration
+@EnableMongoRepositories
+public class MongoConfig extends AbstractMongoConfiguration {
+
+ @Autowired
+ IApplicationConfig appConfig;
+
+ @Autowired
+ List converters;
+
+ Logger logger = LoggerFactory.getLogger(MongoConfig.class);
+
+ @Override
+ public MongoClient mongoClient() {
+ DatabaseInformation info = null;
+ try {
+ info = this.appConfig.getDatabaseInformation();
+
+ logger.info(String.format(Constants.STATUS_DB_CONN_INFO, info));
+ } catch (Exception e) {
+ logger.error(Constants.ERR_DB_CONF, e);
+ }
+
+ return new MongoClient(new MongoClientURI(info.getConnectionString()));
+ }
+
+ @Override
+ protected String getDatabaseName() {
+ DatabaseInformation info = null;
+ try {
+ info = this.appConfig.getDatabaseInformation();
+
+ logger.info(String.format(Constants.STATUS_DB_CONN_INFO, info));
+ } catch (Exception e) {
+ logger.error(Constants.ERR_DB_CONF, e);
+ }
+
+ return info.getName();
+ }
+
+ @Override
+ public MongoCustomConversions customConversions() {
+ return new MongoCustomConversions(converters);
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/OauthConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/OauthConfig.java
new file mode 100644
index 0000000..0f5fd07
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/OauthConfig.java
@@ -0,0 +1,29 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore;
+
+/**
+ * Configure oauth2 resource server
+ */
+@Configuration
+@ConditionalOnProperty(name = {Constants.ENV_OAUTH_KEYSET_URI, Constants.ENV_OAUTH_RES_ID})
+public class OauthConfig extends ResourceServerConfigurerAdapter {
+ @Autowired
+ Environment env;
+
+ @Override
+ public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
+ // setup the resource id
+ resources.resourceId(this.env.getProperty(Constants.ENV_OAUTH_RES_ID));
+
+ // setup the token store
+ resources.tokenStore(new JwkTokenStore(this.env.getProperty(Constants.ENV_OAUTH_KEYSET_URI)));
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/ProductionConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/ProductionConfig.java
new file mode 100644
index 0000000..dbd5889
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/ProductionConfig.java
@@ -0,0 +1,51 @@
+package com.microsoft.cse.reference.spring.dal.config;
+import com.microsoft.applicationinsights.TelemetryConfiguration;
+import com.microsoft.applicationinsights.web.internal.WebRequestTrackingFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+
+@Configuration
+@Profile("production")
+public class ProductionConfig implements IApplicationConfig {
+ @Autowired
+ Environment env;
+
+ Logger logger = LoggerFactory.getLogger(ProductionConfig.class);
+
+ @Override
+ public DatabaseInformation getDatabaseInformation() {
+ return new DatabaseInformation(env.getRequiredProperty(Constants.ENV_DB_CONNSTR),
+ env.getRequiredProperty(Constants.ENV_DB_NAME));
+ }
+
+ /**
+ * Gets the appInsights telemetry configuration information
+ * @return telemetry key
+ */
+ @Bean
+ public String telemetryConfig() {
+ // note: this is optional, if it isn't set we won't use appInsights
+ String telemetryKey = env.getProperty(Constants.ENV_APPINSIGHTS_KEY);
+ if (telemetryKey != null) {
+ TelemetryConfiguration.getActive().setInstrumentationKey(telemetryKey);
+ logger.info(Constants.STATUS_APPINSIGHTS_SUCCESS);
+ } else {
+ logger.info(Constants.STATUS_APPINSIGHTS_FAILURE);
+ }
+ return telemetryKey;
+ }
+
+ /**
+ * Creates bean of type WebRequestTrackingFilter for request tracking to appInsights
+ * @return {@link Bean} of type {@link WebRequestTrackingFilter}
+ */
+ @Bean
+ public WebRequestTrackingFilter appInsightFilter() {
+ return new WebRequestTrackingFilter(Constants.APP_NAME);
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/RepositoryConfig.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/RepositoryConfig.java
new file mode 100644
index 0000000..0e1fcf3
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/config/RepositoryConfig.java
@@ -0,0 +1,52 @@
+package com.microsoft.cse.reference.spring.dal.config;
+
+import com.microsoft.cse.reference.spring.dal.models.Person;
+import com.microsoft.cse.reference.spring.dal.models.Title;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.data.repository.core.RepositoryMetadata;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
+import org.springframework.data.rest.core.mapping.RepositoryDetectionStrategy;
+import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
+
+import java.util.regex.Pattern;
+
+@Configuration
+public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
+ @Autowired
+ Environment env;
+
+ @Override
+ public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
+ // expose the ids for the given model types
+ config.exposeIdsFor(Person.class);
+ config.exposeIdsFor(Title.class);
+
+ // configure how we find and load repositories to let us disable them at runtime with an environment variable
+ config.setRepositoryDetectionStrategy(metadata -> {
+ // if it's not exported, exclude it
+ if (!metadata.getRepositoryInterface().getAnnotation(RepositoryRestResource.class).exported()) {
+ return false;
+ }
+
+ String className = metadata.getRepositoryInterface().getName();
+ String exclusionList = env.getProperty(Constants.ENV_EXCLUDE_FILTER);
+
+ if (exclusionList != null && !exclusionList.isEmpty()) {
+ for (String exclude : exclusionList.split(",")) {
+ // see if we get any hits, treating the exclusion list entry as a regex pattern
+ // note: this allows us to hit 'ClassA' even if it's really 'com.package.ClassA'
+ if (Pattern.compile(exclude).matcher(className).find()) {
+ // exclude if we match
+ return false;
+ }
+ }
+ }
+
+ // default to allowing the repository
+ return true;
+ });
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/CustomEndpointController.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/CustomEndpointController.java
new file mode 100644
index 0000000..b579f1b
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/CustomEndpointController.java
@@ -0,0 +1,223 @@
+package com.microsoft.cse.reference.spring.dal.controllers;
+
+import com.microsoft.cse.reference.spring.dal.converters.IntegerToBoolean;
+import com.microsoft.cse.reference.spring.dal.converters.EmptyStringToNull;
+import com.microsoft.cse.reference.spring.dal.models.PrincipalWithName;
+import com.microsoft.cse.reference.spring.dal.models.Title;
+import org.bson.Document;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.aggregation.*;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+import static java.util.Arrays.asList;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
+
+/**
+ *
+ * Create a custom controller so that when a user hits a URL that's not formatted like the search endpoint
+ *
+ */
+@RestController
+public class CustomEndpointController {
+ private IntegerToBoolean integerToBoolean = new IntegerToBoolean();
+ private EmptyStringToNull emptyStringToNull = new EmptyStringToNull();
+ private MongoTemplate mongoTemplate;
+
+ public CustomEndpointController(MongoTemplate mongoTemplate) {
+ this.mongoTemplate = mongoTemplate;
+ }
+
+ /**
+ * Query the Principals collection via aggregation.
+ *
+ * Since the Mongo/Spring doesn't do a great job with the relational IMDb data we have
+ * and the SDK doesn't have a solution to access the data we want, we have to do some
+ * data transforming.
+ *
+ * example Mongo query that gets us close:
+ * db.principals_mapping.aggregate([
+ * {$match: {"nconst":"nm0000428"}},
+ * {$lookup: {from:"titles", localField:"tconst", foreignField:"tconst", as: "title_info"}},
+ * {$project: {"title_info":{"$arrayElemAt": ["$title_info",0]}, "_id":0}}
+ * ])
+ *
+ * Unfortunately, it seems you can't suppress a field in a projection in Spring, so we get back
+ * data that doesn't properly map into a Title object like we'd want.
+ *
+ * Ideally: if this data was formatted in a more "MongoDB" way, then there would likely be
+ * a Title object embedded into the requested Principal object so no cross-collection,
+ * JOIN-like behavior would be needed. However, the data is not ideal in this way, so we have
+ * to come up with a way to return the needed information.
+ *
+ * @param nconst
+ * @return List of Titles
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/people/{nconst}/titles")
+ public List getAllTitles(@PathVariable String nconst) {
+ MatchOperation filterByNconst = match(Criteria.where("nconst").is(nconst));
+
+ LookupOperation titleLookup = LookupOperation.newLookup()
+ .from("titles")
+ .localField("tconst")
+ .foreignField("tconst")
+ .as("title_info");
+
+ Aggregation aggregation = Aggregation.newAggregation(
+ filterByNconst,
+ titleLookup,
+ project("title_info")
+ );
+
+ AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation, "principals_mapping", Document.class);
+
+ return documentToTitleList(aggregationResults);
+ }
+
+
+ /**
+ * Generates a list from the Principal data set based on the tconst
+ * and has a Person-like object instead of the id.
+ *
+ * @param tconst
+ * @return List of PrincipalWithNames
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/titles/{tconst}/people")
+ public List getAllPeople(@PathVariable String tconst) {
+ MatchOperation filterByNconst = match(Criteria.where("tconst").is(tconst));
+ LookupOperation nameLookup = LookupOperation.newLookup()
+ .from("names")
+ .localField("nconst")
+ .foreignField("nconst")
+ .as("person");
+
+ Aggregation aggregation = Aggregation.newAggregation(
+ filterByNconst,
+ nameLookup
+ );
+
+ AggregationResults results = mongoTemplate.aggregate(aggregation, "principals_mapping", PrincipalWithName.class);
+
+ // removes a clunky "_id" field that is generated when searching MongoDb
+ List mappedResults = results.getMappedResults();
+ for (PrincipalWithName p: mappedResults) {
+ p.person.remove("_id");
+ }
+
+ return mappedResults;
+ }
+
+
+ /**
+ * Generates a list from the Principal data set based on the tconst
+ * and has a Person-like object instead of the id.
+ *
+ * @param tconst
+ * @return List of PrincipalWithNames
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/titles/{tconst}/crew")
+ public List getAllCrew(@PathVariable String tconst) {
+ MatchOperation filterByNconst = match(Criteria.where("tconst").is(tconst));
+ MatchOperation excludeCast = match(Criteria.where("category").ne("actress").andOperator(Criteria.where("category").ne("actor")));
+ LookupOperation nameLookup = LookupOperation.newLookup()
+ .from("names")
+ .localField("nconst")
+ .foreignField("nconst")
+ .as("person");
+
+ Aggregation aggregation = Aggregation.newAggregation(
+ filterByNconst,
+ excludeCast,
+ nameLookup
+ );
+
+ AggregationResults results = mongoTemplate.aggregate(aggregation, "principals_mapping", PrincipalWithName.class);
+
+ // removes a clunky "_id" field that is generated when searching MongoDb
+ List mappedResults = results.getMappedResults();
+ for (PrincipalWithName p: mappedResults) {
+ p.person.remove("_id");
+ }
+
+ return mappedResults;
+ }
+
+
+ /**
+ * Generates a list from the Principal data set based on the tconst
+ * and has a Person-like object instead of the id.
+ *
+ * @param tconst
+ * @return List of PrincipalWithNames
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/titles/{tconst}/cast")
+ public List getAllCast(@PathVariable String tconst) {
+ MatchOperation filterByNconst = match(Criteria.where("tconst").is(tconst));
+ MatchOperation includeCast = match(new Criteria().orOperator(Criteria.where("category").is("actor"), Criteria.where("category").is("actress")));
+ LookupOperation nameLookup = LookupOperation.newLookup()
+ .from("names")
+ .localField("nconst")
+ .foreignField("nconst")
+ .as("person");
+
+ Aggregation aggregation = Aggregation.newAggregation(
+ filterByNconst,
+ includeCast,
+ nameLookup
+ );
+
+ AggregationResults results = mongoTemplate.aggregate(aggregation, "principals_mapping", PrincipalWithName.class);
+
+ // removes a clunky "_id" field that is generated when searching MongoDb
+ List mappedResults = results.getMappedResults();
+ for (PrincipalWithName p: mappedResults) {
+ p.person.remove("_id");
+ }
+
+ return mappedResults;
+ }
+
+
+ /**
+ * Reusable block of code to change the MongoDB document into being
+ * a Title for easier code reading
+ *
+ * @param input
+ * @return List of Title
+ */
+ private List documentToTitleList(AggregationResults input) {
+ List titleList = new ArrayList<>();
+ Iterator iter = input.iterator();
+
+ // Declares reused variables
+ Title t;
+ Document nextDoc, resultDoc;
+ ArrayList titleInfo;
+
+ while (iter.hasNext()){
+ nextDoc = iter.next();
+ titleInfo = (ArrayList) nextDoc.get("title_info");
+ resultDoc = !titleInfo.isEmpty() ? titleInfo.get(0) : null;
+ if (resultDoc != null) {
+ t = new Title();
+
+ t.tconst = (String) resultDoc.get("tconst");
+ t.titleType = (String) resultDoc.get("titleType");
+ t.primaryTitle = (String) resultDoc.get("primaryTitle");
+ t.originalTitle = (String) resultDoc.get("originalTitle");
+ t.isAdult = integerToBoolean.convert(((Integer) resultDoc.get("isAdult")));
+ t.startYear = (Integer) resultDoc.get("startYear");
+ String endYear = emptyStringToNull.convert((String) resultDoc.get("endYear"));
+ t.endYear = endYear == null ? null : Integer.parseInt(endYear);
+ t.runtimeMinutes = (Integer) resultDoc.get("runtimeMinutes");
+ String genres = (String) resultDoc.get("genres");
+ t.genres = genres != null ? asList((genres).split(",")) : null;
+ titleList.add(t);
+ }
+ }
+
+ return titleList;
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/PersonRepository.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/PersonRepository.java
new file mode 100644
index 0000000..ceec9cf
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/PersonRepository.java
@@ -0,0 +1,24 @@
+package com.microsoft.cse.reference.spring.dal.controllers;
+
+import com.microsoft.cse.reference.spring.dal.models.Person;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * Create a repository of Person models (mounted at /people) to facilitate route generation
+ * for model CRUD operations as well as custom queries
+ */
+@Repository
+@RepositoryRestResource(path="people")
+public interface PersonRepository extends MongoRepository {
+ /**
+ * Create a custom query for searching by primaryName
+ * @param primaryName the person primary name
+ * @return the person(s)
+ */
+ List findByPrimaryName(@Param("primaryName") String primaryName);
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/PrincipalRepository.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/PrincipalRepository.java
new file mode 100644
index 0000000..7a631e8
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/PrincipalRepository.java
@@ -0,0 +1,31 @@
+package com.microsoft.cse.reference.spring.dal.controllers;
+
+import com.microsoft.cse.reference.spring.dal.models.Principal;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * Create a repository of Principal models (not externally mounted) to facilitate route generation
+ * for model CRUD operations as well as custom queries
+ */
+@Repository
+@RepositoryRestResource(exported = false)
+public interface PrincipalRepository extends MongoRepository {
+ /**
+ * Create a custom query for searching by tconst
+ * @param tconst the tconst value
+ * @return the principal(s)
+ */
+ List findByTconst(@Param("tconst") String tconst);
+
+ /**
+ * Create a custom query for searching by nconst
+ * @param nconst the nconst value
+ * @return the principal(s)
+ */
+ List findByNconst(@Param("nconst") String nconst);
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/TitleRepository.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/TitleRepository.java
new file mode 100644
index 0000000..8aec6d3
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/controllers/TitleRepository.java
@@ -0,0 +1,24 @@
+package com.microsoft.cse.reference.spring.dal.controllers;
+
+import com.microsoft.cse.reference.spring.dal.models.Title;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * Create a repository of Title models (mounted at /titles) to facilitate route generation
+ * for model CRUD operations as well as custom queries
+ */
+@Repository
+@RepositoryRestResource(path = "titles")
+public interface TitleRepository extends MongoRepository {
+ /**
+ * Create a custom query for searching by primaryTitle
+ * @param primaryTitle the title primary title
+ * @return the title(s)
+ */
+ List findByPrimaryTitle(@Param("primaryTitle") String primaryTitle);
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/BooleanToInteger.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/BooleanToInteger.java
new file mode 100644
index 0000000..11cc584
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/BooleanToInteger.java
@@ -0,0 +1,14 @@
+package com.microsoft.cse.reference.spring.dal.converters;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.WritingConverter;
+import org.springframework.stereotype.Component;
+
+@Component
+@WritingConverter
+public class BooleanToInteger implements Converter {
+ @Override
+ public Integer convert(Boolean bool) {
+ return bool == true ? 1 : 0;
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/EmptyStringToNull.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/EmptyStringToNull.java
new file mode 100644
index 0000000..58eb26b
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/EmptyStringToNull.java
@@ -0,0 +1,14 @@
+package com.microsoft.cse.reference.spring.dal.converters;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+import org.springframework.stereotype.Component;
+
+@Component
+@ReadingConverter
+public class EmptyStringToNull implements Converter {
+ @Override
+ public String convert(String str) {
+ return str == null || str.isEmpty() ? null : str;
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/IntegerToBoolean.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/IntegerToBoolean.java
new file mode 100644
index 0000000..6907213
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/IntegerToBoolean.java
@@ -0,0 +1,14 @@
+package com.microsoft.cse.reference.spring.dal.converters;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+import org.springframework.stereotype.Component;
+
+@Component
+@ReadingConverter
+public class IntegerToBoolean implements Converter {
+ @Override
+ public Boolean convert(Integer integer) {
+ return !(integer == null || integer == 0);
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/JsonArrayToStringList.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/JsonArrayToStringList.java
new file mode 100644
index 0000000..d7884ba
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/JsonArrayToStringList.java
@@ -0,0 +1,55 @@
+package com.microsoft.cse.reference.spring.dal.converters;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Parses json arrays and csv literals to string lists
+ *
+ * Note: we don't convert back, so this is also a data cleaning component - that is,
+ * any new writes will have a normalized schema using an array, not a string literal
+ *
+ * If we didn't want this behavior, we'd need a more complicated @WritingConverter to match
+ */
+@Component
+@ReadingConverter
+public class JsonArrayToStringList implements Converter> {
+ @Override
+ public List convert(String str) {
+ try {
+ str = str.isEmpty() || str == null ? "[]" : str;
+
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jsonNode = mapper.readTree(str);
+
+ if (!jsonNode.isArray()) {
+ throw new IOException(Constants.ERR_TEST_DATA_FORMAT);
+ } else {
+ ArrayList results = new ArrayList<>();
+
+ Iterator it = jsonNode.elements();
+ while (it.hasNext()) {
+ results.add(it.next().asText());
+ }
+
+ return results;
+ }
+ } catch (IOException e) {
+ if (str.contains(",")) {
+ return Arrays.asList(str.split(","));
+ } else {
+ return Arrays.asList(str);
+ }
+ }
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/NullToEmptyString.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/NullToEmptyString.java
new file mode 100644
index 0000000..936f8ea
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/converters/NullToEmptyString.java
@@ -0,0 +1,14 @@
+package com.microsoft.cse.reference.spring.dal.converters;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.WritingConverter;
+import org.springframework.stereotype.Component;
+
+@Component
+@WritingConverter
+public class NullToEmptyString implements Converter {
+ @Override
+ public String convert(String str) {
+ return str == null ? "" : str;
+ }
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Person.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Person.java
new file mode 100644
index 0000000..8945da6
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Person.java
@@ -0,0 +1,20 @@
+package com.microsoft.cse.reference.spring.dal.models;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.util.List;
+
+@Document(collection = Constants.DB_PERSON_COLLECTION)
+public class Person {
+ private ObjectId id;
+ @Id
+ public String nconst;
+ public String primaryName;
+ public Integer birthYear;
+ public Integer deathYear;
+ public List primaryProfession;
+ public List knownForTitles;
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Principal.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Principal.java
new file mode 100644
index 0000000..19a2df0
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Principal.java
@@ -0,0 +1,20 @@
+package com.microsoft.cse.reference.spring.dal.models;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.util.List;
+
+@Document(collection = Constants.DB_PRINCIPAL_COLLECTION)
+public class Principal {
+ @Id
+ private ObjectId id;
+ public String tconst;
+ public Integer ordering;
+ public String nconst;
+ public String category;
+ public String job;
+ public List characters;
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/PrincipalWithName.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/PrincipalWithName.java
new file mode 100644
index 0000000..76dbef1
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/PrincipalWithName.java
@@ -0,0 +1,18 @@
+package com.microsoft.cse.reference.spring.dal.models;
+
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+public class PrincipalWithName {
+ @Id
+ private ObjectId id;
+ public String tconst;
+ public Integer ordering;
+ public LinkedHashMap,?> person;
+ public String category;
+ public String job;
+ public List characters;
+}
diff --git a/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Title.java b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Title.java
new file mode 100644
index 0000000..1bfdc22
--- /dev/null
+++ b/api/src/main/java/com/microsoft/cse/reference/spring/dal/models/Title.java
@@ -0,0 +1,23 @@
+package com.microsoft.cse.reference.spring.dal.models;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.util.List;
+
+@Document(collection = Constants.DB_TITLE_COLLECTION)
+public class Title {
+ private ObjectId id;
+ @Id
+ public String tconst;
+ public String titleType;
+ public String primaryTitle;
+ public String originalTitle;
+ public Boolean isAdult;
+ public Integer startYear;
+ public Integer endYear;
+ public Integer runtimeMinutes;
+ public List genres;
+}
diff --git a/api/src/main/resources/ApplicationInsights.xml b/api/src/main/resources/ApplicationInsights.xml
new file mode 100644
index 0000000..bd0cd34
--- /dev/null
+++ b/api/src/main/resources/ApplicationInsights.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/src/main/resources/testdata/names.testdata.json b/api/src/main/resources/testdata/names.testdata.json
new file mode 100644
index 0000000..349e140
--- /dev/null
+++ b/api/src/main/resources/testdata/names.testdata.json
@@ -0,0 +1,67 @@
+[
+ {
+ "nconst" : "nm0000496",
+ "primaryName" : "Juliette Lewis",
+ "birthYear" : 1973,
+ "deathYear" : "",
+ "primaryProfession" : "actress,soundtrack,director",
+ "knownForTitles" : "tt0116367,tt1322269,tt0110632,tt0101540"
+ },
+ {
+ "nconst" : "nm0000342",
+ "primaryName" : "James Cromwell",
+ "birthYear" : 1940,
+ "deathYear" : "",
+ "primaryProfession" : "actor,producer,soundtrack",
+ "knownForTitles" : "tt0112431,tt0120689,tt2245084,tt0119488"
+ },
+ {
+ "nconst" : "nm0000230",
+ "primaryName" : "Sylvester Stallone",
+ "birthYear" : 1946,
+ "deathYear" : "",
+ "primaryProfession" : "actor,writer,producer",
+ "knownForTitles" : "tt3076658,tt0089927,tt0084602,tt0075148"
+ },
+ {
+ "nconst" : "nm0001500",
+ "primaryName" : "Karl Malden",
+ "birthYear" : 1912,
+ "deathYear" : 2009,
+ "primaryProfession" : "actor,soundtrack,director",
+ "knownForTitles" : "tt0047296,tt0066206,tt0048973,tt0044081"
+ },
+ {
+ "nconst" : "nm0000548",
+ "primaryName" : "Elizabeth Montgomery",
+ "birthYear" : 1933,
+ "deathYear" : 1995,
+ "primaryProfession" : "actress,soundtrack,miscellaneous",
+ "knownForTitles" : "tt0076981,tt0088713,tt0057733,tt0073273"
+ },
+ {
+ "nconst":"nm0000428",
+ "primaryName": "D.W. Griffith",
+ "birthYear": 1875,
+ "deathYear": 1948,
+ "primaryProfession": "director,writer,producer",
+ "knownForTitles": "tt0006864,tt0010484,tt0004972,tt0012532"
+ },
+ {
+ "nconst":"nm0492757",
+ "primaryName": "Florence Lawrence",
+ "birthYear": 1886,
+ "deathYear": 1938,
+ "primaryProfession": "actress",
+ "knownForTitles": "tt0143358,tt0200577,tt0000770,tt0200909"
+ },
+ {
+ "nconst":"nm0555522",
+ "primaryName": "Arthur Marvin",
+ "birthYear": 1859,
+ "deathYear": 1911,
+ "primaryProfession": "cinematographer,director,camera_department",
+ "knownForTitles": "tt0291476,tt0000412,tt0233612,tt0300052"
+ }
+
+]
\ No newline at end of file
diff --git a/api/src/main/resources/testdata/principals_mapping.testdata.json b/api/src/main/resources/testdata/principals_mapping.testdata.json
new file mode 100644
index 0000000..e9c85ae
--- /dev/null
+++ b/api/src/main/resources/testdata/principals_mapping.testdata.json
@@ -0,0 +1,63 @@
+[
+ {
+ "tconst" : "tt0000843",
+ "ordering" : 6,
+ "nconst" : "nm0878494",
+ "category" : "writer",
+ "job" : "story",
+ "characters" : ""
+ },
+ {
+ "tconst" : "tt0000854",
+ "ordering" : 5,
+ "nconst" : "nm0000428",
+ "category" : "director",
+ "job" : "",
+ "characters" : ""
+ },
+ {
+ "tconst" : "tt0000442",
+ "ordering" : 1,
+ "nconst" : "nm0622273",
+ "category" : "actress",
+ "job" : "",
+ "characters" : "[\"Barnemordersken\"]"
+ },
+ {
+ "tconst" : "tt0001008",
+ "ordering" : 1,
+ "nconst" : "nm0819384",
+ "category" : "actress",
+ "job" : "",
+ "characters" : "[\"The Prince\",\"Tom Canty\"]"
+ },
+ {
+ "tconst" : "tt0000698",
+ "ordering" : 3,
+ "nconst" : "nm0000428",
+ "category" : "actor",
+ "job" : "",
+ "characters" : "[\"Footman\"]"
+ },
+ {
+ "tconst" : "tt0092377",
+ "ordering" : 4,
+ "nconst" : "nm0000496",
+ "category" : "actress",
+ "characters" : "[\"Kate Farrell\"]"
+ },
+ {
+ "tconst" : "tt0000698",
+ "ordering" : 1,
+ "nconst" : "nm0492757",
+ "category" : "actress",
+ "characters" : "[\"O'Yama\"]"
+ },
+ {
+ "tconst" : "tt0000698",
+ "ordering" : 6,
+ "nconst" : "nm0555522",
+ "category" : "cinematographer",
+ "characters" : ""
+ }
+]
\ No newline at end of file
diff --git a/api/src/main/resources/testdata/titles.testdata.json b/api/src/main/resources/testdata/titles.testdata.json
new file mode 100644
index 0000000..bb4f896
--- /dev/null
+++ b/api/src/main/resources/testdata/titles.testdata.json
@@ -0,0 +1,68 @@
+[
+ {
+ "tconst" : "tt0000003",
+ "titleType" : "short",
+ "primaryTitle" : "Pauvre Pierrot",
+ "originalTitle" : "Pauvre Pierrot",
+ "isAdult" : 0,
+ "startYear" : 1892,
+ "endYear" : "",
+ "runtimeMinutes" : 4,
+ "genres" : "Animation,Comedy,Romance"
+ },
+ {
+ "tconst" : "tt0000192",
+ "titleType" : "short",
+ "primaryTitle" : "Ella Lola, a la Trilby",
+ "originalTitle" : "Ella Lola, a la Trilby",
+ "isAdult" : 0,
+ "startYear" : 1898,
+ "endYear" : "",
+ "runtimeMinutes" : "",
+ "genres" : "Short"
+ },
+ {
+ "tconst" : "tt0001022",
+ "titleType" : "short",
+ "primaryTitle" : "A Rose of the Tenderloin",
+ "originalTitle" : "A Rose of the Tenderloin",
+ "isAdult" : 0,
+ "startYear" : 1909,
+ "endYear" : "",
+ "runtimeMinutes" : "",
+ "genres" : "Drama,Short"
+ },
+ {
+ "tconst" : "tt0001008",
+ "titleType" : "short",
+ "primaryTitle" : "The Prince and the Pauper",
+ "originalTitle" : "The Prince and the Pauper",
+ "isAdult" : 0,
+ "startYear" : 1909,
+ "endYear" : "",
+ "runtimeMinutes" : "",
+ "genres" : "Short"
+ },
+ {
+ "tconst" : "tt0075472",
+ "titleType" : "tvSeries",
+ "primaryTitle" : "All Creatures Great and Small",
+ "originalTitle" : "All Creatures Great and Small",
+ "isAdult" : 0,
+ "startYear" : 1978,
+ "endYear" : 1990,
+ "runtimeMinutes" : 50,
+ "genres" : "Comedy,Drama"
+ },
+ {
+ "tconst":"tt0000698",
+ "titleType": "short",
+ "primaryTitle": "The Heart of O Yama",
+ "originalTitle": "The Heart of O Yama",
+ "isAdult": 0,
+ "startYear": 1908,
+ "endYear": "",
+ "runtimeMinutes": 15,
+ "genres": "Drama,Romance,Short"
+ }
+]
\ No newline at end of file
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/BasicExclusionTests.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/BasicExclusionTests.java
new file mode 100644
index 0000000..9c1fb56
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/BasicExclusionTests.java
@@ -0,0 +1,40 @@
+package com.microsoft.cse.reference.spring.dal.integration;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ContextConfiguration(initializers = BasicExclusionTests.Config.class)
+public class BasicExclusionTests {
+ @Autowired
+ TestRestTemplate rest;
+
+ @LocalServerPort
+ Integer httpPort;
+
+ @Test
+ public void ExcludeTitleRepository() {
+ ResponseEntity res = this.rest.getForEntity("http://localhost:" + httpPort + "/titles", String.class);
+ Assert.assertTrue(res.getStatusCode().is4xxClientError());
+ }
+
+ /**
+ * A configuration instance for these tests
+ */
+ public static class Config extends PropertyMockingApplicationContextInitializer {
+ @Override
+ protected String[] getExcludeList() {
+ // we wish to disable the TitleRepository for the tests above, so we exclude them
+ return new String[] { "TitleRepository" };
+ }
+ }
+}
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/BasicRouteTests.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/BasicRouteTests.java
new file mode 100644
index 0000000..76578a4
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/BasicRouteTests.java
@@ -0,0 +1,371 @@
+package com.microsoft.cse.reference.spring.dal.integration;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Note: we do integration tests for the endpoints, as unit tests aren't feasible
+ * https://stackoverflow.com/questions/23435937/how-to-test-spring-data-repositories
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ContextConfiguration(initializers = BasicRouteTests.Config.class)
+public class BasicRouteTests {
+ @Autowired
+ TestRestTemplate rest;
+
+ @LocalServerPort
+ Integer httpPort;
+
+ @Test
+ public void ValidateTitlesEndpoint() throws JSONException {
+ String obj = this.rest.getForObject("http://localhost:" + httpPort + "/titles", String.class);
+
+ String raw = "{\n" +
+ " \"_embedded\" : {\n" +
+ " \"titles\" : [ {\n" +
+ " \"tconst\" : \"tt0000003\",\n" +
+ " \"titleType\" : \"short\",\n" +
+ " \"primaryTitle\" : \"Pauvre Pierrot\",\n" +
+ " \"originalTitle\" : \"Pauvre Pierrot\",\n" +
+ " \"isAdult\" : false,\n" +
+ " \"startYear\" : 1892,\n" +
+ " \"endYear\" : null,\n" +
+ " \"runtimeMinutes\" : 4,\n" +
+ " \"genres\" : [ \"Animation\", \"Comedy\", \"Romance\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0000003\"\n" +
+ " },\n" +
+ " \"title\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0000003\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"tconst\" : \"tt0000192\",\n" +
+ " \"titleType\" : \"short\",\n" +
+ " \"primaryTitle\" : \"Ella Lola, a la Trilby\",\n" +
+ " \"originalTitle\" : \"Ella Lola, a la Trilby\",\n" +
+ " \"isAdult\" : false,\n" +
+ " \"startYear\" : 1898,\n" +
+ " \"endYear\" : null,\n" +
+ " \"runtimeMinutes\" : null,\n" +
+ " \"genres\" : [ \"Short\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0000192\"\n" +
+ " },\n" +
+ " \"title\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0000192\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"tconst\" : \"tt0001022\",\n" +
+ " \"titleType\" : \"short\",\n" +
+ " \"primaryTitle\" : \"A Rose of the Tenderloin\",\n" +
+ " \"originalTitle\" : \"A Rose of the Tenderloin\",\n" +
+ " \"isAdult\" : false,\n" +
+ " \"startYear\" : 1909,\n" +
+ " \"endYear\" : null,\n" +
+ " \"runtimeMinutes\" : null,\n" +
+ " \"genres\" : [ \"Drama\", \"Short\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0001022\"\n" +
+ " },\n" +
+ " \"title\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0001022\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"tconst\" : \"tt0001008\",\n" +
+ " \"titleType\" : \"short\",\n" +
+ " \"primaryTitle\" : \"The Prince and the Pauper\",\n" +
+ " \"originalTitle\" : \"The Prince and the Pauper\",\n" +
+ " \"isAdult\" : false,\n" +
+ " \"startYear\" : 1909,\n" +
+ " \"endYear\" : null,\n" +
+ " \"runtimeMinutes\" : null,\n" +
+ " \"genres\" : [ \"Short\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0001008\"\n" +
+ " },\n" +
+ " \"title\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0001008\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"tconst\" : \"tt0075472\",\n" +
+ " \"titleType\" : \"tvSeries\",\n" +
+ " \"primaryTitle\" : \"All Creatures Great and Small\",\n" +
+ " \"originalTitle\" : \"All Creatures Great and Small\",\n" +
+ " \"isAdult\" : false,\n" +
+ " \"startYear\" : 1978,\n" +
+ " \"endYear\" : 1990,\n" +
+ " \"runtimeMinutes\" : 50,\n" +
+ " \"genres\" : [ \"Comedy\", \"Drama\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0075472\"\n" +
+ " },\n" +
+ " \"title\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/tt0075472\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"titleType\": \"short\",\n" +
+ " \"primaryTitle\": \"The Heart of O Yama\",\n" +
+ " \"originalTitle\": \"The Heart of O Yama\",\n" +
+ " \"isAdult\": false,\n" +
+ " \"startYear\": 1908,\n" +
+ " \"endYear\": null,\n" +
+ " \"runtimeMinutes\": 15,\n" +
+ " \"genres\": [ \"Drama\", \"Romance\", \"Short\" ],\n" +
+ " \"_links\": {\n" +
+ " \"self\": {\n" +
+ " \"href\": \"http://localhost:8080/titles/tt0000698\"\n" +
+ " },\n" +
+ " \"title\": {\n" +
+ " \"href\": \"http://localhost:8080/titles/tt0000698\"\n" +
+ " }\n" +
+ " }\n" +
+ " } ]" +
+ " }, " +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles{?page,size,sort}\",\n" +
+ " \"templated\" : true\n" +
+ " },\n" +
+ " \"profile\" : {\n" +
+ " \"href\" : \"http://localhost:8080/profile/titles\"\n" +
+ " },\n" +
+ " \"search\" : {\n" +
+ " \"href\" : \"http://localhost:8080/titles/search\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"page\" : {\n" +
+ " \"size\" : 20,\n" +
+ " \"totalElements\" : 6,\n" +
+ " \"totalPages\" : 1,\n" +
+ " \"number\" : 0\n" +
+ " }\n" +
+ "}";
+
+ raw = raw.replace("localhost:8080/", "localhost:" + httpPort + "/");
+
+ JSONObject expected = new JSONObject(raw);
+ JSONAssert.assertEquals(expected, new JSONObject(obj), true);
+ }
+
+ @Test
+ public void ValidatePeopleEndpoint() throws JSONException {
+ String obj = this.rest.getForObject("http://localhost:" + httpPort + "/people", String.class);
+
+ String raw = "{\n" +
+ " \"_embedded\" : {\n" +
+ " \"persons\" : [ {\n" +
+ " \"nconst\" : \"nm0000496\",\n" +
+ " \"primaryName\" : \"Juliette Lewis\",\n" +
+ " \"birthYear\" : 1973,\n" +
+ " \"deathYear\" : null,\n" +
+ " \"primaryProfession\" : [ \"actress\", \"soundtrack\", \"director\" ],\n" +
+ " \"knownForTitles\" : [ \"tt0116367\", \"tt1322269\", \"tt0110632\", \"tt0101540\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000496\"\n" +
+ " },\n" +
+ " \"person\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000496\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\" : \"nm0000342\",\n" +
+ " \"primaryName\" : \"James Cromwell\",\n" +
+ " \"birthYear\" : 1940,\n" +
+ " \"deathYear\" : null,\n" +
+ " \"primaryProfession\" : [ \"actor\", \"producer\", \"soundtrack\" ],\n" +
+ " \"knownForTitles\" : [ \"tt0112431\", \"tt0120689\", \"tt2245084\", \"tt0119488\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000342\"\n" +
+ " },\n" +
+ " \"person\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000342\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\" : \"nm0000230\",\n" +
+ " \"primaryName\" : \"Sylvester Stallone\",\n" +
+ " \"birthYear\" : 1946,\n" +
+ " \"deathYear\" : null,\n" +
+ " \"primaryProfession\" : [ \"actor\", \"writer\", \"producer\" ],\n" +
+ " \"knownForTitles\" : [ \"tt3076658\", \"tt0089927\", \"tt0084602\", \"tt0075148\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000230\"\n" +
+ " },\n" +
+ " \"person\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000230\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\" : \"nm0001500\",\n" +
+ " \"primaryName\" : \"Karl Malden\",\n" +
+ " \"birthYear\" : 1912,\n" +
+ " \"deathYear\" : 2009,\n" +
+ " \"primaryProfession\" : [ \"actor\", \"soundtrack\", \"director\" ],\n" +
+ " \"knownForTitles\" : [ \"tt0047296\", \"tt0066206\", \"tt0048973\", \"tt0044081\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0001500\"\n" +
+ " },\n" +
+ " \"person\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0001500\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\" : \"nm0000548\",\n" +
+ " \"primaryName\" : \"Elizabeth Montgomery\",\n" +
+ " \"birthYear\" : 1933,\n" +
+ " \"deathYear\" : 1995,\n" +
+ " \"primaryProfession\" : [ \"actress\", \"soundtrack\", \"miscellaneous\" ],\n" +
+ " \"knownForTitles\" : [ \"tt0076981\", \"tt0088713\", \"tt0057733\", \"tt0073273\" ],\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000548\"\n" +
+ " },\n" +
+ " \"person\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/nm0000548\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\": \"nm0000428\",\n" +
+ " \"primaryName\": \"D.W. Griffith\",\n" +
+ " \"birthYear\": 1875,\n" +
+ " \"deathYear\": 1948,\n" +
+ " \"primaryProfession\": [ \"director\", \"writer\", \"producer\" ],\n" +
+ " \"knownForTitles\": [ \"tt0006864\", \"tt0010484\", \"tt0004972\", \"tt0012532\" ],\n" +
+ " \"_links\": {\n" +
+ " \"self\": {\n" +
+ " \"href\": \"http://localhost:8080/people/nm0000428\"\n" +
+ " },\n" +
+ " \"person\": {\n" +
+ " \"href\": \"http://localhost:8080/people/nm0000428\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\": \"nm0492757\",\n" +
+ " \"primaryName\": \"Florence Lawrence\",\n" +
+ " \"birthYear\": 1886,\n" +
+ " \"deathYear\": 1938,\n" +
+ " \"primaryProfession\": [\n \"actress\" ],\n" +
+ " \"knownForTitles\": [ \"tt0143358\", \"tt0200577\", \"tt0000770\", \"tt0200909\" ],\n" +
+ " \"_links\": {\n" +
+ " \"self\": {\n" +
+ " \"href\": \"http://localhost:8080/people/nm0492757\"\n" +
+ " },\n" +
+ " \"person\": {\n" +
+ " \"href\": \"http://localhost:8080/people/nm0492757\"\n" +
+ " }\n" +
+ " }\n" +
+ " }, {\n" +
+ " \"nconst\": \"nm0555522\",\n" +
+ " \"primaryName\": \"Arthur Marvin\",\n" +
+ " \"birthYear\": 1859,\n" +
+ " \"deathYear\": 1911,\n" +
+ " \"primaryProfession\": [ \"cinematographer\", \"director\", \"camera_department\" ],\n" +
+ " \"knownForTitles\": [ \"tt0291476\", \"tt0000412\", \"tt0233612\", \"tt0300052\" ],\n" +
+ " \"_links\": {\n" +
+ " \"self\": {\n" +
+ " \"href\": \"http://localhost:8080/people/nm0555522\"\n" +
+ " },\n" +
+ " \"person\": {\n" +
+ " \"href\": \"http://localhost:8080/people/nm0555522\"\n" +
+ " }\n" +
+ " }\n" +
+ " }" +
+ " ]\n" +
+ "},\n" +
+ " \"_links\" : {\n" +
+ " \"self\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people{?page,size,sort}\",\n" +
+ " \"templated\" : true\n" +
+ " },\n" +
+ " \"profile\" : {\n" +
+ " \"href\" : \"http://localhost:8080/profile/people\"\n" +
+ " },\n" +
+ " \"search\" : {\n" +
+ " \"href\" : \"http://localhost:8080/people/search\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"page\" : {\n" +
+ " \"size\" : 20,\n" +
+ " \"totalElements\" : 8,\n" +
+ " \"totalPages\" : 1,\n" +
+ " \"number\" : 0\n" +
+ " }\n" +
+ "}";
+ raw = raw.replace("localhost:8080/", "localhost:" + httpPort + "/");
+
+ JSONObject expected = new JSONObject(raw);
+ JSONAssert.assertEquals(expected, new JSONObject(obj), true);
+ }
+
+ @Test
+ public void CORS_Success_TitlesEndpointResponse() throws URISyntaxException {
+
+ ResponseEntity resTitles = this.rest.exchange(RequestEntity
+ .get(new URI("http://localhost:" + httpPort + "/titles"))
+ .header(HttpHeaders.ORIGIN, "http://test.com")
+ .build(),
+ String.class
+ );
+
+ Assert.assertTrue(resTitles.getStatusCode().is2xxSuccessful());
+ Assert.assertEquals(resTitles.getHeaders().getAccessControlAllowOrigin(), "*");
+ }
+
+
+ @Test
+ public void CORS_Success_PeopleEndpointResponse() throws URISyntaxException {
+
+ ResponseEntity resPeople = this.rest.exchange(RequestEntity
+ .get(new URI("http://localhost:" + httpPort + "/people"))
+ .header(HttpHeaders.ORIGIN, "http://test.com")
+ .build(),
+ String.class
+ );
+
+ Assert.assertTrue(resPeople.getStatusCode().is2xxSuccessful());
+ Assert.assertEquals(resPeople.getHeaders().getAccessControlAllowOrigin(), "*");
+ }
+
+ /**
+ * A configuration instance for these tests
+ */
+ public static class Config extends PropertyMockingApplicationContextInitializer {
+ @Override
+ protected String getAllowedOrigin() {
+ // we wish to allow * with CORS for the tests above
+ return "*";
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/CustomRouteTests.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/CustomRouteTests.java
new file mode 100644
index 0000000..535887d
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/CustomRouteTests.java
@@ -0,0 +1,192 @@
+package com.microsoft.cse.reference.spring.dal.integration;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ContextConfiguration(initializers = CustomRouteTests.Config.class)
+public class CustomRouteTests {
+ @Autowired
+ TestRestTemplate rest;
+
+ @LocalServerPort
+ Integer httpPort;
+
+ @Test
+ public void ValidatePeopleFromTitlesEndpoint() throws JSONException {
+ String obj = this.rest.getForObject("http://localhost:" + httpPort + "/titles/tt0000698/people", String.class);
+
+ String raw = "[\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"ordering\": 3,\n" +
+ " \"person\": {\n" +
+ " \"nconst\": \"nm0000428\",\n" +
+ " \"primaryName\": \"D.W. Griffith\",\n" +
+ " \"birthYear\": 1875,\n" +
+ " \"deathYear\": 1948,\n" +
+ " \"primaryProfession\": \"director,writer,producer\",\n" +
+ " \"knownForTitles\": \"tt0006864,tt0010484,tt0004972,tt0012532\"\n" +
+ " },\n" +
+ " \"category\": \"actor\",\n" +
+ " \"job\": null,\n" +
+ " \"characters\": [\n" +
+ " \"Footman\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"ordering\": 1,\n" +
+ " \"person\": {\n" +
+ " \"nconst\": \"nm0492757\",\n" +
+ " \"primaryName\": \"Florence Lawrence\",\n" +
+ " \"birthYear\": 1886,\n" +
+ " \"deathYear\": 1938,\n" +
+ " \"primaryProfession\": \"actress\",\n" +
+ " \"knownForTitles\": \"tt0143358,tt0200577,tt0000770,tt0200909\"\n" +
+ " },\n" +
+ " \"category\": \"actress\",\n" +
+ " \"job\": null,\n" +
+ " \"characters\": [\n" +
+ " \"O'Yama\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"ordering\": 6,\n" +
+ " \"person\": {\n" +
+ " \"nconst\": \"nm0555522\",\n" +
+ " \"primaryName\": \"Arthur Marvin\",\n" +
+ " \"birthYear\": 1859,\n" +
+ " \"deathYear\": 1911,\n" +
+ " \"primaryProfession\": \"cinematographer,director,camera_department\",\n" +
+ " \"knownForTitles\": \"tt0291476,tt0000412,tt0233612,tt0300052\"\n" +
+ " },\n" +
+ " \"category\": \"cinematographer\",\n" +
+ " \"job\": null,\n" +
+ " \"characters\": []\n" +
+ " }\n" +
+ "]";
+
+ JSONArray expected = new JSONArray(raw);
+ JSONAssert.assertEquals(expected, new JSONArray(obj), true);
+ }
+
+ @Test
+ public void ValidateCastFromTitlesEndpoint() throws JSONException {
+ String obj = this.rest.getForObject("http://localhost:" + httpPort + "/titles/tt0000698/cast", String.class);
+
+ String raw = "[\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"ordering\": 3,\n" +
+ " \"person\": {\n" +
+ " \"nconst\": \"nm0000428\",\n" +
+ " \"primaryName\": \"D.W. Griffith\",\n" +
+ " \"birthYear\": 1875,\n" +
+ " \"deathYear\": 1948,\n" +
+ " \"primaryProfession\": \"director,writer,producer\",\n" +
+ " \"knownForTitles\": \"tt0006864,tt0010484,tt0004972,tt0012532\"\n" +
+ " },\n" +
+ " \"category\": \"actor\",\n" +
+ " \"job\": null,\n" +
+ " \"characters\": [\n" +
+ " \"Footman\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"ordering\": 1,\n" +
+ " \"person\": {\n" +
+ " \"nconst\": \"nm0492757\",\n" +
+ " \"primaryName\": \"Florence Lawrence\",\n" +
+ " \"birthYear\": 1886,\n" +
+ " \"deathYear\": 1938,\n" +
+ " \"primaryProfession\": \"actress\",\n" +
+ " \"knownForTitles\": \"tt0143358,tt0200577,tt0000770,tt0200909\"\n" +
+ " },\n" +
+ " \"category\": \"actress\",\n" +
+ " \"job\": null,\n" +
+ " \"characters\": [\n" +
+ " \"O'Yama\"\n" +
+ " ]\n" +
+ " }\n" +
+ "]";
+
+ JSONArray expected = new JSONArray(raw);
+ JSONAssert.assertEquals(expected, new JSONArray(obj), true);
+ }
+
+ @Test
+ public void ValidateCrewFromTitlesEndpoint() throws JSONException {
+ String obj = this.rest.getForObject("http://localhost:" + httpPort + "/titles/tt0000698/crew", String.class);
+
+ String raw = "[\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"ordering\": 6,\n" +
+ " \"person\": {\n" +
+ " \"nconst\": \"nm0555522\",\n" +
+ " \"primaryName\": \"Arthur Marvin\",\n" +
+ " \"birthYear\": 1859,\n" +
+ " \"deathYear\": 1911,\n" +
+ " \"primaryProfession\": \"cinematographer,director,camera_department\",\n" +
+ " \"knownForTitles\": \"tt0291476,tt0000412,tt0233612,tt0300052\"\n" +
+ " },\n" +
+ " \"category\": \"cinematographer\",\n" +
+ " \"job\": null,\n" +
+ " \"characters\": []\n" +
+ " }\n" +
+ "]";
+
+ JSONArray expected = new JSONArray(raw);
+ JSONAssert.assertEquals(expected, new JSONArray(obj), true);
+ }
+
+ @Test
+ public void ValidateTitlesFromPeopleEndpoint() throws JSONException {
+ String obj = this.rest.getForObject("http://localhost:" + httpPort + "/people/nm0000428/titles", String.class);
+
+ String raw = "[\n" +
+ " {\n" +
+ " \"tconst\": \"tt0000698\",\n" +
+ " \"titleType\": \"short\",\n" +
+ " \"primaryTitle\": \"The Heart of O Yama\",\n" +
+ " \"originalTitle\": \"The Heart of O Yama\",\n" +
+ " \"isAdult\": false,\n" +
+ " \"startYear\": 1908,\n" +
+ " \"endYear\": null,\n" +
+ " \"runtimeMinutes\": 15,\n" +
+ " \"genres\": [\n" +
+ " \"Drama\",\n" +
+ " \"Romance\",\n" +
+ " \"Short\"\n" +
+ " ]\n" +
+ " }\n" +
+ "]";
+
+ JSONArray expected = new JSONArray(raw);
+ JSONAssert.assertEquals(expected, new JSONArray(obj), true);
+ }
+
+ /**
+ * A configuration instance for these tests
+ */
+ public static class Config extends PropertyMockingApplicationContextInitializer {
+ @Override
+ protected String getAllowedOrigin() {
+ // we wish to allow * with CORS for the tests above
+ return "*";
+ }
+ }
+}
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/Helpers.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/Helpers.java
new file mode 100644
index 0000000..670175a
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/Helpers.java
@@ -0,0 +1,35 @@
+package com.microsoft.cse.reference.spring.dal.integration;
+
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+
+import java.io.IOException;
+
+/**
+ * Integration test utilities
+ */
+public class Helpers {
+ /**
+ * Setup a mongo instance
+ * @param net the net instance to bind to
+ * @return the mongo instance
+ * @throws IOException thrown when unable to bind
+ */
+ static MongodExecutable SetupMongo(Net net) throws IOException {
+ MongodStarter starter = MongodStarter.getDefaultInstance();
+
+ IMongodConfig mongodConfig = new MongodConfigBuilder()
+ .version(Version.Main.DEVELOPMENT)
+ .net(net)
+ .build();
+
+ MongodExecutable mongoProc = starter.prepare(mongodConfig);
+ mongoProc.start();
+
+ return mongoProc;
+ }
+}
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/PropertyMockingApplicationContextInitializer.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/PropertyMockingApplicationContextInitializer.java
new file mode 100644
index 0000000..64fe4dd
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/integration/PropertyMockingApplicationContextInitializer.java
@@ -0,0 +1,97 @@
+package com.microsoft.cse.reference.spring.dal.integration;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.config.Net;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.StandardEnvironment;
+import org.springframework.mock.env.MockPropertySource;
+
+import java.io.IOException;
+
+/**
+ * Allows mocking of application context properties
+ */
+public abstract class PropertyMockingApplicationContextInitializer implements ApplicationContextInitializer {
+ /**
+ * Get the mongo data repository exclusion list
+ * @apiNote see Constants.ENV_EXCLUDE_FILTER for more info
+ * @return the mongo data repository exclusion list
+ */
+ protected String[] getExcludeList() {
+ return new String[0];
+ }
+
+ /**
+ * Get the CORS allowed origin value
+ * @return the CORS allowed origin value
+ */
+ protected String getAllowedOrigin() { return ""; }
+
+
+ /**
+ * Get the net binding information for the embedded mongo server
+ * @return net binding information
+ */
+ protected Net getMongoNet() {
+ try {
+ return new Net();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Get the database name
+ * @return the database name
+ */
+ protected String getDbName() {
+ return "test";
+ }
+
+ /**
+ * Get the embedded mongo server instance
+ * @param bind the net binding information to bind to
+ * @return the embedded mongo server instance
+ */
+ protected MongodExecutable getMongo(Net bind) {
+ try {
+ return Helpers.SetupMongo(bind);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Get the rest template builder with which to test rest endpoints
+ * @return the rest template builder
+ */
+ protected RestTemplateBuilder getRestTemplateBuilder() {
+ return new RestTemplateBuilder().setConnectTimeout(1000).setReadTimeout(1000);
+ }
+
+ @Override
+ public void initialize(ConfigurableApplicationContext applicationContext) {
+ // configure a net binding instance
+ Net mongoNet = this.getMongoNet();
+
+ // register some autowire-able dependencies, to make leveraging the configured instances in a test possible
+ applicationContext.getBeanFactory().registerResolvableDependency(RestTemplateBuilder.class, this.getRestTemplateBuilder());
+ applicationContext.getBeanFactory().registerResolvableDependency(Net.class, mongoNet);
+ applicationContext.getBeanFactory().registerResolvableDependency(MongodExecutable.class, this.getMongo(mongoNet));
+
+ // configure the property sources that will be used by the application
+ MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources();
+ MockPropertySource mockEnvVars = new MockPropertySource()
+ .withProperty(Constants.ENV_DB_NAME, this.getDbName())
+ .withProperty(Constants.ENV_DB_CONNSTR, "mongodb://localhost:" + mongoNet.getPort())
+ .withProperty(Constants.ENV_ALLOWED_ORIGIN, this.getAllowedOrigin())
+ .withProperty(Constants.ENV_EXCLUDE_FILTER, String.join(",", this.getExcludeList()));
+
+ // inject the property sources into the application as environment variables
+ propertySources.replace(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, mockEnvVars);
+ }
+}
\ No newline at end of file
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/PersonDataTests.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/PersonDataTests.java
new file mode 100644
index 0000000..3f827d7
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/PersonDataTests.java
@@ -0,0 +1,160 @@
+package com.microsoft.cse.reference.spring.dal.unit;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import com.microsoft.cse.reference.spring.dal.config.DevelopmentConfig;
+import com.microsoft.cse.reference.spring.dal.config.MongoConfig;
+import com.microsoft.cse.reference.spring.dal.controllers.PersonRepository;
+import com.microsoft.cse.reference.spring.dal.converters.BooleanToInteger;
+import com.microsoft.cse.reference.spring.dal.converters.IntegerToBoolean;
+import com.microsoft.cse.reference.spring.dal.models.Person;
+import org.bson.Document;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration;
+import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Define the tests using the built-in DataMongoTest attribute
+ * However, since the builtin doesn't load other beans, we need to load
+ * the converters, and the config that loads the converters - we do that with @Import
+ */
+@RunWith(SpringRunner.class)
+@DataMongoTest
+@EnableWebSecurity
+@EnableResourceServer
+@Import({IntegerToBoolean.class,
+ BooleanToInteger.class,
+ MongoConfig.class,
+ DevelopmentConfig.class})
+public class PersonDataTests {
+ @Autowired
+ public MongoTemplate mongoTemplate;
+
+ @Autowired
+ public PersonRepository repo;
+
+ @Before
+ public void setUp() {
+ this.mongoTemplate.dropCollection(Constants.DB_PERSON_COLLECTION);
+
+ this.mongoTemplate.insert(Document.parse("{\n" +
+ " \"nconst\" : \"nm0001500\",\n" +
+ " \"primaryName\" : \"Karl Malden\",\n" +
+ " \"birthYear\" : 1912,\n" +
+ " \"deathYear\" : 2009,\n" +
+ " \"primaryProfession\" : \"actor,soundtrack,director\",\n" +
+ " \"knownForTitles\" : \"tt0047296,tt0066206,tt0048973,tt0044081\"\n" +
+ " },"), Constants.DB_PERSON_COLLECTION);
+ }
+
+ @Test
+ public void findById_Success() {
+ Person actual = this.repo.findById("nm0001500").get();
+
+ assertThat(actual.nconst, is("nm0001500"));
+ assertThat(actual.primaryName, is("Karl Malden"));
+ assertThat(actual.birthYear, is(1912));
+ assertThat(actual.deathYear, is(2009));
+ assertThat(actual.primaryProfession, is(Arrays.asList("actor", "soundtrack", "director")));
+ assertThat(actual.knownForTitles, is(Arrays.asList("tt0047296", "tt0066206", "tt0048973", "tt0044081")));
+ }
+
+ @Test
+ public void findById_Failure() {
+ Optional actual = this.repo.findById("not-real");
+
+ assertThat(actual.isPresent(), is(false));
+ }
+
+ @Test
+ public void findByPrimaryName_Success() {
+ List actuals = this.repo.findByPrimaryName("Karl Malden");
+
+ assertThat(actuals.size(), is(1));
+
+ Person actual = actuals.get(0);
+
+ assertThat(actual.nconst, is("nm0001500"));
+ assertThat(actual.primaryName, is("Karl Malden"));
+ assertThat(actual.birthYear, is(1912));
+ assertThat(actual.deathYear, is(2009));
+ assertThat(actual.primaryProfession, is(Arrays.asList("actor", "soundtrack", "director")));
+ assertThat(actual.knownForTitles, is(Arrays.asList("tt0047296", "tt0066206", "tt0048973", "tt0044081")));
+ }
+
+ @Test
+ public void findByPrimaryName_Failure() {
+ List actuals = this.repo.findByPrimaryName("not real");
+
+ assertThat(actuals.size(), is(0));
+ }
+
+ @Test
+ public void deleteAll_Success() {
+ this.repo.deleteAll();
+
+ assertThat(this.repo.count(), is(0L));
+ }
+
+ @Test
+ public void deleteById_Success() {
+ this.repo.deleteById("nm0001500");
+
+ assertThat(this.repo.count(), is(0L));
+ }
+
+ @Test
+ public void insert_Success() {
+ String id = "nm0000001";
+ Person newPerson = new Person();
+ newPerson.nconst = id;
+ newPerson.birthYear = 2020;
+ newPerson.primaryName = "Tim Tam";
+ newPerson.primaryProfession = Arrays.asList("Test", "Dancer");
+
+ assertThat(this.repo.insert(newPerson), is(newPerson));
+ assertThat(this.repo.count(), is(2L));
+
+ Person actual = this.repo.findById(id).get();
+
+ assertThat(actual.nconst, is(id));
+ assertThat(actual.primaryName, is("Tim Tam"));
+ assertThat(actual.birthYear, is(2020));
+ assertThat(actual.deathYear, is(nullValue()));
+ assertThat(actual.primaryProfession, is(Arrays.asList("Test", "Dancer")));
+ assertThat(actual.knownForTitles, is(nullValue()));
+ }
+
+ @Test
+ public void update_Success() {
+ Person update = this.repo.findById("nm0001500").get();
+
+ update.deathYear = 2010;
+ update.primaryProfession.add("Test");
+
+ assertThat(this.repo.save(update), is(update));
+
+ Person actual = this.repo.findById("nm0001500").get();
+ assertThat(actual.nconst, is("nm0001500"));
+ assertThat(actual.primaryName, is("Karl Malden"));
+ assertThat(actual.birthYear, is(1912));
+ assertThat(actual.deathYear, is(2010));
+ assertThat(actual.primaryProfession, is(Arrays.asList("actor", "soundtrack", "director", "Test")));
+ assertThat(actual.knownForTitles, is(Arrays.asList("tt0047296", "tt0066206", "tt0048973", "tt0044081")));
+ }
+}
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/PrincipalDataTests.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/PrincipalDataTests.java
new file mode 100644
index 0000000..960ec5a
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/PrincipalDataTests.java
@@ -0,0 +1,175 @@
+package com.microsoft.cse.reference.spring.dal.unit;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import com.microsoft.cse.reference.spring.dal.config.DevelopmentConfig;
+import com.microsoft.cse.reference.spring.dal.config.MongoConfig;
+import com.microsoft.cse.reference.spring.dal.controllers.PrincipalRepository;
+import com.microsoft.cse.reference.spring.dal.converters.*;
+import com.microsoft.cse.reference.spring.dal.models.Principal;
+import org.bson.Document;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Define the tests using the built-in DataMongoTest attribute
+ * However, since the builtin doesn't load other beans, we need to load
+ * the converters, and the config that loads the converters - we do that with @Import
+ */
+@RunWith(SpringRunner.class)
+@DataMongoTest
+@EnableWebSecurity
+@EnableResourceServer
+@Import({EmptyStringToNull.class,
+ NullToEmptyString.class,
+ JsonArrayToStringList.class,
+ MongoConfig.class,
+ DevelopmentConfig.class})
+public class PrincipalDataTests {
+ @Autowired
+ public MongoTemplate mongoTemplate;
+
+ @Autowired
+ public PrincipalRepository repo;
+
+ @Before
+ public void setUp() {
+ this.mongoTemplate.dropCollection(Constants.DB_PRINCIPAL_COLLECTION);
+
+ this.mongoTemplate.insert(Document.parse("{\n" +
+ " \"tconst\" : \"tt0000442\",\n" +
+ " \"ordering\" : 1,\n" +
+ " \"nconst\" : \"nm0622273\",\n" +
+ " \"category\" : \"actress\",\n" +
+ " \"job\" : \"\",\n" +
+ " \"characters\" : \"[\\\"Barnemordersken\\\"]\"\n" +
+ " },"), Constants.DB_PRINCIPAL_COLLECTION);
+ }
+
+ @Test
+ public void storageOperation_Success() {
+ // we aren't really testing findAll here, we're testing that
+ // our model inflates as expected - hence the name storageOperation
+ Principal actual = this.repo.findAll().get(0);
+
+ assertThat(actual.tconst, is("tt0000442"));
+ assertThat(actual.ordering, is(1));
+ assertThat(actual.nconst, is("nm0622273"));
+ assertThat(actual.category, is("actress"));
+ assertThat(actual.job, is(nullValue()));
+ assertThat(actual.characters, is(Arrays.asList("Barnemordersken")));
+ }
+
+ @Test
+ public void findById_Failure() {
+ Optional actual = this.repo.findById("not-real");
+
+ assertThat(actual.isPresent(), is(false));
+ }
+
+ @Test
+ public void findByNconst_Success() {
+ List actuals = this.repo.findByNconst("nm0622273");
+
+ assertThat(actuals.size(), is(1));
+
+ Principal actual = actuals.get(0);
+
+ assertThat(actual.tconst, is("tt0000442"));
+ assertThat(actual.ordering, is(1));
+ assertThat(actual.nconst, is("nm0622273"));
+ assertThat(actual.category, is("actress"));
+ assertThat(actual.job, is(nullValue()));
+ assertThat(actual.characters, is(Arrays.asList("Barnemordersken")));
+ }
+
+ @Test
+ public void findByNconst_Failure() {
+ List actuals = this.repo.findByNconst("not real");
+
+ assertThat(actuals.size(), is(0));
+ }
+
+ @Test
+ public void findByTconst_Success() {
+ List actuals = this.repo.findByTconst("tt0000442");
+
+ assertThat(actuals.size(), is(1));
+
+ Principal actual = actuals.get(0);
+
+ assertThat(actual.tconst, is("tt0000442"));
+ assertThat(actual.ordering, is(1));
+ assertThat(actual.nconst, is("nm0622273"));
+ assertThat(actual.category, is("actress"));
+ assertThat(actual.job, is(nullValue()));
+ assertThat(actual.characters, is(Arrays.asList("Barnemordersken")));
+ }
+
+ @Test
+ public void findByTconst_Failure() {
+ List actuals = this.repo.findByTconst("not real");
+
+ assertThat(actuals.size(), is(0));
+ }
+
+ @Test
+ public void deleteAll_Success() {
+ this.repo.deleteAll();
+
+ assertThat(this.repo.count(), is(0L));
+ }
+
+ @Test
+ public void insert_Success() {
+ String id = "tt0000001";
+ Principal newPrincipal = new Principal();
+ newPrincipal.tconst = id;
+ newPrincipal.nconst = "nm0000001";
+
+ assertThat(this.repo.insert(newPrincipal), is(newPrincipal));
+ assertThat(this.repo.count(), is(2L));
+
+ Principal actual = this.repo.findAll().get(1);
+
+ assertThat(actual.tconst, is("tt0000001"));
+ assertThat(actual.ordering, is(nullValue()));
+ assertThat(actual.nconst, is("nm0000001"));
+ assertThat(actual.category, is(nullValue()));
+ assertThat(actual.job, is(nullValue()));
+ assertThat(actual.characters, is(nullValue()));
+ }
+
+ @Test
+ public void update_Success() {
+ Principal update = this.repo.findAll().get(0);
+
+ update.job = "Test";
+ update.characters.add("Test");
+
+ assertThat(this.repo.save(update), is(update));
+
+ Principal actual = this.repo.findAll().get(0);
+ assertThat(actual.tconst, is("tt0000442"));
+ assertThat(actual.ordering, is(1));
+ assertThat(actual.nconst, is("nm0622273"));
+ assertThat(actual.category, is("actress"));
+ assertThat(actual.job, is("Test"));
+ assertThat(actual.characters, is(Arrays.asList("Barnemordersken", "Test")));
+ }
+}
diff --git a/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/TitleDataTests.java b/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/TitleDataTests.java
new file mode 100644
index 0000000..9a083ea
--- /dev/null
+++ b/api/src/test/java/com/microsoft/cse/reference/spring/dal/unit/TitleDataTests.java
@@ -0,0 +1,174 @@
+package com.microsoft.cse.reference.spring.dal.unit;
+
+import com.microsoft.cse.reference.spring.dal.config.Constants;
+import com.microsoft.cse.reference.spring.dal.config.DevelopmentConfig;
+import com.microsoft.cse.reference.spring.dal.config.MongoConfig;
+import com.microsoft.cse.reference.spring.dal.controllers.TitleRepository;
+import com.microsoft.cse.reference.spring.dal.converters.BooleanToInteger;
+import com.microsoft.cse.reference.spring.dal.converters.IntegerToBoolean;
+import com.microsoft.cse.reference.spring.dal.models.Title;
+import org.bson.Document;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Define the tests using the built-in DataMongoTest attribute
+ * However, since the builtin doesn't load other beans, we need to load
+ * the converters, and the config that loads the converters - we do that with @Import
+ */
+@RunWith(SpringRunner.class)
+@DataMongoTest
+@EnableWebSecurity
+@EnableResourceServer
+@Import({IntegerToBoolean.class,
+ BooleanToInteger.class,
+ MongoConfig.class,
+ DevelopmentConfig.class})
+public class TitleDataTests {
+ @Autowired
+ public MongoTemplate mongoTemplate;
+
+ @Autowired
+ public TitleRepository repo;
+
+ @Before
+ public void setUp() {
+ this.mongoTemplate.dropCollection(Constants.DB_TITLE_COLLECTION);
+
+ this.mongoTemplate.insert(Document.parse("{\n" +
+ " \"tconst\" : \"tt0075472\",\n" +
+ " \"titleType\" : \"tvSeries\",\n" +
+ " \"primaryTitle\" : \"All Creatures Great and Small\",\n" +
+ " \"originalTitle\" : \"All Creatures Great and Small\",\n" +
+ " \"isAdult\" : 0,\n" +
+ " \"startYear\" : 1978,\n" +
+ " \"endYear\" : 1990,\n" +
+ " \"runtimeMinutes\" : 50,\n" +
+ " \"genres\" : \"Comedy,Drama\"\n" +
+ " }"), Constants.DB_TITLE_COLLECTION);
+ }
+
+ @Test
+ public void findById_Success() {
+ Title actual = this.repo.findById("tt0075472").get();
+
+ assertThat(actual.tconst, is("tt0075472"));
+ assertThat(actual.titleType, is("tvSeries"));
+ assertThat(actual.primaryTitle, is("All Creatures Great and Small"));
+ assertThat(actual.originalTitle, is("All Creatures Great and Small"));
+ assertThat(actual.isAdult, is(false));
+ assertThat(actual.startYear, is(1978));
+ assertThat(actual.endYear, is(1990));
+ assertThat(actual.runtimeMinutes, is(50));
+ assertThat(actual.genres, is(Arrays.asList("Comedy", "Drama")));
+ }
+
+ @Test
+ public void findById_Failure() {
+ Optional actual = this.repo.findById("not-real");
+
+ assertThat(actual.isPresent(), is(false));
+ }
+
+ @Test
+ public void findByPrimaryTitle_Success() {
+ List actuals = this.repo.findByPrimaryTitle("All Creatures Great and Small");
+
+ assertThat(actuals.size(), is(1));
+
+ Title actual = actuals.get(0);
+
+ assertThat(actual.tconst, is("tt0075472"));
+ assertThat(actual.titleType, is("tvSeries"));
+ assertThat(actual.primaryTitle, is("All Creatures Great and Small"));
+ assertThat(actual.originalTitle, is("All Creatures Great and Small"));
+ assertThat(actual.isAdult, is(false));
+ assertThat(actual.startYear, is(1978));
+ assertThat(actual.endYear, is(1990));
+ assertThat(actual.runtimeMinutes, is(50));
+ assertThat(actual.genres, is(Arrays.asList("Comedy", "Drama")));
+ }
+
+ @Test
+ public void findByPrimaryTitle_Failure() {
+ List actuals = this.repo.findByPrimaryTitle("not real");
+
+ assertThat(actuals.size(), is(0));
+ }
+
+ @Test
+ public void deleteAll_Success() {
+ this.repo.deleteAll();
+
+ assertThat(this.repo.count(), is(0L));
+ }
+
+ @Test
+ public void deleteById_Success() {
+ this.repo.deleteById("tt0075472");
+
+ assertThat(this.repo.count(), is(0L));
+ }
+
+ @Test
+ public void insert_Success() {
+ String id = "tt0000001";
+ Title newTitle = new Title();
+ newTitle.tconst = id;
+ newTitle.originalTitle = "Test Movie";
+ newTitle.isAdult = true;
+ newTitle.genres = Arrays.asList("Comedy", "Horror");
+
+ assertThat(this.repo.insert(newTitle), is(newTitle));
+ assertThat(this.repo.count(), is(2L));
+
+ Title actual = this.repo.findById(id).get();
+
+ assertThat(actual.tconst, is(id));
+ assertThat(actual.titleType, is(nullValue()));
+ assertThat(actual.primaryTitle, is(nullValue()));
+ assertThat(actual.originalTitle, is("Test Movie"));
+ assertThat(actual.isAdult, is(true));
+ assertThat(actual.startYear, is(nullValue()));
+ assertThat(actual.endYear, is(nullValue()));
+ assertThat(actual.runtimeMinutes, is(nullValue()));
+ assertThat(actual.genres, is(Arrays.asList("Comedy", "Horror")));
+ }
+
+ @Test
+ public void update_Success() {
+ Title update = this.repo.findById("tt0075472").get();
+
+ update.isAdult = true;
+ update.genres.add("Test");
+
+ assertThat(this.repo.save(update), is(update));
+
+ Title actual = this.repo.findById("tt0075472").get();
+ assertThat(actual.tconst, is("tt0075472"));
+ assertThat(actual.titleType, is("tvSeries"));
+ assertThat(actual.primaryTitle, is("All Creatures Great and Small"));
+ assertThat(actual.originalTitle, is("All Creatures Great and Small"));
+ assertThat(actual.isAdult, is(true));
+ assertThat(actual.startYear, is(1978));
+ assertThat(actual.endYear, is(1990));
+ assertThat(actual.runtimeMinutes, is(50));
+ assertThat(actual.genres, is(Arrays.asList("Comedy", "Drama", "Test")));
+ }
+}
diff --git a/api/swagger.yml b/api/swagger.yml
new file mode 100644
index 0000000..9a12059
--- /dev/null
+++ b/api/swagger.yml
@@ -0,0 +1,478 @@
+swagger: "2.0"
+info:
+ description: "The ProjectJackson API. Azure-based services."
+ version: "1.0.0"
+ title: "Project Jackson API"
+schemes:
+- "https"
+paths:
+ /people:
+ post:
+ tags:
+ - people
+ - active
+ summary: "Creates a person"
+ description: "Returns information and ID of new person"
+ produces:
+ - "application/json"
+ parameters:
+ - in: body
+ name: person
+ required: true
+ schema:
+ $ref: "#/definitions/Person"
+ responses:
+ 201:
+ description: Successful person creation
+ 400:
+ description: Incorrect/incomplete person supplied
+ 401:
+ description: Unauthorized
+ get:
+ tags:
+ - people
+ - active
+ summary: "An endpoint that returns some people objects"
+ description: "Returns a small number of people entries"
+ responses:
+ 200:
+ description: Successful person creation
+ schema:
+ $ref: "#/definitions/Person"
+ 401:
+ description: Unauthorized
+ "/people/{nconst}":
+ get:
+ tags:
+ - people
+ - active
+ summary: "Gets the person associated with ID"
+ description: "Returns information about person"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: nconst
+ description: "ID (nconst) of the person"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful get of person
+ schema:
+ $ref: "#/definitions/Person"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Person not found
+ put:
+ tags:
+ - people
+ - active
+ summary: "Updates a person for a given ID"
+ description: "Returns information about updated person"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: nconst
+ description: "ID (nconst) of the person"
+ required: true
+ type: string
+ - in: body
+ name: person
+ required: true
+ schema:
+ $ref: "#/definitions/Person"
+ responses:
+ 200:
+ description: Successful update
+ schema:
+ $ref: "#/definitions/Person"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Person not found
+ delete:
+ tags:
+ - people
+ - active
+ summary: "Deletes a person"
+ description: "Returns success/failure of deletion"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: nconst
+ description: "ID (nconst) of the person"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful deletion
+ 401:
+ description: Unauthorized
+ 404:
+ description: Person not found
+ "/people/{nconst}/titles":
+ get:
+ tags:
+ - people
+ - active
+ summary: "Gets the titles associated with the person associated with specified ID"
+ description: "Returns array of titles"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: nconst
+ description: "ID (nconst) of the person"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful return of titles
+ schema:
+ $ref: "#/definitions/Title"
+ 401:
+ description: Unauthorized
+ 404:
+ description: No valid ID Supplied
+ "/people/search":
+ get:
+ tags:
+ - people
+ - upcoming feature
+ summary: "Search people by specified terms"
+ description: "Returns collection of titles, where 'Type' may be like Role/Name/etc and 'Value' is the filtering search criterion"
+ produces:
+ - "application/json"
+ parameters:
+ - in: query
+ name: filterType
+ description: "Filtering type, eg Role, Name, etc."
+ required: true
+ type: string
+ - in: query
+ name: filterValue
+ description: "Filtering value"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful return of people
+ schema:
+ $ref: "#/definitions/Person"
+ 401:
+ description: Unauthorized
+ 404:
+ description: No people found with matching criteria
+ /titles:
+ post:
+ tags:
+ - titles
+ - active
+ summary: "Creates a title"
+ description: "Returns information and ID of new title"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters:
+ - in: body
+ name: title
+ description: "the details for a title"
+ required: true
+ schema:
+ $ref: "#/definitions/Title"
+ responses:
+ 201:
+ description: Successful title creation
+ 401:
+ description: Unauthorized
+ get:
+ tags:
+ - titles
+ - active
+ summary: "An endpoint that returns some title objects"
+ description: "Returns a small number of title entries"
+ responses:
+ 200:
+ description: Successful return of some titles
+ schema:
+ $ref: "#/definitions/Title"
+ 401:
+ description: Unauthorized
+ "/titles/{tconst}":
+ get:
+ tags:
+ - titles
+ - active
+ summary: "Gets the title of a piece given an ID"
+ description: "Returns information about title"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: tconst
+ description: "tconst of title to return"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful get
+ schema:
+ $ref: "#/definitions/Title"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Title not found
+ put:
+ tags:
+ - titles
+ - active
+ summary: "Updates the title of a piece given an ID"
+ description: "Returns information about title"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: tconst
+ description: "tconst of title to update and return"
+ required: true
+ type: string
+ responses:
+ 201:
+ description: Successful update of Title
+ schema:
+ $ref: "#/definitions/Title"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Title not found
+ delete:
+ tags:
+ - titles
+ - active
+ summary: "Deletes the piece of media given an ID"
+ description: "Returns success/failure message"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: tconst
+ description: "ID of title to delete"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful deletion
+ 401:
+ description: Unauthorized
+ 404:
+ description: Title not found
+ "/titles/{tconst}/people":
+ get:
+ tags:
+ - titles
+ - active
+ - principalwithname
+ summary: "Gets the people popularly associated with the given title"
+ description: "Returns list of PrincipalWithName objects"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: tconst
+ description: "tconst of title to get"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful get
+ schema:
+ $ref: "#/definitions/PrincipalWithName"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Title not supplied/found
+ "/titles/{tconst}/cast":
+ get:
+ tags:
+ - titles
+ - active
+ - principalwithname
+ summary: "Gets the actors associated with the given title"
+ description: "Returns list of PrincipalWithName objects whose role is actor"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: tconst
+ description: "tconst of title to get"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful get
+ schema:
+ $ref: "#/definitions/PrincipalWithName"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Title not supplied/found
+ "/titles/{tconst}/crew":
+ get:
+ tags:
+ - titles
+ - active
+ - principalwithname
+ summary: "Gets the crew members associated with the given title"
+ description: "Returns list of PrincipalWithName objects whose roles are not actor"
+ produces:
+ - "application/json"
+ parameters:
+ - in: path
+ name: tconst
+ description: "tconst of title to get"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful get
+ schema:
+ $ref: "#/definitions/PrincipalWithName"
+ 401:
+ description: Unauthorized
+ 404:
+ description: Title not supplied/found
+ "/titles/search":
+ get:
+ tags:
+ - titles
+ - upcoming feature
+ summary: "Search titles by specified terms"
+ description: "Returns collection of titles based on search criteria"
+ produces:
+ - "application/json"
+ parameters:
+ - in: query
+ name: filterType
+ description: "Filtering type"
+ required: true
+ type: string
+ - in: query
+ name: filterValue
+ description: "Filtering value"
+ required: true
+ type: string
+ responses:
+ 200:
+ description: Successful return of titles
+ schema:
+ $ref: "#/definitions/Title"
+ 401:
+ description: Unauthorized
+ 404:
+ description: No people found with matching criteria
+ /search:
+ get:
+ tags:
+ - upcoming feature
+ summary: "Upcoming Feature: Performs an aggregate search"
+ description: "Upcoming Feature: Any title or person who has a field that matches the search term(s)"
+ produces:
+ - "application/json"
+ responses:
+ 200:
+ description: Successful get
+ 401:
+ description: Unauthorized
+definitions:
+ Title:
+ properties:
+ tconst:
+ description: "A string of a sequential number prepended with 'tt'"
+ type: string
+ titleType:
+ description: "A string describing the type of content, eg. tvSeries, movie, tvMiniSeries"
+ type: string
+ primaryTitle:
+ description: "A string of the title of the piece of media"
+ type: string
+ originalTitle:
+ description: "A string of the original title of the piece of media, typically distinct from primaryTitle if film name is originally in a foreign language"
+ type: string
+ isAdult:
+ description: "An integer representation of a boolean (0 or 1) whether the content is adult, ie. typically of pornographic nature"
+ type: integer
+ format: int32
+ startYear:
+ description: "An integer of the year; for non-serialized content it's the release year"
+ type: integer
+ format: int32
+ endYear:
+ description: "An integer of the year; for serialized content it's the year media completes"
+ type: integer
+ format: int32
+ runtimeMinutes:
+ description: "An integer of the number of minutes long the content lasts"
+ type: integer
+ format: int32
+ genres:
+ description: "A array of strings for genres associated with the piece"
+ type: array
+ items:
+ type: string
+ Person:
+ properties:
+ nconst:
+ description: "A string of a sequential number prepended with 'nm'"
+ type: string
+ primaryName:
+ description: "A string representing a person's name"
+ type: string
+ birthYear:
+ description: "An integer representing the person's birth year"
+ type: integer
+ format: int32
+ deathYear:
+ description: "An integer representing the person's year of death"
+ type: integer
+ format: int32
+ primaryProfession:
+ description: "A string of a comma-separated list of professions"
+ type: string
+ knownForTitles:
+ description: "An array of strings of tconsts (from the titles)"
+ type: array
+ items:
+ type: string
+ PrincipalWithName:
+ properties:
+ tconst:
+ description: "A string representing a title's IMDb ID, one half of the title-person join"
+ type: string
+ ordering:
+ description: "An integer representing the billing order when searching on IMDb for the piece of media"
+ type: integer
+ format: int32
+ person:
+ description: "An LinkedHashMap object that maps to the fields found in an a Person object"
+ type: object
+ category:
+ description: "A string that contains what kind of role a Person has in a piece of media"
+ type: integer
+ format: int32
+ job:
+ description: "A string that has a person's job in the piece of media"
+ type: string
+ characters:
+ description: "An array of strings that optionally contain what characters a Person plays in the piece of media"
+ type: array
+ items:
+ type: string
\ No newline at end of file
diff --git a/data/getdata.sh b/data/getdata.sh
new file mode 100644
index 0000000..5fc2cc5
--- /dev/null
+++ b/data/getdata.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+echo
+echo "Getting IMDb data files (updated daily)..."
+curl --remote-name-all https://datasets.imdbws.com/{name.basics.tsv.gz,title.basics.tsv.gz,title.principals.tsv.gz}
+echo
+echo "Unzipping the data files (overwrites any existing .tsv files)..."
+gunzip -vf *.gz
+echo
+echo "Removing IMDb '\N' values..."
+sed --in-place 's/\\N//g' *.tsv
+echo
+echo "IMDb data files ready:"
+ls *.tsv
+echo
\ No newline at end of file
diff --git a/data/importdata.sh b/data/importdata.sh
new file mode 100644
index 0000000..93fc262
--- /dev/null
+++ b/data/importdata.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+################################################################################
+# Variables
+################################################################################
+
+resourceGroup=$RESOURCE_GROUP
+cosmosName=$COSMOSDB_NAME
+password=$COSMOSDB_PASSWORD
+databaseName=IMDb
+files=("title.basics.tsv" "name.basics.tsv" "title.principals.tsv")
+collections=(titles names principals_mapping)
+keys=("tconst" "nconst" "tconst")
+
+len=${#collections[@]}
+
+################################################################################
+# Helpers
+################################################################################
+create_database() {
+ az cosmosdb database create -g $resourceGroup -n $cosmosName --db-name $databaseName > /dev/null
+}
+
+create_collections() {
+ for ((i=0; i /dev/null
+ done
+}
+
+delete_tsv_files() {
+ for ((i=0; i Note: This document roughly follows [this tutorial](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v1-add-azure-ad-app).
+
+To enable authentication, one may wish to use [Azure Active Directory (AAD)](https://azure.microsoft.com/en-us/services/active-directory/).
+This document will describe how to configure and leverage AAD for this application.
+
+## Setup AAD App
+
+> TL;DR: After these steps you should have two values noted - an `Application ID` and an `App ID URI`.
+
+1. Login to [Azure Portal](https://portal.azure.com)
+2. Select "Azure Active Directory" from the portal left-hand sidebar
+3. Select "App Registrations" from the left-most panel
+4. Select "New Application" from the top panel
+5. Name your application, and enter a valid url for sign-on (hint: we use the url of our hosted service)
+6. When the application has been created, the newly visible panel will display its "Application ID" - please note its value
+7. Select "Settings" from the top panel
+8. Select "Properties" from the right-most panel
+9. Find "App ID URI" in the panel, note its value
+
+## Configure SpringDAL
+
+> Note: Authentication is only enabled in the `production` profile.
+> TL;DR: After these steps you should have two application environment variables set, `security.oauth2.resource.jwk.key-set-uri` and `security.oauth2.resource.id`.
+
+Ensure that the `security.oauth2.resource.jwk.key-set-uri` environment variable is set to `https://login.microsoftonline.com/common/discovery/keys` - this is because a common key set is used for all Azure Active Directory applications. This will validate that your service only allows valid AAD tokens, but it won't yet verify that the token is for your application.
+
+To ensure the token was granted for your application, you must set `security.oauth2.resource.id` to your `App ID URI` as noted [above](#setup-aad-app).
+
+## Test Authentication
+
+> Note: Authentication is only enabled in the `production` profile.
+
+To ensure authentication is working properly, we need to issue ourselves a token and validate it works. To do so, we'll use [Postman](https://www.getpostman.com/). Please download and install it now.
+
+### Configure AAD Test information
+
+> TL;DR: After these steps you should have one value noted - a `Value`.
+
+1. Login to [Azure Portal](https://portal.azure.com)
+2. Select "Azure Active Directory" from the portal left-hand sidebar
+3. Select "App Registrations" from the left-most panel
+4. Enter your `Application ID` as noted above, into the search field
+5. Click your application, to enter its panel
+6. Select "Settings" from the top panel
+7. Select "Reply URLs" from the right-most panel
+8. Ensure `https://www.getpostman.com/oauth2/callback` is the only reply URL entry
+9. Select "Save" from the top panel
+10. Close the "Reply URLs" panel by selecting the "x" in the top right
+11. Select "Settings" from the top panel
+12. Select "Keys" from the right-most panel
+13. Under "Passwords" type a new "Key Description" in the field, and choose an expiration time
+14. Select "Save" from the top panel - please note the value that appears in the `Value` field
+
+### Configure Postman Test information
+
+> TL;DR: After these steps you should have one value noted - an `access_token`.
+
+1. Open Postman
+2. Navigate to the Body panel
+3. Select "x-www-form-urlencoded"
+4. Populate the table that appears with the following values
+ + `grant_type`: `client_credentials`
+ + `client_id`: `` where `` is `Application ID` from above
+ + `client_secret`: `` where `` is the Key `Value` from above
+ + `resource`: `` where `` is `App ID URI` from above
+5. Change the method in the address bar to "POST"
+6. Enter `https://login.microsoftonline.com/microsoft.onmicrosoft.com/oauth2/token` for the url
+7. Select "Send"
+8. The "Body" section of the bottom pane should now be populated
+9. Select `access_token` from the "Body" section - please note its value
+
+### Run test
+
+> TL;DR: After these steps you should know if authentication is working properly!
+
+1. Start the `SpringDAL` application with the `production` profile (see the Readme for more information)
+2. Open Postman
+3. Change the method in the address bar to "GET"
+4. Enter `http://localhost:8080/` for the url
+5. Navigate to the Headers panel
+6. Add one header in the table - `Authorization`: `Bearer ` where `` is `access_token` from [above](#configure-postman-test-information)
+7. Issue the Postman request by clicking "Send"
+8. Validate that Postman shows a successful response
+9. Navigate to "Headers" in Postman
+10. Toggle off the "Authorization" header by clicking the checkbox next to it
+11. Issue the Postman request by clicking "Send"
+12. Validate that Postman shows a failure response
\ No newline at end of file
diff --git a/docs/buildAndReleasePipelines.md b/docs/buildAndReleasePipelines.md
new file mode 100644
index 0000000..bcb6fc6
--- /dev/null
+++ b/docs/buildAndReleasePipelines.md
@@ -0,0 +1,43 @@
+# Build and Release Pipelines
+
+For Project Jackson, the team utilized [Azure Dev Ops](https://azure.microsoft.com/en-us/services/devops/) for source control, work tracking, build and release pipelines. The build pipelines were set up for the API and for the small client application. The build artifacts were used as the kickoff point for the release pipelines for each of the deployment pipelines.
+
+## API Build
+
+The API utilizes Spring Boot to create a standalone Java application. The API is described in depth in [the swagger doc](../swagger.yml). The API uses [Maven](https://maven.apache.org/) with [Spring Boot](https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/) to test, compile, run and package the self-contained executable jar that runs in production. To create the executable jar, a dependency in `pom.xml` is added:
+
+```
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+```
+Once this is added, the command `mvn package` can be run, which will produce a `example-name.jar` which can be run with the command `java -jar example-name.jar`.
+
+To build the Project Jackson API repo in Azure Dev Ops, a build pipeline was created and described with the [`azure-pipelines.yml`](../azure-pipelines.yml) file. It is broken up into sections based on build step. It starts by running `mvn test` which runs all the unit and integration tests and if that step is successful, it runs `mvn package` and creates that executable jar described previously.
+
+The next steps involve building the docker image defined in the [`Dockerfile`](../Dockerfile), tagging it with the Azure Container Registry (ACR) name and build number, and pushing the tagged Docker image to ACR. The variables for ACR such as `$ACR_SERVER`, `$ACR_CONTAINER_TAG`, `$ACR_PASSWORD`, and `$ACR_USERNAME` are defined in Azure Dev Ops under the build for this repo. The team created a variable group in Azure Dev Ops, under Pipelines, then Library, called `ACR Credentials` that contains the `ACR_SERVER`, `ACR_USERNAME`, and `ACR_PASSWORD` variables. Then in the build pipeline for the API repository, there is a `Variables` tab that has `Variable Groups` as an option and that is where the `ACR Credentials` variable group is linked to the build pipeline for the repository. The `$ACR_CONTAINER_TAG` is set in the `Variables` tab as well, but under `Pipeline Variables` and the team uses a value of `pj-api/pj-api-combined:$(Build.BuildNumber)`.
+
+## Client Build
+
+The UI is a React and TypeScript web app that allows users to easily test the API endpoints and see the data that is returned from the database in a cleaner way. The build pipeline for it was also setup with an `azure-pipelines.yml` file, broken into npm and docker steps. The npm steps include linting, testing and building through the following commands.
+```
+npm run lint
+npm run test
+npm run build
+```
+
+After those steps finish successfully, a docker image is built, tagged, and pushed into ACR in the same way that the API container is dockerized. The difference is that the `$ACR_CONTAINER_TAG` variable in the UI build `Variables` is `pj-ui:$(Build.BuildNumber)` to differentiate the docker container from the API in ACR.
+
+
+## API Release Pipeline
+
+The release pipeline for the API was built with Azure Dev Ops, under `Pipelines` and `Releases`. The pipeline was configured so that when there was a new build of the master branch in the API repository, a deployment of the API to Azure App Services would start. The API Deployment pipeline has two tasks in the `Stages` section, which are `Person Endpoint Deploy` and `Title Endpoint Deploy`. Each task deploys an Azure App Service of the type `Linux App` to the `jackson-person` and `jackson-title`, respectively, App Services. The `Image Source` is `Container Registry`, the `Registry or Namespace` is `jacksoncontainer.azurecr.io`, the `Repository` is `pj-api/pj-api-combined`, and the `Tag` is `$(Build.BuildNumber)` which match the values for the docker image pushed into ACR that was set in the build step. For each task, there were some environment variables that needed to be configured under `App settings` and those variables and values are the ones described in the [`README.md`](../README.md). In order for the front end to communicate with the API successfully, the `ALLOWED_ORIGIN` variable is set to `*` for both tasks. By setting the `App settings` in the deployment task, the `Application Settings` in the Azure Portal for the App Service will get set to the values from the deployment.
+
+## Client Release Pipeline
+
+Like the build pipeline, the release pipeline for the UI is almost identical to the API release pipeline, with key differences being that only the `pj-client` App Service is deployed to and that the docker image being pulled from ACR is from the `pj-client` repository. Only a single environment variable is defined in `Application settings` and it is named `WEBSITES_PORT` with a value of `8080`. In a similar fashion to the API, when there is a build on the master branch of the UI repository, a new release deployment is kicked off.
\ No newline at end of file
diff --git a/docs/images/high_level_architecture.png b/docs/images/high_level_architecture.png
new file mode 100644
index 0000000..7be61f0
Binary files /dev/null and b/docs/images/high_level_architecture.png differ
diff --git a/infrastructure/ACR/README.md b/infrastructure/ACR/README.md
new file mode 100644
index 0000000..59fea43
--- /dev/null
+++ b/infrastructure/ACR/README.md
@@ -0,0 +1,5 @@
+# ACR
+
+Project Jackson uses Azure Container Registry to push and pull images. Deploy your own instance using the button below based off the included ARM template.
+
+[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://azuredeploy.net/)
diff --git a/infrastructure/ACR/template.json b/infrastructure/ACR/template.json
new file mode 100644
index 0000000..743d23b
--- /dev/null
+++ b/infrastructure/ACR/template.json
@@ -0,0 +1,28 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "registries_containers_name": {
+ "type": "String"
+ }
+ },
+ "variables": {},
+ "resources": [
+ {
+ "type": "Microsoft.ContainerRegistry/registries",
+ "sku": {
+ "name": "Basic",
+ "tier": "Basic"
+ },
+ "name": "[parameters('registries_containers_name')]",
+ "apiVersion": "2017-10-01",
+ "location": "westus",
+ "tags": {},
+ "scale": null,
+ "properties": {
+ "adminUserEnabled": true
+ },
+ "dependsOn": []
+ }
+ ]
+}
diff --git a/infrastructure/CosmosDB/README.md b/infrastructure/CosmosDB/README.md
new file mode 100644
index 0000000..ad4380b
--- /dev/null
+++ b/infrastructure/CosmosDB/README.md
@@ -0,0 +1,5 @@
+# CosmosDB
+
+Project Jackson uses a CosmosDB instance enabled with the MongoDB API. Deploy your own instance using the button below based off the included ARM template.
+
+[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://azuredeploy.net/)
diff --git a/infrastructure/CosmosDB/azuredeploy.json b/infrastructure/CosmosDB/azuredeploy.json
new file mode 100644
index 0000000..ce5adba
--- /dev/null
+++ b/infrastructure/CosmosDB/azuredeploy.json
@@ -0,0 +1,35 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "resource-name": {
+ "type": "string"
+ },
+ "database-name": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.DocumentDB/databaseAccounts",
+ "kind": "MongoDB",
+ "name": "[parameters('resource-name')]",
+ "apiVersion": "2015-04-08",
+ "location": "West US",
+ "tags": {
+ "defaultExperience": "MongoDB"
+ },
+ "scale": null,
+ "properties": {
+ "databaseAccountOfferType": "Standard",
+ "consistencyPolicy": {
+ "defaultConsistencyLevel": "Session",
+ "maxIntervalInSeconds": 5,
+ "maxStalenessPrefix": 100
+ },
+ "name": "[parameters('database-name')]"
+ },
+ "dependsOn": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/infrastructure/README.md b/infrastructure/README.md
new file mode 100644
index 0000000..234e37f
--- /dev/null
+++ b/infrastructure/README.md
@@ -0,0 +1,60 @@
+
+# Project Jackson Infrastructure
+
+This repository tracks various Project Jackson ARM templates.
+
+### Table Of Contents
+
+- [ACR](/ACR/README.md)
+- [CosmosDB](/CosmosDB/README.md)
+
+## Performance Testing
+How to performance test an App Service.
+
+1. Navigate to the Azure Portal for your App Service
+2. Under `Developer Tools` select `Performance Testing`
+!['This image is of the performance testing menu item'](/images/perftest1.png)
+3. Select `New`
+!['This image is of new performance testing button'](/images/perftest2.png)
+4. Name the new performance test and configure the settings appropriately
+!['This image is of performance testing settings'](/images/perftest3.png)
+5. Submit the test and after resources are automatically allocated it will run
+
+After it completes, Azure will automatically generate graphs and charts for you to easily analyze the performance test.
+
+## ARM Template
+To deploy all the resources, the script deploy.sh can be used.
+The below values are required as the script inputs:
+1. Azure Subscription ID
+2. Azure Resource Group (Add existing if any else create a new one)
+3. Azure Deployment Location (eastus, westus, etc)
+4. App-name: Application Name
+
+Another way to deploy is to run one-click deploy for all resources using below Deploy to Azure:
+
+[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://azuredeploy.net/)
+
+Once the ACR is deployed using the above deployment method follow the below manual steps to set up CD pipeline:
+1. Create a new variable group in Azure Pipeline Library
+2. Create variable ACR_SERVER and set value to the server name which will be the output of your deployment (container.azurecr.io)
+3. Get values of username and password from container using Azure Portal
+4. Create variables ACR_USERNAME and ACR_PASSWORD and set it using the above values respectively.
+5. Once you set the above variables, your deployment resources can now be used as part of your CD pipeline.
+
+## Environments
+- Different environments like Dev, QA, Staging and Production environments are created under the resource group for all the resources to be deployed using ARM Template.
+- Policies can be created between each of the environments to promote builds from one environment to another based on the requirements of the customer.
+- These policies can differ for each customer and product.
+- Once the tests under Dev environment passes, they can be approved to run on the QA environment based on policies set for approvals on each. These policies can be set under Azure DevOps Release Pipeline.
+
+## Redis Cache
+- A Redis cache is part of the resources to enhance performance of queries.
+- The capacity of the Redis cache can be changed in the ARM template anywhere between 1 to 6.
+- One also has the option to enable or disable Non SSL port from the ARM template.
+- Azure allows 3 different values for the sku viz. Basic, Standard and Premium having different costs for each.
+
+## Auto Scaling
+- The app service is enabled with auto scaling
+- When the CPU used is above 70 percent, the app will automatically be scaled to add another compute instance and this can be done for up to a max of 5 instances which can be changed based on requirements.
+- When the memory on an instance used is above 70 percent, the app will automatically be scaled to add another compute instance and this can be done for up to a max of 5 instances which can be changed based on requirements.
+- The minimum number of instances is set to be 1 which means, if the memory used on an instance is less, the instances will be scaled down automatically.
diff --git a/infrastructure/azure-pipelines.yml b/infrastructure/azure-pipelines.yml
new file mode 100644
index 0000000..61f1760
--- /dev/null
+++ b/infrastructure/azure-pipelines.yml
@@ -0,0 +1,35 @@
+trigger:
+ branches:
+ include:
+ - master
+ paths:
+ include:
+ - infrastructure/*
+pool:
+ vmImage: 'Ubuntu 16.04'
+
+steps:
+# Validate ARM template
+- task: AzureResourceGroupDeployment@2
+ displayName: 'Validate ARM template'
+ inputs:
+ azureSubscription: $(serviceConnectionAzureSubscription)
+ resourceGroupName: $(resourceGroupName)
+ location: $(location)
+ csmFile: infrastructure/azuredeploy.json
+ overrideParameters: '-application_name $(applicationName) -docker_registry_url $(ACR_SERVER) -docker_registry_username $(ACR_USERNAME) -docker_registry_password $(ACR_PASSWORD)'
+ deploymentMode: Validation
+
+# Copy ARM deployment JSON
+- task: CopyFiles@2
+ displayName: 'Copy ARM deployment JSON'
+ inputs:
+ contents: 'infrastructure/azuredeploy.json'
+ targetFolder: '$(Build.ArtifactStagingDirectory)'
+
+# Publish Build Artifacts
+- task: PublishBuildArtifacts@1
+ inputs:
+ PathToPublish: '$(Build.ArtifactStagingDirectory)'
+ ArtifactName: package
+ publishLocation: Container
\ No newline at end of file
diff --git a/infrastructure/azuredeploy.json b/infrastructure/azuredeploy.json
new file mode 100644
index 0000000..2629356
--- /dev/null
+++ b/infrastructure/azuredeploy.json
@@ -0,0 +1,283 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "application_name": {
+ "type": "string"
+ },
+ "docker_registry_url": {
+ "type": "string"
+ },
+ "docker_registry_username": {
+ "type": "securestring"
+ },
+ "docker_registry_password": {
+ "type": "securestring"
+ }
+ },
+ "variables": {
+ "autoscale_settings_name": "[concat(parameters('application_name'), '-autoscale')]",
+ "components_insights_name": "[concat(parameters('application_name'), '-componentsinsights')]",
+ "database_accounts_name": "[concat(parameters('application_name'), '-databaseaccounts')]",
+ "sites_api_title_name": "[concat(parameters('application_name'), '-title')]",
+ "sites_api_person_name": "[concat(parameters('application_name'), '-person')]",
+ "serverfarms_appservice_plan_name": "[concat(parameters('application_name'), '-appserviceplan')]",
+ "traffic_manager_profiles_name": "[concat(parameters('application_name'), '-trafficManager')]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.DocumentDB/databaseAccounts",
+ "kind": "MongoDB",
+ "name": "[variables('database_accounts_name')]",
+ "apiVersion": "2015-04-08",
+ "location": "[resourceGroup().location]",
+ "tags": {
+ "defaultExperience": "MongoDB"
+ },
+ "scale": null,
+ "properties": {
+ "databaseAccountOfferType": "Standard",
+ "consistencyPolicy": {
+ "defaultConsistencyLevel": "Session",
+ "maxIntervalInSeconds": 5,
+ "maxStalenessPrefix": 100
+ },
+ "name": "[variables('database_accounts_name')]"
+ },
+ "dependsOn": []
+ },
+ {
+ "type": "Microsoft.Insights/components",
+ "kind": "web",
+ "name": "[variables('components_insights_name')]",
+ "apiVersion": "2015-05-01",
+ "location": "South Central US",
+ "tags": {},
+ "scale": null,
+ "properties": {
+ "Application_Type": "java",
+ "Flow_Type": "Redfield",
+ "Request_Source": "IbizaAIExtension",
+ "HockeyAppId": null,
+ "SamplingPercentage": null
+ },
+ "dependsOn": []
+ },
+ {
+ "type": "Microsoft.Web/serverfarms",
+ "sku": {
+ "name": "S1",
+ "tier": "Basic",
+ "size": "S1",
+ "family": "S",
+ "capacity": 1
+ },
+ "kind": "linux",
+ "name": "[variables('serverfarms_appservice_plan_name')]",
+ "apiVersion": "2016-09-01",
+ "location": "[resourceGroup().location]",
+ "scale": null,
+ "properties": {
+ "name": "[variables('serverfarms_appservice_plan_name')]",
+ "workerTierName": null,
+ "adminSiteName": null,
+ "hostingEnvironmentProfile": null,
+ "perSiteScaling": false,
+ "reserved": true,
+ "targetWorkerCount": 0,
+ "targetWorkerSizeId": 0
+ },
+ "dependsOn": []
+ },
+ {
+ "type": "Microsoft.Web/sites",
+ "name": "[variables('sites_api_title_name')]",
+ "apiVersion": "2016-03-01",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "name": "[variables('sites_api_title_name')]",
+ "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]"
+ ],
+ "resources": [
+ {
+ "name": "appsettings",
+ "type": "config",
+ "apiVersion": "2016-03-01",
+ "dependsOn": [
+ "[resourceId('Microsoft.Web/sites', variables('sites_api_title_name'))]"
+ ],
+ "tags": {
+ "displayName": "appSettings"
+ },
+ "properties": {
+ "DB_CONNSTR": "[concat('mongodb://', variables('database_accounts_name'), ':', listKeys(resourceId('Microsoft.DocumentDb/databaseAccounts', variables('database_accounts_name')), '2015-04-08').primaryMasterKey, '@', variables('database_accounts_name'), '.documents.azure.com:10250/?ssl=true&replicaSet=globaldb')]",
+ "DB_NAME": "IMDb",
+ "RESOURCE_GROUP": "[resourceGroup().name]",
+ "spring.profiles.active": "production",
+ "DOCKER_REGISTRY_SERVER_USERNAME": "[parameters('docker_registry_username')]",
+ "DOCKER_REGISTRY_SERVER_PASSWORD": "[parameters('docker_registry_password')]",
+ "DOCKER_REGISTRY_SERVER_URL": "[parameters('docker_registry_url')]",
+ "EXCLUDE_FILTER": "PersonRepository"
+ }
+ }
+ ]
+ },
+ {
+ "type": "Microsoft.Web/sites",
+ "name": "[variables('sites_api_person_name')]",
+ "apiVersion": "2016-03-01",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "name": "[variables('sites_api_person_name')]",
+ "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]"
+ ],
+ "resources": [
+ {
+ "name": "appsettings",
+ "type": "config",
+ "apiVersion": "2016-03-01",
+ "dependsOn": [
+ "[resourceId('Microsoft.Web/sites', variables('sites_api_person_name'))]"
+ ],
+ "tags": {
+ "displayName": "appSettings"
+ },
+ "properties": {
+ "DB_CONNSTR": "[concat('mongodb://', variables('database_accounts_name'), ':', listKeys(resourceId('Microsoft.DocumentDb/databaseAccounts', variables('database_accounts_name')), '2015-04-08').primaryMasterKey, '@', variables('database_accounts_name'), '.documents.azure.com:10250/?ssl=true&replicaSet=globaldb')]",
+ "DB_NAME": "IMDb",
+ "RESOURCE_GROUP": "[resourceGroup().name]",
+ "spring.profiles.active": "production",
+ "DOCKER_REGISTRY_SERVER_USERNAME": "[parameters('docker_registry_username')]",
+ "DOCKER_REGISTRY_SERVER_PASSWORD": "[parameters('docker_registry_password')]",
+ "DOCKER_REGISTRY_SERVER_URL": "[parameters('docker_registry_url')]",
+ "EXCLUDE_FILTER": "PersonRepository"
+ }
+ }
+ ]
+ },
+ {
+ "type": "Microsoft.Network/trafficManagerProfiles",
+ "name": "[variables('traffic_manager_profiles_name')]",
+ "apiVersion": "2017-05-01",
+ "location": "global",
+ "tags": {},
+ "scale": null,
+ "properties": {
+ "profileStatus": "Enabled",
+ "trafficRoutingMethod": "Geographic",
+ "dnsConfig": {
+ "relativeName": "[variables('traffic_manager_profiles_name')]",
+ "fqdn": "[concat(variables('traffic_manager_profiles_name'),'.trafficmanager.net')]",
+ "ttl": 60
+ },
+ "monitorConfig": {
+ "protocol": "HTTP",
+ "port": 80,
+ "path": "/",
+ "intervalInSeconds": 30,
+ "toleratedNumberOfFailures": 3,
+ "timeoutInSeconds": 10
+ },
+ "endpoints": [
+ {
+ "name": "[concat(variables('traffic_manager_profiles_name'),'-endpoint-west')]",
+ "type": "Microsoft.Network/trafficManagerProfiles/azureEndpoints",
+ "properties": {
+ "endpointStatus": "Enabled",
+ "targetResourceId": "[resourceId('Microsoft.Web/sites', variables('sites_api_title_name'))]",
+ "target": "[concat(variables('sites_api_title_name'),'.azurewebsites.net')]",
+ "weight": 1,
+ "priority": 1,
+ "endpointLocation": "westus",
+ "geoMapping": [
+ "US-WA"
+ ]
+ }
+ }
+ ]
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Web/sites', variables('sites_api_title_name'))]"
+ ]
+ },
+ {
+ "comments": "Autoscale Settings",
+ "type": "microsoft.insights/autoscalesettings",
+ "name": "[variables('autoscale_settings_name')]",
+ "apiVersion": "2014-04-01",
+ "location": "[resourceGroup().location]",
+ "tags": {},
+ "scale": null,
+ "properties": {
+ "profiles": [
+ {
+ "name": "Auto created scale condition",
+ "capacity": {
+ "minimum": "1",
+ "maximum": "5",
+ "default": "1"
+ },
+ "rules": [
+ {
+ "metricTrigger": {
+ "metricName": "CpuPercentage",
+ "metricNamespace": "",
+ "metricResourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]",
+ "timeGrain": "PT1M",
+ "statistic": "Average",
+ "timeWindow": "PT10M",
+ "timeAggregation": "Average",
+ "operator": "GreaterThan",
+ "threshold": 70
+ },
+ "scaleAction": {
+ "direction": "Increase",
+ "type": "ChangeCount",
+ "value": "1",
+ "cooldown": "PT5M"
+ }
+ },
+ {
+ "metricTrigger": {
+ "metricName": "MemoryPercentage",
+ "metricNamespace": "",
+ "metricResourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]",
+ "timeGrain": "PT1M",
+ "statistic": "Average",
+ "timeWindow": "PT10M",
+ "timeAggregation": "Average",
+ "operator": "GreaterThan",
+ "threshold": 70
+ },
+ "scaleAction": {
+ "direction": "Increase",
+ "type": "ChangeCount",
+ "value": "1",
+ "cooldown": "PT5M"
+ }
+ }
+ ]
+ }
+ ],
+ "enabled": true,
+ "name": "[variables('autoscale_settings_name')]",
+ "targetResourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Web/serverfarms', variables('serverfarms_appservice_plan_name'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "connectionString": {
+ "value": "[concat('mongodb://', variables('database_accounts_name'), ':', listKeys(resourceId('Microsoft.DocumentDb/databaseAccounts', variables('database_accounts_name')), '2015-04-08').primaryMasterKey, '@', variables('database_accounts_name'), '.documents.azure.com:10250/?ssl=true&replicaSet=globaldb')]",
+ "type": "string"
+ }
+ }
+}
diff --git a/infrastructure/deploy.sh b/infrastructure/deploy.sh
new file mode 100644
index 0000000..4748cfb
--- /dev/null
+++ b/infrastructure/deploy.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+# -e: immediately exit if any command has a non-zero exit status
+# -o: prevents errors in a pipeline from being masked
+# IFS new value is less likely to cause confusing bugs when looping arrays or arguments (e.g. $@)
+
+usage() { echo "Usage: $0 -i -g -n -l " 1>&2; exit 1; }
+
+declare subscriptionId=""
+declare resourceGroupName=""
+declare deploymentName=""
+declare resourceGroupLocation=""
+
+# Initialize parameters specified from command line
+while getopts ":i:g:n:l:" arg; do
+ case "${arg}" in
+ i)
+ subscriptionId=${OPTARG}
+ ;;
+ g)
+ resourceGroupName=${OPTARG}
+ ;;
+ n)
+ deploymentName=${OPTARG}
+ ;;
+ l)
+ resourceGroupLocation=${OPTARG}
+ ;;
+ esac
+done
+shift $((OPTIND-1))
+
+#Prompt for parameters is some required parameters are missing
+if [[ -z "$subscriptionId" ]]; then
+ echo "Your subscription ID can be looked up with the CLI using: az account show --out json "
+ echo "Enter your subscription ID:"
+ read subscriptionId
+ [[ "${subscriptionId:?}" ]]
+fi
+
+if [[ -z "$resourceGroupName" ]]; then
+ echo "This script will look for an existing resource group, otherwise a new one will be created "
+ echo "You can create new resource groups with the CLI using: az group create "
+ echo "Enter a resource group name"
+ read resourceGroupName
+ [[ "${resourceGroupName:?}" ]]
+fi
+
+if [[ -z "$resourceGroupLocation" ]]; then
+ echo "If creating a *new* resource group, you need to set a location "
+ echo "You can lookup locations with the CLI using: az account list-locations "
+
+ echo "Enter resource group location:"
+ read resourceGroupLocation
+fi
+
+#templateFile Path - template file to be used
+templateFilePath="azuredeploy.json"
+
+if [ ! -f "$templateFilePath" ]; then
+ echo "$templateFilePath not found"
+ exit 1
+fi
+
+#parameter file path
+#parametersFilePath="parameters.json"
+
+#if [ ! -f "$parametersFilePath" ]; then
+# echo "$parametersFilePath not found"
+# exit 1
+#fi
+
+if [ -z "$subscriptionId" ] || [ -z "$resourceGroupName" ]; then
+ echo "Either one of subscriptionId, resourceGroupName, deploymentName is empty"
+ usage
+fi
+
+#login to azure using your credentials
+az account show 1> /dev/null
+
+if [ $? != 0 ];
+then
+ az login
+fi
+
+#set the default subscription id
+az account set --subscription $subscriptionId
+
+set +e
+
+#Check for existing RG
+az group show --name $resourceGroupName 1> /dev/null
+
+if [ $? != 0 ]; then
+ echo "Resource group with name" $resourceGroupName "could not be found. Creating new resource group.."
+ set -e
+ (
+ set -x
+ az group create --name $resourceGroupName --location $resourceGroupLocation 1> /dev/null
+ )
+ else
+ echo "Using existing resource group..."
+fi
+
+#Start deployment
+echo "Starting deployment..."
+(
+ set -x
+ az group deployment create --name "$deploymentName" --resource-group "$resourceGroupName" --template-file "$templateFilePath" #--parameters "@${parametersFilePath}"
+)
+
+if [ $? == 0 ];
+ then
+ echo "Template has been successfully deployed"
+fi
diff --git a/infrastructure/images/perftest1.png b/infrastructure/images/perftest1.png
new file mode 100644
index 0000000..de4276c
Binary files /dev/null and b/infrastructure/images/perftest1.png differ
diff --git a/infrastructure/images/perftest2.png b/infrastructure/images/perftest2.png
new file mode 100644
index 0000000..ae05cc3
Binary files /dev/null and b/infrastructure/images/perftest2.png differ
diff --git a/infrastructure/images/perftest3.png b/infrastructure/images/perftest3.png
new file mode 100644
index 0000000..14ddb8f
Binary files /dev/null and b/infrastructure/images/perftest3.png differ
diff --git a/load_env.sh b/load_env.sh
new file mode 100644
index 0000000..7dca580
--- /dev/null
+++ b/load_env.sh
@@ -0,0 +1,214 @@
+#!/bin/bash
+set -euo pipefail
+IFS=$'\n\t'
+
+# -e: immediately exit if any command has a non-zero exit status
+# -o: prevents errors in a pipeline from being masked
+# IFS new value is less likely to cause confusing bugs when looping arrays or arguments (e.g. $@)
+
+#******************************************************************************
+# Script to set environment variables
+#******************************************************************************
+
+usage() { echo "Usage: $0 -i -g -n -l " 1>&2; exit 1; }
+
+declare subscriptionId=""
+declare resourceGroupName=""
+declare resourceGroupLocation=""
+declare dbName=""
+declare connStr=""
+declare dbPassword=""
+
+# Initialize parameters specified from command line
+while getopts ":i:g:n:l:" arg; do
+ case "${arg}" in
+ i)
+ subscriptionId=${OPTARG}
+ ;;
+ g)
+ resourceGroupName=${OPTARG}
+ ;;
+ l)
+ resourceGroupLocation=${OPTARG}
+ ;;
+ d)
+ dbName=${OPTARG}
+ esac
+done
+shift $((OPTIND-1))
+
+#******************************************************************************
+# Helper functions
+#******************************************************************************
+
+azLogin() {
+ (
+ set +e
+ #login to azure using your credentials
+ az account show &> /dev/null
+
+ if [ $? != 0 ];
+ then
+ echo "Azure login required..."
+ az login -o table
+ else
+ az account list -o table
+ fi
+ )
+}
+
+validatedRead() {
+ prompt=$1
+ regex=$2
+ error=$3
+
+ userInput=""
+ while [[ ! $userInput =~ $regex ]]; do
+ if [[ (-n $userInput) ]]; then
+ printf "'%s' is not valid. %s\n" $userInput $error
+ fi
+ printf $prompt
+ read userInput
+ done
+}
+
+readSubscriptionId () {
+ currentSub="$(az account show -o tsv | cut -f2)"
+ subNames="$(az account list -o tsv | cut -f4)"
+ subIds="$(az account list -o tsv | cut -f2)"
+
+ while ([[ -z "$subscriptionId" ]]); do
+ printf "Enter your subscription ID [%s]: " $currentSub
+ read userInput
+
+ if [[ (-z "$userInput") && (-n "$currentSub")]]; then
+ userInput=$currentSub
+ fi
+
+ set +e
+ nameExists="$(echo $subNames | grep $userInput)"
+ idExists="$(echo $subIds | grep $userInput)"
+
+ if [[ (-z "$nameExists") && (-z "$idExists") ]]; then
+ printf "'${userInput}' is not a valid subscription name or ID.\n"
+ else
+ subscriptionId=$userInput
+ printf "Using subscription '$subscriptionId'...\n"
+ fi
+ done
+}
+
+readResourceGroupName () {
+ printf "Existing resource groups:\n"
+ groups="$(az group list -o tsv | cut -f4 | tr '\n' ', ' | sed "s/,/, /g")"
+ printf "\n%s\n" "${groups%??}"
+ validatedRead "\nEnter a resource group name: " "^[a-zA-Z0-9_]+$" "Only letters, numbers and underscores are allowed."
+ resourceGroupName=$userInput
+
+ set +e
+
+ #Check for existing RG
+ az group show --name $resourceGroupName &> /dev/null
+ if [ $? != 0 ]; then
+ echo "To create a new resource group, please enter an Azure location:"
+ readLocation
+
+ (set -ex; az group create --name $resourceGroupName --location $resourceGroupLocation)
+ else
+ resourceGroupLocation="$(az group show -n $resourceGroupName -o tsv | cut -f2)"
+ printf "Using resource group '$resourceGroupName'...\n"
+ fi
+
+ set -e
+}
+
+readLocation() {
+ if [[ -z "$resourceGroupLocation" ]]; then
+ locations="$(az account list-locations --output tsv | cut -f5 | tr '\n' ', ' | sed "s/,/, /g")"
+ printf "\n%s\n" "${locations%??}"
+
+ declare locationExists
+ while ([[ -z $resourceGroupLocation ]]); do
+ validatedRead "\nEnter resource group location: " "^[a-zA-Z0-9]+$" "Only letters & numbers are allowed."
+ locationExists="$(echo $locations | grep $userInput)"
+ if [[ -z $locationExists ]]; then
+ printf "'${userInput}' is not a valid location.\n"
+ else
+ resourceGroupLocation=$userInput
+ printf "Using resource group '$resourceGroupName'...\n"
+ fi
+ done
+ fi
+}
+
+readDbName () {
+ dbNames="$(az cosmosdb list -g $resourceGroupName -o tsv | cut -f12)"
+ defaultDb=(${dbNames[@]})
+
+ while ([[ -z "$dbName" ]]); do
+ printf "Cosmos DB instances in group '$resourceGroupName':\n\n"
+ dbNames="$(az cosmosdb list -g $resourceGroupName -o tsv | cut -f12 | tr '\n' ', ' | sed "s/,/, /g")"
+ printf "${dbNames%??}\n\n"
+
+ printf "Enter the Cosmos DB name [%s]: " $defaultDb
+ read userInput
+
+ if [[ (-z "$userInput") && (-n "$defaultDb")]]; then
+ userInput=$defaultDb
+ fi
+
+ set +e
+ nameExists="$(echo $dbNames | grep $userInput)"
+
+ if [[ (-z "$nameExists") ]]; then
+ printf "'${userInput}' is not a valid Cosmos DB name.\n"
+ else
+ dbName=$userInput
+ printf "Using database '$dbName'...\n"
+
+ fi
+ done
+}
+
+#******************************************************************************
+# Script to set environment variables
+#******************************************************************************
+
+azLogin
+
+#Prompt for parameters if some required parameters are missing
+if [[ -z "$subscriptionId" ]]; then
+ echo
+ readSubscriptionId
+fi
+
+#set the default subscription id
+az account set --subscription $subscriptionId
+
+if [[ -z "$resourceGroupName" ]]; then
+ echo
+ readResourceGroupName
+fi
+
+if [[ -z "$dbName" ]]; then
+ echo
+ readDbName
+fi
+
+# At this time, list-connection-strings does not support '-o tsv', so this command uses sed to extract the connection string from json results
+connString="$(az cosmosdb list-connection-strings --ids $dbName -g $resourceGroupName | sed -n -e '4 p' | sed -E -e 's/.*mongo(.*)true.*/mongo\1true/')"
+# But list-keys does support `-o tsv`
+dbPassword="$(az cosmosdb list-keys --resource-group $resourceGroupName --name $dbName -o tsv | sed -e 's/\s.*$//')"
+
+touch vars.env
+echo "export RESOURCE_GROUP=${resourceGroupName}" > vars.env
+echo "export COSMOSDB_NAME=${dbName}" >> vars.env
+echo "export COSMOSDB_PASSWORD=${dbPassword}" >> vars.env
+# Creates a distinction - some of these ENV variables will be used exclusively to connect to an Azure CosmosDB instance,
+# but in an Azure-agnostic setup, the DB_NAME and DB_CONNSTR may not be on CosmosDB
+echo "export DB_NAME=${dbName}" >> vars.env
+echo "export DB_CONNSTR=${connString}" >> vars.env
+echo
+echo "Variables written to file 'vars.env'"
+echo
+
diff --git a/ui/.gitignore b/ui/.gitignore
new file mode 100644
index 0000000..234f9ca
--- /dev/null
+++ b/ui/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+dist/
+.vscode/
\ No newline at end of file
diff --git a/ui/Dockerfile b/ui/Dockerfile
new file mode 100644
index 0000000..986f4ed
--- /dev/null
+++ b/ui/Dockerfile
@@ -0,0 +1,12 @@
+# Nginx web server from the official docker registry
+FROM nginx:1.14.0-alpine
+
+EXPOSE 8080
+
+RUN rm -rv /etc/nginx/conf.d
+COPY conf /etc/nginx
+
+# The static site is built using npm run build
+# the output of build is stored in the dist dir
+WORKDIR /usr/share/nginx/html
+COPY ./dist/ /usr/share/nginx/html
\ No newline at end of file
diff --git a/ui/README.md b/ui/README.md
new file mode 100644
index 0000000..bbe9dda
--- /dev/null
+++ b/ui/README.md
@@ -0,0 +1,23 @@
+# Project Jackson Client
+
+- Built using `React`
+- Compiled and bundled using `TypeScript` and `Webpack`
+- Tested using `Jest` and `Enzyme`
+
+## Deploy
+
+In order to deploy this app, in development or production, you must define the AAD Client ID as an environment variable. It will be injected during build time with Webpack. The environment variable that needs to be set is called `WEBPACK_PROP_AAD_CLIENT_ID` and is provided by your AAD App settings available on the AAD Azure Portal.
+
+In development, you should need to set the env variable on process and then run `npm run dev` as usual. For example, on a UNIX Bash shell you can run `WEBPACK_PROP_AAD_CLIENT_ID= npm run dev`.
+
+In production, make sure to set this in the build pipeline such as in Azure Dev Ops.
+
+## Contributing
+
+Run `npm run dev` to launch a hot-reloading webpack server
+
+Before commiting your changes make sure to run `npm run lint`
+
+Testing with `npm run test` will run all test files in the `src/__tests__` directory
+
+The `conf` directory is for production deployment purposes with NGINX
diff --git a/ui/azure-pipelines.yml b/ui/azure-pipelines.yml
new file mode 100644
index 0000000..fe862c1
--- /dev/null
+++ b/ui/azure-pipelines.yml
@@ -0,0 +1,38 @@
+trigger:
+ branches:
+ include:
+ - master
+ paths:
+ include:
+ - ui/*
+
+pool:
+ vmImage: 'Ubuntu 16.04'
+
+steps:
+- task: NodeTool@0
+ inputs:
+ versionSpec: '10.13.0'
+ failOnStandardError: 'true'
+ displayName: 'Install Node.js'
+- script: |
+ npm install
+ displayName: 'NPM Install Step'
+- script: |
+ npm run lint
+ displayName: 'NPM Lint Step'
+- script: |
+ npm run test
+ displayName: 'NPM Test Step'
+- script: |
+ npm run build
+ displayName: 'NPM Build Step'
+- script: |
+ docker build -t $ACR_SERVER/$ACR_CONTAINER_TAG .
+ displayName: 'Docker Build'
+- script: |
+ docker login $(ACR_SERVER) -u $(ACR_USERNAME) -p $(ACR_PASSWORD)
+ displayName: 'Docker Login'
+- script: |
+ docker push $ACR_SERVER/$ACR_CONTAINER_TAG
+ displayName: 'Docker Push'
diff --git a/ui/conf/conf.d/default.conf b/ui/conf/conf.d/default.conf
new file mode 100644
index 0000000..5af03a8
--- /dev/null
+++ b/ui/conf/conf.d/default.conf
@@ -0,0 +1,17 @@
+server {
+ listen 8080;
+ server_name localhost;
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html index.htm;
+ try_files $uri $uri/ /index.html;
+ }
+
+ # redirect server error pages to the static page /50x.html
+ #
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root /usr/share/nginx/html;
+ }
+}
\ No newline at end of file
diff --git a/ui/jest.config.js b/ui/jest.config.js
new file mode 100644
index 0000000..dbee367
--- /dev/null
+++ b/ui/jest.config.js
@@ -0,0 +1,22 @@
+module.exports = {
+ moduleFileExtensions: [ "ts", "tsx", "js" ],
+ transform: {
+ "^.+\\.(ts|tsx)$": "ts-jest"
+ },
+ globals: {
+ "ts-jest": {
+ "tsConfig": "tsconfig.json"
+ },
+ "WEBPACK_PROP_AAD_CLIENT_ID": ''
+ },
+ testMatch: [
+ "**/__tests__/**/*.(ts|tsx|js)"
+ ],
+ testPathIgnorePatterns: [
+ "setup.ts"
+ ],
+ moduleNameMapper: {
+ "\\.(css)$": "identity-obj-proxy"
+ },
+ setupTestFrameworkScriptFile: "/src/__tests__/setup.ts"
+}
\ No newline at end of file
diff --git a/ui/package-lock.json b/ui/package-lock.json
new file mode 100644
index 0000000..27dfbd3
--- /dev/null
+++ b/ui/package-lock.json
@@ -0,0 +1,9896 @@
+{
+ "name": "projectjacksonclient",
+ "version": "1.0.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"
+ }
+ },
+ "@reach/router": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.2.1.tgz",
+ "integrity": "sha512-kTaX08X4g27tzIFQGRukaHmNbtMYDS3LEWIS8+l6OayGIw6Oyo1HIF/JzeuR2FoF9z6oV+x/wJSVSq4v8tcUGQ==",
+ "requires": {
+ "create-react-context": "^0.2.1",
+ "invariant": "^2.2.3",
+ "prop-types": "^15.6.1",
+ "react-lifecycles-compat": "^3.0.4",
+ "warning": "^3.0.0"
+ }
+ },
+ "@types/cheerio": {
+ "version": "0.22.9",
+ "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.9.tgz",
+ "integrity": "sha512-q6LuBI0t5u04f0Q4/R+cGBqIbZMtJkVvCSF+nTfFBBdQqQvJR/mNHeWjRkszyLl7oyf2rDoKUYMEjTw5AV0hiw==",
+ "dev": true
+ },
+ "@types/enzyme": {
+ "version": "3.1.15",
+ "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.1.15.tgz",
+ "integrity": "sha512-6b4JWgV+FNec1c4+8HauGbXg5gRc1oQK93t2+4W+bHjG/PzO+iPvagY6d6bXAZ+t+ps51Zb2F9LQ4vl0S0Epog==",
+ "dev": true,
+ "requires": {
+ "@types/cheerio": "*",
+ "@types/react": "*"
+ }
+ },
+ "@types/history": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.2.tgz",
+ "integrity": "sha512-ui3WwXmjTaY73fOQ3/m3nnajU/Orhi6cEu5rzX+BrAAJxa3eITXZ5ch9suPqtM03OWhAHhPSyBGCN4UKoxO20Q==",
+ "dev": true
+ },
+ "@types/jest": {
+ "version": "23.3.8",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.8.tgz",
+ "integrity": "sha512-OKDxB/7woaQfUKkj+7+Zo3PmAxAYAy+SNwOwFhnYAc8JTaPhGOv8SC6QQg5D9+Giprhx/DzoKbJIpV9799VV0g==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "10.12.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz",
+ "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==",
+ "dev": true
+ },
+ "@types/prop-types": {
+ "version": "15.5.6",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.6.tgz",
+ "integrity": "sha512-ZBFR7TROLVzCkswA3Fmqq+IIJt62/T7aY/Dmz+QkU7CaW2QFqAitCE8Ups7IzmGhcN1YWMBT4Qcoc07jU9hOJQ==",
+ "dev": true
+ },
+ "@types/reach__router": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.2.1.tgz",
+ "integrity": "sha512-gzQuJDszKU1uyAgyJtR+vkrK9F6w6GfiR1uWn0rMYzuou/3wO5388m5ymUQDtTTjUcSSID/cMvQiCE8N/eOWRQ==",
+ "dev": true,
+ "requires": {
+ "@types/history": "*",
+ "@types/react": "*"
+ }
+ },
+ "@types/react": {
+ "version": "16.4.18",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.18.tgz",
+ "integrity": "sha512-eFzJKEg6pdeaukVLVZ8Xb79CTl/ysX+ExmOfAAqcFlCCK5TgFDD9kWR0S18sglQ3EmM8U+80enjUqbfnUyqpdA==",
+ "dev": true,
+ "requires": {
+ "@types/prop-types": "*",
+ "csstype": "^2.2.0"
+ }
+ },
+ "@types/react-dom": {
+ "version": "16.0.9",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.0.9.tgz",
+ "integrity": "sha512-4Z0bW+75zeQgsEg7RaNuS1k9MKhci7oQqZXxrV5KUGIyXZHHAAL3KA4rjhdH8o6foZ5xsRMSqkoM5A3yRVPR5w==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "@types/react": "*"
+ }
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.10.tgz",
+ "integrity": "sha512-wTUeaByYN2EA6qVqhbgavtGc7fLTOx0glG2IBsFlrFG51uXIGlYBTyIZMf4SPLo3v1bgV/7lBN3l7Z0R6Hswew==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/wast-parser": "1.7.10"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.10.tgz",
+ "integrity": "sha512-gMsGbI6I3p/P1xL2UxqhNh1ga2HCsx5VBB2i5VvJFAaqAjd2PBTRULc3BpTydabUQEGlaZCzEUQhLoLG7TvEYQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.10.tgz",
+ "integrity": "sha512-DoYRlPWtuw3yd5BOr9XhtrmB6X1enYF0/54yNvQWGXZEPDF5PJVNI7zQ7gkcKfTESzp8bIBWailaFXEK/jjCsw==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.10.tgz",
+ "integrity": "sha512-+RMU3dt/dPh4EpVX4u5jxsOlw22tp3zjqE0m3ftU2tsYxnPULb4cyHlgaNd2KoWuwasCQqn8Mhr+TTdbtj3LlA==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.10.tgz",
+ "integrity": "sha512-UiytbpKAULOEab2hUZK2ywXen4gWJVrgxtwY3Kn+eZaaSWaRM8z/7dAXRSoamhKFiBh1uaqxzE/XD9BLlug3gw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.7.10"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.10.tgz",
+ "integrity": "sha512-w2vDtUK9xeSRtt5+RnnlRCI7wHEvLjF0XdnxJpgx+LJOvklTZPqWkuy/NhwHSLP19sm9H8dWxKeReMR7sCkGZA==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.10.tgz",
+ "integrity": "sha512-yE5x/LzZ3XdPdREmJijxzfrf+BDRewvO0zl8kvORgSWmxpRrkqY39KZSq6TSgIWBxkK4SrzlS3BsMCv2s1FpsQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.10.tgz",
+ "integrity": "sha512-u5qy4SJ/OrxKxZqJ9N3qH4ZQgHaAzsopsYwLvoWJY6Q33r8PhT3VPyNMaJ7ZFoqzBnZlCcS/0f4Sp8WBxylXfg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.10.tgz",
+ "integrity": "sha512-Ecvww6sCkcjatcyctUrn22neSJHLN/TTzolMGG/N7S9rpbsTZ8c6Bl98GpSpV77EvzNijiNRHBG0+JO99qKz6g==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-buffer": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/wasm-gen": "1.7.10"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.10.tgz",
+ "integrity": "sha512-HRcWcY+YWt4+s/CvQn+vnSPfRaD4KkuzQFt5MNaELXXHSjelHlSEA8ZcqT69q0GTIuLWZ6JaoKar4yWHVpZHsQ==",
+ "dev": true,
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.10.tgz",
+ "integrity": "sha512-og8MciYlA8hvzCLR71hCuZKPbVBfLQeHv7ImKZ4nlyxrYbG7uJHYtHiHu6OV9SqrGuD03H/HtXC4Bgdjfm9FHw==",
+ "dev": true,
+ "requires": {
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.10.tgz",
+ "integrity": "sha512-Ng6Pxv6siyZp635xCSnH3mKmIFgqWPCcGdoo0GBYgyGdxu7cUj4agV7Uu1a8REP66UYUFXJLudeGgd4RvuJAnQ==",
+ "dev": true
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.10.tgz",
+ "integrity": "sha512-e9RZFQlb+ZuYcKRcW9yl+mqX/Ycj9+3/+ppDI8nEE/NCY6FoK8f3dKBcfubYV/HZn44b+ND4hjh+4BYBt+sDnA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-buffer": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/helper-wasm-section": "1.7.10",
+ "@webassemblyjs/wasm-gen": "1.7.10",
+ "@webassemblyjs/wasm-opt": "1.7.10",
+ "@webassemblyjs/wasm-parser": "1.7.10",
+ "@webassemblyjs/wast-printer": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.10.tgz",
+ "integrity": "sha512-M0lb6cO2Y0PzDye/L39PqwV+jvO+2YxEG5ax+7dgq7EwXdAlpOMx1jxyXJTScQoeTpzOPIb+fLgX/IkLF8h2yw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/ieee754": "1.7.10",
+ "@webassemblyjs/leb128": "1.7.10",
+ "@webassemblyjs/utf8": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.10.tgz",
+ "integrity": "sha512-R66IHGCdicgF5ZliN10yn5HaC7vwYAqrSVJGjtJJQp5+QNPBye6heWdVH/at40uh0uoaDN/UVUfXK0gvuUqtVg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-buffer": "1.7.10",
+ "@webassemblyjs/wasm-gen": "1.7.10",
+ "@webassemblyjs/wasm-parser": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.10.tgz",
+ "integrity": "sha512-AEv8mkXVK63n/iDR3T693EzoGPnNAwKwT3iHmKJNBrrALAhhEjuPzo/lTE4U7LquEwyvg5nneSNdTdgrBaGJcA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-api-error": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/ieee754": "1.7.10",
+ "@webassemblyjs/leb128": "1.7.10",
+ "@webassemblyjs/utf8": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.10.tgz",
+ "integrity": "sha512-YTPEtOBljkCL0VjDp4sHe22dAYSm3ZwdJ9+2NTGdtC7ayNvuip1wAhaAS8Zt9Q6SW9E5Jf5PX7YE3XWlrzR9cw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/floating-point-hex-parser": "1.7.10",
+ "@webassemblyjs/helper-api-error": "1.7.10",
+ "@webassemblyjs/helper-code-frame": "1.7.10",
+ "@webassemblyjs/helper-fsm": "1.7.10",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.10.tgz",
+ "integrity": "sha512-mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/wast-parser": "1.7.10",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true
+ },
+ "@xtuc/long": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz",
+ "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==",
+ "dev": true
+ },
+ "abab": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
+ "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==",
+ "dev": true
+ },
+ "accepts": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.18",
+ "negotiator": "0.6.1"
+ }
+ },
+ "acorn": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "dev": true
+ },
+ "acorn-dynamic-import": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
+ "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
+ "dev": true,
+ "requires": {
+ "acorn": "^5.0.0"
+ }
+ },
+ "acorn-globals": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz",
+ "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^6.0.1",
+ "acorn-walk": "^6.0.1"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz",
+ "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==",
+ "dev": true
+ }
+ }
+ },
+ "acorn-walk": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.0.tgz",
+ "integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+ "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
+ "dev": true,
+ "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"
+ }
+ },
+ "ajv-errors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz",
+ "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=",
+ "dev": true
+ },
+ "ajv-keywords": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+ "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
+ "dev": true
+ },
+ "ansi-colors": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.1.tgz",
+ "integrity": "sha512-Xt+zb6nqgvV9SWAVp0EG3lRsHcbq5DDgqjPPz6pwgtj6RKz65zGXMNa82oJfOSBA/to6GmRP7Dr+6o+kbApTzQ==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
+ "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
+ "dev": true
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+ "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"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "append-transform": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz",
+ "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=",
+ "dev": true,
+ "requires": {
+ "default-require-extensions": "^1.0.0"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+ "dev": true
+ },
+ "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": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
+ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
+ "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "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=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "array.prototype.flat": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz",
+ "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.10.0",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "dev": true,
+ "requires": {
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "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=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.10"
+ }
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+ "dev": 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==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true
+ },
+ "awesome-typescript-loader": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz",
+ "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "enhanced-resolve": "^4.0.0",
+ "loader-utils": "^1.1.0",
+ "lodash": "^4.17.5",
+ "micromatch": "^3.1.9",
+ "mkdirp": "^0.5.1",
+ "source-map-support": "^0.5.3",
+ "webpack-log": "^1.2.0"
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "dev": true
+ },
+ "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=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "babel-core": {
+ "version": "6.26.3",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
+ "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
+ "dev": true,
+ "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"
+ }
+ },
+ "babel-generator": {
+ "version": "6.26.1",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+ "dev": true,
+ "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-helpers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1"
+ }
+ },
+ "babel-jest": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz",
+ "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-istanbul": "^4.1.6",
+ "babel-preset-jest": "^23.2.0"
+ }
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-istanbul": {
+ "version": "4.1.6",
+ "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
+ "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-syntax-object-rest-spread": "^6.13.0",
+ "find-up": "^2.1.0",
+ "istanbul-lib-instrument": "^1.10.1",
+ "test-exclude": "^4.2.1"
+ }
+ },
+ "babel-plugin-jest-hoist": {
+ "version": "23.2.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz",
+ "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=",
+ "dev": true
+ },
+ "babel-plugin-syntax-object-rest-spread": {
+ "version": "6.13.0",
+ "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+ "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
+ "dev": true
+ },
+ "babel-preset-jest": {
+ "version": "23.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz",
+ "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-jest-hoist": "^23.2.0",
+ "babel-plugin-syntax-object-rest-spread": "^6.13.0"
+ }
+ },
+ "babel-register": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+ "dev": true,
+ "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"
+ },
+ "dependencies": {
+ "source-map-support": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.5.6"
+ }
+ }
+ }
+ },
+ "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=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "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==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "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==",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
+ "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
+ "dev": true
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "big.js": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz",
+ "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
+ "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==",
+ "dev": true
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.18.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+ "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+ "dev": true,
+ "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"
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "dev": true,
+ "requires": {
+ "array-flatten": "^2.1.0",
+ "deep-equal": "^1.0.1",
+ "dns-equal": "^1.0.0",
+ "dns-txt": "^2.0.2",
+ "multicast-dns": "^6.0.1",
+ "multicast-dns-service-types": "^1.1.0"
+ }
+ },
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+ "dev": true
+ },
+ "browser-process-hrtime": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
+ "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==",
+ "dev": true
+ },
+ "browser-resolve": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz",
+ "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==",
+ "dev": true,
+ "requires": {
+ "resolve": "1.1.7"
+ },
+ "dependencies": {
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ }
+ }
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "dev": true,
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.1",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.2",
+ "elliptic": "^6.0.0",
+ "inherits": "^2.0.1",
+ "parse-asn1": "^5.0.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "dev": true,
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "bs-logger": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.5.tgz",
+ "integrity": "sha512-uFLE0LFMxrH8Z5Hd9QgivvRbrl/NFkOTHzGhlqQxsnmx5JBLrp4bc249afLL+GccyY/8hkcGi2LpVaOzaEY0nQ==",
+ "dev": true,
+ "requires": {
+ "fast-json-stable-stringify": "^2.0.0"
+ }
+ },
+ "bser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz",
+ "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=",
+ "dev": true,
+ "requires": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "cacache": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+ "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.1",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.2",
+ "ssri": "^5.2.4",
+ "unique-filename": "^1.1.0",
+ "y18n": "^4.0.0"
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "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"
+ }
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ },
+ "camel-case": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "dev": true,
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.1.1"
+ }
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ },
+ "capture-exit": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz",
+ "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=",
+ "dev": true,
+ "requires": {
+ "rsvp": "^3.3.3"
+ }
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "cheerio": {
+ "version": "1.0.0-rc.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
+ "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash": "^4.15.0",
+ "parse5": "^3.0.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.3.0",
+ "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
+ "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.0.6"
+ }
+ },
+ "parse5": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "readable-stream": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.0.6.tgz",
+ "integrity": "sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "chokidar": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
+ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.0",
+ "braces": "^2.3.0",
+ "fsevents": "^1.2.2",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.1",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "lodash.debounce": "^4.0.8",
+ "normalize-path": "^2.1.1",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.0.0",
+ "upath": "^1.0.5"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+ "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
+ "dev": true
+ },
+ "chrome-trace-event": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz",
+ "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "ci-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+ "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "clean-css": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "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"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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=",
+ "dev": true
+ },
+ "colors": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz",
+ "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+ "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "compressible": {
+ "version": "2.0.15",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz",
+ "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==",
+ "dev": true,
+ "requires": {
+ "mime-db": ">= 1.36.0 < 2"
+ }
+ },
+ "compression": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz",
+ "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.14",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.1",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
+ "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=",
+ "dev": true
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "dev": true,
+ "requires": {
+ "date-now": "^0.1.4"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+ "dev": true
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+ "dev": true
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "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=",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "core-js": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
+ "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "create-react-context": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
+ "integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
+ "requires": {
+ "fbjs": "^0.8.0",
+ "gud": "^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"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "dev": true,
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "css": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
+ "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "source-map": "^0.6.1",
+ "source-map-resolve": "^0.5.2",
+ "urix": "^0.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "css-loader": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz",
+ "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.26.0",
+ "css-selector-tokenizer": "^0.7.0",
+ "icss-utils": "^2.1.0",
+ "loader-utils": "^1.0.2",
+ "lodash": "^4.17.11",
+ "postcss": "^6.0.23",
+ "postcss-modules-extract-imports": "^1.2.0",
+ "postcss-modules-local-by-default": "^1.2.0",
+ "postcss-modules-scope": "^1.1.0",
+ "postcss-modules-values": "^1.3.0",
+ "postcss-value-parser": "^3.3.0",
+ "source-list-map": "^2.0.0"
+ }
+ },
+ "css-select": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+ "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0",
+ "css-what": "2.1",
+ "domutils": "1.5.1",
+ "nth-check": "~1.0.1"
+ }
+ },
+ "css-selector-tokenizer": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+ "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^0.1.0",
+ "fastparse": "^1.1.1",
+ "regexpu-core": "^1.0.0"
+ }
+ },
+ "css-what": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz",
+ "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==",
+ "dev": true
+ },
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+ "dev": true
+ },
+ "cssom": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz",
+ "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==",
+ "dev": true
+ },
+ "cssstyle": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz",
+ "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==",
+ "dev": true,
+ "requires": {
+ "cssom": "0.3.x"
+ }
+ },
+ "csstype": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.7.tgz",
+ "integrity": "sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw==",
+ "dev": true
+ },
+ "cyclist": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+ "dev": true
+ },
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "^0.10.9"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "data-urls": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
+ "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
+ "dev": true,
+ "requires": {
+ "abab": "^2.0.0",
+ "whatwg-mimetype": "^2.2.0",
+ "whatwg-url": "^7.0.0"
+ },
+ "dependencies": {
+ "whatwg-url": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz",
+ "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^1.0.1",
+ "webidl-conversions": "^4.0.2"
+ }
+ }
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz",
+ "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==",
+ "dev": true,
+ "requires": {
+ "xregexp": "4.0.0"
+ }
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "deep-equal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "default-gateway": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz",
+ "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.10.0",
+ "ip-regex": "^2.1.0"
+ }
+ },
+ "default-require-extensions": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
+ "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=",
+ "dev": true,
+ "requires": {
+ "strip-bom": "^2.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
+ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
+ "dev": true,
+ "requires": {
+ "globby": "^6.1.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "p-map": "^1.1.1",
+ "pify": "^3.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+ "dev": true
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "detect-newline": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
+ "dev": true
+ },
+ "detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+ "dev": true
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "discontinuous-range": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+ "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
+ "dev": true
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "dev": true,
+ "requires": {
+ "buffer-indexof": "^1.0.0"
+ }
+ },
+ "dom-converter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+ "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+ "dev": true,
+ "requires": {
+ "utila": "~0.4"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "~1.1.1",
+ "entities": "~1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
+ "dev": true
+ }
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true
+ },
+ "domelementtype": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.2.1.tgz",
+ "integrity": "sha512-SQVCLFS2E7G5CRCMdn6K9bIhRj1bS6QBWZfF0TUPh4V/BbqrQ619IdSS3/izn0FZ+9l+uODzaZjb08fjOfablA==",
+ "dev": true
+ },
+ "domexception": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
+ "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
+ "dev": true,
+ "requires": {
+ "webidl-conversions": "^4.0.2"
+ }
+ },
+ "domhandler": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz",
+ "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "duplexify": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz",
+ "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "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=",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
+ "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "enzyme": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.7.0.tgz",
+ "integrity": "sha512-QLWx+krGK6iDNyR1KlH5YPZqxZCQaVF6ike1eDJAOg0HvSkSCVImPsdWaNw6v+VrnK92Kg8jIOYhuOSS9sBpyg==",
+ "dev": true,
+ "requires": {
+ "array.prototype.flat": "^1.2.1",
+ "cheerio": "^1.0.0-rc.2",
+ "function.prototype.name": "^1.1.0",
+ "has": "^1.0.3",
+ "is-boolean-object": "^1.0.0",
+ "is-callable": "^1.1.4",
+ "is-number-object": "^1.0.3",
+ "is-string": "^1.0.4",
+ "is-subset": "^0.1.1",
+ "lodash.escape": "^4.0.1",
+ "lodash.isequal": "^4.5.0",
+ "object-inspect": "^1.6.0",
+ "object-is": "^1.0.1",
+ "object.assign": "^4.1.0",
+ "object.entries": "^1.0.4",
+ "object.values": "^1.0.4",
+ "raf": "^3.4.0",
+ "rst-selector-parser": "^2.2.3",
+ "string.prototype.trim": "^1.1.2"
+ }
+ },
+ "enzyme-adapter-react-16": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.6.0.tgz",
+ "integrity": "sha512-ay9eGFpChyUDnjTFMMJHzrb681LF3hPWJLEA7RoLFG9jSWAdAm2V50pGmFV9dYGJgh5HfdiqM+MNvle41Yf/PA==",
+ "dev": true,
+ "requires": {
+ "enzyme-adapter-utils": "^1.8.0",
+ "function.prototype.name": "^1.1.0",
+ "object.assign": "^4.1.0",
+ "object.values": "^1.0.4",
+ "prop-types": "^15.6.2",
+ "react-is": "^16.5.2",
+ "react-test-renderer": "^16.0.0-0"
+ }
+ },
+ "enzyme-adapter-utils": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.8.1.tgz",
+ "integrity": "sha512-s3QB3xQAowaDS2sHhmEqrT13GJC4+n5bG015ZkLv60n9k5vhxxHTQRIneZmQ4hmdCZEBrvUJ89PG6fRI5OEeuQ==",
+ "dev": true,
+ "requires": {
+ "function.prototype.name": "^1.1.0",
+ "object.assign": "^4.1.0",
+ "prop-types": "^15.6.2"
+ }
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "dev": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
+ "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.1.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.1",
+ "is-callable": "^1.1.3",
+ "is-regex": "^1.0.4"
+ }
+ },
+ "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"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.46",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz",
+ "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "~2.0.3",
+ "es6-symbol": "~3.1.1",
+ "next-tick": "1"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "escodegen": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz",
+ "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==",
+ "dev": true,
+ "requires": {
+ "esprima": "^3.1.3",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "eslint-scope": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+ "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "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
+ },
+ "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=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
+ "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
+ "dev": true
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+ "dev": true
+ },
+ "eventsource": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+ "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+ "dev": true,
+ "requires": {
+ "original": "^1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "exec-sh": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz",
+ "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==",
+ "dev": true,
+ "requires": {
+ "merge": "^1.2.0"
+ }
+ },
+ "execa": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+ "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": 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=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^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=",
+ "dev": true,
+ "requires": {
+ "fill-range": "^2.1.0"
+ },
+ "dependencies": {
+ "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==",
+ "dev": 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"
+ }
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "expect": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz",
+ "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "jest-diff": "^23.6.0",
+ "jest-get-type": "^22.1.0",
+ "jest-matcher-utils": "^23.6.0",
+ "jest-message-util": "^23.4.0",
+ "jest-regex-util": "^23.3.0"
+ }
+ },
+ "express": {
+ "version": "4.16.4",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+ "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+ "dev": true,
+ "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": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": 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=",
+ "dev": 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=",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "fb-watchman": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz",
+ "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=",
+ "dev": true,
+ "requires": {
+ "bser": "^2.0.0"
+ }
+ },
+ "fbjs": {
+ "version": "0.8.17",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
+ "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
+ "requires": {
+ "core-js": "^1.0.0",
+ "isomorphic-fetch": "^2.1.1",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^0.7.18"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ }
+ }
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+ "dev": true
+ },
+ "fileset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
+ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.3",
+ "minimatch": "^3.0.3"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+ "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+ "dev": true,
+ "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"
+ }
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^1.0.0",
+ "pkg-dir": "^2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "flush-write-stream": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
+ "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.4"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.5.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz",
+ "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==",
+ "dev": true,
+ "requires": {
+ "debug": "=3.1.0"
+ },
+ "dependencies": {
+ "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"
+ }
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "dev": 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=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "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=",
+ "dev": true
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
+ "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.9.2",
+ "node-pre-gyp": "^0.10.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": 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.2",
+ "bundled": true,
+ "dev": 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,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.21",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.2.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.1",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^2.1.2",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.10.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.0",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.1.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.1.10",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": 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,
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.5.1",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": 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.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.0.5"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.5.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": 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,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.0.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.2.4",
+ "minizlib": "^1.1.0",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.1",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "function.prototype.name": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz",
+ "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "is-callable": "^1.1.3"
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "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==",
+ "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"
+ }
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "dev": true,
+ "requires": {
+ "glob-parent": "^2.0.0",
+ "is-glob": "^2.0.0"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^2.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ }
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "global-modules-path": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz",
+ "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==",
+ "dev": true
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true
+ },
+ "gud": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
+ "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
+ },
+ "handle-thing": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
+ "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz",
+ "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==",
+ "dev": true,
+ "requires": {
+ "async": "^2.5.0",
+ "optimist": "^0.6.1",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "dev": true,
+ "optional": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.4.9",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
+ "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "commander": "~2.17.1",
+ "source-map": "~0.6.1"
+ }
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
+ "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^5.3.0",
+ "har-schema": "^2.0.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "dev": true,
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true
+ }
+ }
+ },
+ "harmony-reflect": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.1.tgz",
+ "integrity": "sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ }
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "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=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "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=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz",
+ "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "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
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "dev": true,
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "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=",
+ "dev": true,
+ "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==",
+ "dev": true
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "html-encoding-sniffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
+ "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
+ "dev": true,
+ "requires": {
+ "whatwg-encoding": "^1.0.1"
+ }
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
+ "html-minifier": {
+ "version": "3.5.21",
+ "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
+ "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+ "dev": true,
+ "requires": {
+ "camel-case": "3.0.x",
+ "clean-css": "4.2.x",
+ "commander": "2.17.x",
+ "he": "1.2.x",
+ "param-case": "2.1.x",
+ "relateurl": "0.2.x",
+ "uglify-js": "3.4.x"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.4.9",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
+ "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.17.1",
+ "source-map": "~0.6.1"
+ }
+ }
+ }
+ },
+ "html-webpack-plugin": {
+ "version": "3.2.0",
+ "resolved": "http://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
+ "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
+ "dev": true,
+ "requires": {
+ "html-minifier": "^3.2.3",
+ "loader-utils": "^0.2.16",
+ "lodash": "^4.17.3",
+ "pretty-error": "^2.0.2",
+ "tapable": "^1.0.0",
+ "toposort": "^1.0.0",
+ "util.promisify": "1.0.0"
+ },
+ "dependencies": {
+ "loader-utils": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
+ "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
+ "dev": true,
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0",
+ "object-assign": "^4.0.1"
+ }
+ }
+ }
+ },
+ "htmlparser2": {
+ "version": "3.3.0",
+ "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
+ "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1",
+ "domhandler": "2.1",
+ "domutils": "1.1",
+ "readable-stream": "1.0"
+ },
+ "dependencies": {
+ "domutils": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz",
+ "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "http-parser-js": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz",
+ "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
+ "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^3.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.18.0",
+ "resolved": "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz",
+ "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==",
+ "dev": true,
+ "requires": {
+ "http-proxy": "^1.16.2",
+ "is-glob": "^4.0.0",
+ "lodash": "^4.17.5",
+ "micromatch": "^3.1.9"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "icss-replace-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
+ "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
+ "dev": true
+ },
+ "icss-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz",
+ "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=",
+ "dev": true,
+ "requires": {
+ "postcss": "^6.0.1"
+ }
+ },
+ "identity-obj-proxy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz",
+ "integrity": "sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ=",
+ "dev": true,
+ "requires": {
+ "harmony-reflect": "^1.4.6"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
+ "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==",
+ "dev": true
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+ "dev": true
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.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"
+ }
+ },
+ "p-limit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
+ "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
+ "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.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
+ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
+ "dev": true
+ },
+ "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"
+ }
+ }
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+ "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+ "dev": true
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "internal-ip": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz",
+ "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==",
+ "dev": true,
+ "requires": {
+ "default-gateway": "^2.6.0",
+ "ipaddr.js": "^1.5.2"
+ }
+ },
+ "interpret": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
+ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=",
+ "dev": true
+ },
+ "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": "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
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+ "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=",
+ "dev": true
+ },
+ "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=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-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=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz",
+ "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=",
+ "dev": true
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+ "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^1.5.0"
+ }
+ },
+ "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=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true
+ }
+ }
+ },
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+ "dev": 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=",
+ "dev": 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=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-generator-fn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz",
+ "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "dev": true,
+ "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=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-number-object": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz",
+ "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=",
+ "dev": true
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+ "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-string": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz",
+ "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=",
+ "dev": true
+ },
+ "is-subset": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
+ "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "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": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ }
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "istanbul-api": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz",
+ "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==",
+ "dev": true,
+ "requires": {
+ "async": "^2.1.4",
+ "fileset": "^2.0.2",
+ "istanbul-lib-coverage": "^1.2.1",
+ "istanbul-lib-hook": "^1.2.2",
+ "istanbul-lib-instrument": "^1.10.2",
+ "istanbul-lib-report": "^1.1.5",
+ "istanbul-lib-source-maps": "^1.2.6",
+ "istanbul-reports": "^1.5.1",
+ "js-yaml": "^3.7.0",
+ "mkdirp": "^0.5.1",
+ "once": "^1.4.0"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz",
+ "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==",
+ "dev": true
+ },
+ "istanbul-lib-hook": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz",
+ "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==",
+ "dev": true,
+ "requires": {
+ "append-transform": "^0.4.0"
+ }
+ },
+ "istanbul-lib-instrument": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz",
+ "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==",
+ "dev": true,
+ "requires": {
+ "babel-generator": "^6.18.0",
+ "babel-template": "^6.16.0",
+ "babel-traverse": "^6.18.0",
+ "babel-types": "^6.18.0",
+ "babylon": "^6.18.0",
+ "istanbul-lib-coverage": "^1.2.1",
+ "semver": "^5.3.0"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz",
+ "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^1.2.1",
+ "mkdirp": "^0.5.1",
+ "path-parse": "^1.0.5",
+ "supports-color": "^3.1.2"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true,
+ "requires": {
+ "has-flag": "^1.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz",
+ "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.1.0",
+ "istanbul-lib-coverage": "^1.2.1",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.6.1",
+ "source-map": "^0.5.3"
+ },
+ "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
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz",
+ "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==",
+ "dev": true,
+ "requires": {
+ "handlebars": "^4.0.3"
+ }
+ },
+ "jest": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz",
+ "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==",
+ "dev": true,
+ "requires": {
+ "import-local": "^1.0.0",
+ "jest-cli": "^23.6.0"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^1.8.1",
+ "preserve": "^0.2.0",
+ "repeat-element": "^1.1.2"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "^0.1.0"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "import-local": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
+ "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^2.0.0",
+ "resolve-cwd": "^2.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=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "jest-cli": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz",
+ "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "import-local": "^1.0.0",
+ "is-ci": "^1.0.10",
+ "istanbul-api": "^1.3.1",
+ "istanbul-lib-coverage": "^1.2.0",
+ "istanbul-lib-instrument": "^1.10.1",
+ "istanbul-lib-source-maps": "^1.2.4",
+ "jest-changed-files": "^23.4.2",
+ "jest-config": "^23.6.0",
+ "jest-environment-jsdom": "^23.4.0",
+ "jest-get-type": "^22.1.0",
+ "jest-haste-map": "^23.6.0",
+ "jest-message-util": "^23.4.0",
+ "jest-regex-util": "^23.3.0",
+ "jest-resolve-dependencies": "^23.6.0",
+ "jest-runner": "^23.6.0",
+ "jest-runtime": "^23.6.0",
+ "jest-snapshot": "^23.6.0",
+ "jest-util": "^23.4.0",
+ "jest-validate": "^23.6.0",
+ "jest-watcher": "^23.4.0",
+ "jest-worker": "^23.2.0",
+ "micromatch": "^2.3.11",
+ "node-notifier": "^5.2.1",
+ "prompts": "^0.1.9",
+ "realpath-native": "^1.0.0",
+ "rimraf": "^2.5.4",
+ "slash": "^1.0.0",
+ "string-length": "^2.0.0",
+ "strip-ansi": "^4.0.0",
+ "which": "^1.2.12",
+ "yargs": "^11.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": 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"
+ }
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "11.1.0",
+ "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
+ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^9.0.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
+ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+ },
+ "jest-changed-files": {
+ "version": "23.4.2",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz",
+ "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==",
+ "dev": true,
+ "requires": {
+ "throat": "^4.0.0"
+ }
+ },
+ "jest-config": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz",
+ "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==",
+ "dev": true,
+ "requires": {
+ "babel-core": "^6.0.0",
+ "babel-jest": "^23.6.0",
+ "chalk": "^2.0.1",
+ "glob": "^7.1.1",
+ "jest-environment-jsdom": "^23.4.0",
+ "jest-environment-node": "^23.4.0",
+ "jest-get-type": "^22.1.0",
+ "jest-jasmine2": "^23.6.0",
+ "jest-regex-util": "^23.3.0",
+ "jest-resolve": "^23.6.0",
+ "jest-util": "^23.4.0",
+ "jest-validate": "^23.6.0",
+ "micromatch": "^2.3.11",
+ "pretty-format": "^23.6.0"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^1.8.1",
+ "preserve": "^0.2.0",
+ "repeat-element": "^1.1.2"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "^0.1.0"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": 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"
+ }
+ }
+ }
+ },
+ "jest-diff": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz",
+ "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1",
+ "diff": "^3.2.0",
+ "jest-get-type": "^22.1.0",
+ "pretty-format": "^23.6.0"
+ }
+ },
+ "jest-docblock": {
+ "version": "23.2.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz",
+ "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=",
+ "dev": true,
+ "requires": {
+ "detect-newline": "^2.1.0"
+ }
+ },
+ "jest-dom": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/jest-dom/-/jest-dom-2.1.0.tgz",
+ "integrity": "sha512-1kUVHGqvsJYK9u0sTAihDp9IRIwngMH7JghRaQWB6WluWf0/2L6MxTEE2U4x7aRN6H89bfPeCu8zjlO+/nBqgw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "css": "^2.2.3",
+ "jest-diff": "^23.6.0",
+ "jest-matcher-utils": "^23.6.0",
+ "lodash": "^4.17.11",
+ "pretty-format": "^23.6.0",
+ "redent": "^2.0.0"
+ }
+ },
+ "jest-each": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz",
+ "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1",
+ "pretty-format": "^23.6.0"
+ }
+ },
+ "jest-environment-jsdom": {
+ "version": "23.4.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz",
+ "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=",
+ "dev": true,
+ "requires": {
+ "jest-mock": "^23.2.0",
+ "jest-util": "^23.4.0",
+ "jsdom": "^11.5.1"
+ }
+ },
+ "jest-environment-node": {
+ "version": "23.4.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz",
+ "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=",
+ "dev": true,
+ "requires": {
+ "jest-mock": "^23.2.0",
+ "jest-util": "^23.4.0"
+ }
+ },
+ "jest-get-type": {
+ "version": "22.4.3",
+ "resolved": "http://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz",
+ "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==",
+ "dev": true
+ },
+ "jest-haste-map": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz",
+ "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==",
+ "dev": true,
+ "requires": {
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.1.11",
+ "invariant": "^2.2.4",
+ "jest-docblock": "^23.2.0",
+ "jest-serializer": "^23.0.1",
+ "jest-worker": "^23.2.0",
+ "micromatch": "^2.3.11",
+ "sane": "^2.0.0"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^1.8.1",
+ "preserve": "^0.2.0",
+ "repeat-element": "^1.1.2"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "^0.1.0"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": 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"
+ }
+ }
+ }
+ },
+ "jest-jasmine2": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz",
+ "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==",
+ "dev": true,
+ "requires": {
+ "babel-traverse": "^6.0.0",
+ "chalk": "^2.0.1",
+ "co": "^4.6.0",
+ "expect": "^23.6.0",
+ "is-generator-fn": "^1.0.0",
+ "jest-diff": "^23.6.0",
+ "jest-each": "^23.6.0",
+ "jest-matcher-utils": "^23.6.0",
+ "jest-message-util": "^23.4.0",
+ "jest-snapshot": "^23.6.0",
+ "jest-util": "^23.4.0",
+ "pretty-format": "^23.6.0"
+ }
+ },
+ "jest-leak-detector": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz",
+ "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==",
+ "dev": true,
+ "requires": {
+ "pretty-format": "^23.6.0"
+ }
+ },
+ "jest-matcher-utils": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz",
+ "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1",
+ "jest-get-type": "^22.1.0",
+ "pretty-format": "^23.6.0"
+ }
+ },
+ "jest-message-util": {
+ "version": "23.4.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz",
+ "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0-beta.35",
+ "chalk": "^2.0.1",
+ "micromatch": "^2.3.11",
+ "slash": "^1.0.0",
+ "stack-utils": "^1.0.1"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^1.8.1",
+ "preserve": "^0.2.0",
+ "repeat-element": "^1.1.2"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "^0.1.0"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": 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"
+ }
+ }
+ }
+ },
+ "jest-mock": {
+ "version": "23.2.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz",
+ "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=",
+ "dev": true
+ },
+ "jest-regex-util": {
+ "version": "23.3.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz",
+ "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=",
+ "dev": true
+ },
+ "jest-resolve": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz",
+ "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==",
+ "dev": true,
+ "requires": {
+ "browser-resolve": "^1.11.3",
+ "chalk": "^2.0.1",
+ "realpath-native": "^1.0.0"
+ }
+ },
+ "jest-resolve-dependencies": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz",
+ "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==",
+ "dev": true,
+ "requires": {
+ "jest-regex-util": "^23.3.0",
+ "jest-snapshot": "^23.6.0"
+ }
+ },
+ "jest-runner": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz",
+ "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==",
+ "dev": true,
+ "requires": {
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.1.11",
+ "jest-config": "^23.6.0",
+ "jest-docblock": "^23.2.0",
+ "jest-haste-map": "^23.6.0",
+ "jest-jasmine2": "^23.6.0",
+ "jest-leak-detector": "^23.6.0",
+ "jest-message-util": "^23.4.0",
+ "jest-runtime": "^23.6.0",
+ "jest-util": "^23.4.0",
+ "jest-worker": "^23.2.0",
+ "source-map-support": "^0.5.6",
+ "throat": "^4.0.0"
+ }
+ },
+ "jest-runtime": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz",
+ "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==",
+ "dev": true,
+ "requires": {
+ "babel-core": "^6.0.0",
+ "babel-plugin-istanbul": "^4.1.6",
+ "chalk": "^2.0.1",
+ "convert-source-map": "^1.4.0",
+ "exit": "^0.1.2",
+ "fast-json-stable-stringify": "^2.0.0",
+ "graceful-fs": "^4.1.11",
+ "jest-config": "^23.6.0",
+ "jest-haste-map": "^23.6.0",
+ "jest-message-util": "^23.4.0",
+ "jest-regex-util": "^23.3.0",
+ "jest-resolve": "^23.6.0",
+ "jest-snapshot": "^23.6.0",
+ "jest-util": "^23.4.0",
+ "jest-validate": "^23.6.0",
+ "micromatch": "^2.3.11",
+ "realpath-native": "^1.0.0",
+ "slash": "^1.0.0",
+ "strip-bom": "3.0.0",
+ "write-file-atomic": "^2.1.0",
+ "yargs": "^11.0.0"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^1.8.1",
+ "preserve": "^0.2.0",
+ "repeat-element": "^1.1.2"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "^0.1.0"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^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=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": 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"
+ }
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "11.1.0",
+ "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
+ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^9.0.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
+ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+ },
+ "jest-serializer": {
+ "version": "23.0.1",
+ "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz",
+ "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=",
+ "dev": true
+ },
+ "jest-snapshot": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz",
+ "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==",
+ "dev": true,
+ "requires": {
+ "babel-types": "^6.0.0",
+ "chalk": "^2.0.1",
+ "jest-diff": "^23.6.0",
+ "jest-matcher-utils": "^23.6.0",
+ "jest-message-util": "^23.4.0",
+ "jest-resolve": "^23.6.0",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^23.6.0",
+ "semver": "^5.5.0"
+ }
+ },
+ "jest-util": {
+ "version": "23.4.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz",
+ "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=",
+ "dev": true,
+ "requires": {
+ "callsites": "^2.0.0",
+ "chalk": "^2.0.1",
+ "graceful-fs": "^4.1.11",
+ "is-ci": "^1.0.10",
+ "jest-message-util": "^23.4.0",
+ "mkdirp": "^0.5.1",
+ "slash": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "jest-validate": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz",
+ "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1",
+ "jest-get-type": "^22.1.0",
+ "leven": "^2.1.0",
+ "pretty-format": "^23.6.0"
+ }
+ },
+ "jest-watcher": {
+ "version": "23.4.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz",
+ "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.1",
+ "string-length": "^2.0.0"
+ }
+ },
+ "jest-worker": {
+ "version": "23.2.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz",
+ "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=",
+ "dev": true,
+ "requires": {
+ "merge-stream": "^1.0.1"
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "js-yaml": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
+ "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "jsdom": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
+ "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
+ "dev": true,
+ "requires": {
+ "abab": "^2.0.0",
+ "acorn": "^5.5.3",
+ "acorn-globals": "^4.1.0",
+ "array-equal": "^1.0.0",
+ "cssom": ">= 0.3.2 < 0.4.0",
+ "cssstyle": "^1.0.0",
+ "data-urls": "^1.0.0",
+ "domexception": "^1.0.1",
+ "escodegen": "^1.9.1",
+ "html-encoding-sniffer": "^1.0.2",
+ "left-pad": "^1.3.0",
+ "nwsapi": "^2.0.7",
+ "parse5": "4.0.0",
+ "pn": "^1.1.0",
+ "request": "^2.87.0",
+ "request-promise-native": "^1.0.5",
+ "sax": "^1.2.4",
+ "symbol-tree": "^3.2.2",
+ "tough-cookie": "^2.3.4",
+ "w3c-hr-time": "^1.0.1",
+ "webidl-conversions": "^4.0.2",
+ "whatwg-encoding": "^1.0.3",
+ "whatwg-mimetype": "^2.1.0",
+ "whatwg-url": "^6.4.1",
+ "ws": "^5.2.0",
+ "xml-name-validator": "^3.0.0"
+ }
+ },
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
+ "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==",
+ "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=",
+ "dev": true
+ },
+ "json3": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "killable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+ "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "kleur": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz",
+ "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==",
+ "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"
+ }
+ },
+ "left-pad": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
+ "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==",
+ "dev": true
+ },
+ "leven": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
+ "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "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"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "loader-runner": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz",
+ "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.11",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+ "dev": true
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+ "dev": true
+ },
+ "lodash.escape": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
+ "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=",
+ "dev": true
+ },
+ "lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
+ "dev": true
+ },
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
+ "dev": true
+ },
+ "lodash.sortby": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "loglevel": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz",
+ "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
+ "dev": true
+ },
+ "loglevelnext": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz",
+ "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==",
+ "dev": true,
+ "requires": {
+ "es6-symbol": "^3.1.1",
+ "object.assign": "^4.1.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"
+ }
+ },
+ "lower-case": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
+ "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
+ "dev": true
+ },
+ "makeerror": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
+ "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=",
+ "dev": true,
+ "requires": {
+ "tmpl": "1.0.x"
+ }
+ },
+ "map-age-cleaner": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz",
+ "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==",
+ "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=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "math-random": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
+ "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
+ "dev": true
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "mem": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz",
+ "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^1.0.0",
+ "p-is-promise": "^1.1.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "dev": true,
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "merge": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz",
+ "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==",
+ "dev": true
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
+ "merge-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
+ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": 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"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ }
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.37.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
+ "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.21",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
+ "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
+ "dev": true,
+ "requires": {
+ "mime-db": "~1.37.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
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+ "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"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mississippi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^2.0.1",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
+ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "moo": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz",
+ "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==",
+ "dev": true
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "msal": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/msal/-/msal-0.2.3.tgz",
+ "integrity": "sha512-U/7lDY9xoN8wKjqQtgGFdyI539YpIS1EA65agiGpvGdzT6h9mG61voB+xuuB1fg4UKtRD10RTE2TsLPPEK1MLQ==",
+ "requires": {
+ "tslib": "1.7.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz",
+ "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw="
+ }
+ }
+ },
+ "multicast-dns": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "dev": true,
+ "requires": {
+ "dns-packet": "^1.3.1",
+ "thunky": "^1.0.2"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.11.1",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
+ "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "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"
+ }
+ },
+ "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
+ },
+ "nearley": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz",
+ "integrity": "sha512-8IUY/rUrKz2mIynUGh8k+tul1awMKEjeHHC5G3FHvvyAW6oq4mQfNp2c0BMea+sYZJvYcrrM6GmZVIle/GRXGw==",
+ "dev": true,
+ "requires": {
+ "moo": "^0.4.3",
+ "nomnom": "~1.6.2",
+ "railroad-diagrams": "^1.0.0",
+ "randexp": "0.4.6",
+ "semver": "^5.4.1"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+ "dev": true
+ },
+ "neo-async": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
+ "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
+ "dev": true
+ },
+ "next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
+ "dev": true
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "dev": true,
+ "requires": {
+ "lower-case": "^1.1.1"
+ }
+ },
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ },
+ "node-forge": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
+ "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
+ "dev": true
+ },
+ "node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "dev": true
+ },
+ "node-libs-browser": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
+ "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
+ "dev": true,
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^1.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.0",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.10.3",
+ "vm-browserify": "0.0.4"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "node-notifier": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.3.0.tgz",
+ "integrity": "sha512-AhENzCSGZnZJgBARsUjnQ7DnZbzyP+HxlVXuD0xqAnvL8q+OqtSX7lGg9e8nHzwXkMMXNdVeqq4E2M3EUAqX6Q==",
+ "dev": true,
+ "requires": {
+ "growly": "^1.3.0",
+ "semver": "^5.5.0",
+ "shellwords": "^0.1.1",
+ "which": "^1.3.0"
+ }
+ },
+ "nomnom": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz",
+ "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=",
+ "dev": true,
+ "requires": {
+ "colors": "0.5.x",
+ "underscore": "~1.4.4"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "is-builtin-module": "^1.0.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=",
+ "dev": true,
+ "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"
+ }
+ },
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.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=",
+ "dev": true
+ },
+ "nwsapi": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz",
+ "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
+ "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
+ "dev": true
+ },
+ "object-is": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
+ "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+ "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
+ "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=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "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.entries": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz",
+ "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.6.1",
+ "function-bind": "^1.1.0",
+ "has": "^1.0.1"
+ }
+ },
+ "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=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "object.values": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz",
+ "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.6.1",
+ "function-bind": "^1.1.0",
+ "has": "^1.0.1"
+ }
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
+ "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "opn": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz",
+ "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "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"
+ },
+ "dependencies": {
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ }
+ }
+ },
+ "original": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "dev": true,
+ "requires": {
+ "url-parse": "^1.4.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz",
+ "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.10.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "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": "1.1.0",
+ "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+ "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "dev": true
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "pako": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
+ "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
+ "dev": true
+ },
+ "parallel-transform": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
+ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+ "dev": true,
+ "requires": {
+ "cyclist": "~0.2.2",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "param-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
+ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+ "dev": true,
+ "requires": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.1",
+ "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
+ "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
+ "dev": true,
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3"
+ }
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "dev": true,
+ "requires": {
+ "glob-base": "^0.3.0",
+ "is-dotfile": "^1.0.0",
+ "is-extglob": "^1.0.0",
+ "is-glob": "^2.0.0"
+ },
+ "dependencies": {
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ }
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+ "dev": true
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-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==",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
+ "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+ "dev": true,
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "pn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
+ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
+ "dev": true
+ },
+ "portfinder": {
+ "version": "1.0.19",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.19.tgz",
+ "integrity": "sha512-23aeQKW9KgHe6citUrG3r9HjeX6vls0h713TAa+CwTKZwNIr/pD2ApaxYF4Um3ZZyq4ar+Siv3+fhoHaIwSOSw==",
+ "dev": true,
+ "requires": {
+ "async": "^1.5.2",
+ "debug": "^2.2.0",
+ "mkdirp": "0.5.x"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ }
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-modules-extract-imports": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz",
+ "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==",
+ "dev": true,
+ "requires": {
+ "postcss": "^6.0.1"
+ }
+ },
+ "postcss-modules-local-by-default": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz",
+ "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=",
+ "dev": true,
+ "requires": {
+ "css-selector-tokenizer": "^0.7.0",
+ "postcss": "^6.0.1"
+ }
+ },
+ "postcss-modules-scope": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz",
+ "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=",
+ "dev": true,
+ "requires": {
+ "css-selector-tokenizer": "^0.7.0",
+ "postcss": "^6.0.1"
+ }
+ },
+ "postcss-modules-values": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz",
+ "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=",
+ "dev": true,
+ "requires": {
+ "icss-replace-symbols": "^1.1.0",
+ "postcss": "^6.0.1"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+ "dev": true
+ },
+ "pretty-error": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz",
+ "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=",
+ "dev": true,
+ "requires": {
+ "renderkid": "^2.0.1",
+ "utila": "~0.4"
+ }
+ },
+ "pretty-format": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
+ "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0",
+ "ansi-styles": "^3.2.0"
+ }
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+ "dev": true
+ },
+ "prompts": {
+ "version": "0.1.14",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz",
+ "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==",
+ "dev": true,
+ "requires": {
+ "kleur": "^2.0.1",
+ "sisteransi": "^0.1.1"
+ }
+ },
+ "prop-types": {
+ "version": "15.6.2",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
+ "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
+ "requires": {
+ "loose-envify": "^1.3.1",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "proxy-addr": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+ "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+ "dev": true,
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.8.0"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.1.29",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
+ "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+ "dev": true
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz",
+ "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==",
+ "dev": true
+ },
+ "raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "dev": true,
+ "requires": {
+ "performance-now": "^2.1.0"
+ }
+ },
+ "railroad-diagrams": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+ "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
+ "dev": true
+ },
+ "randexp": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+ "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+ "dev": true,
+ "requires": {
+ "discontinuous-range": "1.0.0",
+ "ret": "~0.1.10"
+ }
+ },
+ "randomatic": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
+ "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
+ "dev": 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==",
+ "dev": true
+ }
+ }
+ },
+ "randombytes": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
+ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+ "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "http-errors": "1.6.3",
+ "iconv-lite": "0.4.23",
+ "unpipe": "1.0.0"
+ }
+ },
+ "react": {
+ "version": "16.6.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.6.0.tgz",
+ "integrity": "sha512-zJPnx/jKtuOEXCbQ9BKaxDMxR0001/hzxXwYxG8septeyYGfsgAei6NgfbVgOhbY1WOP2o3VPs/E9HaN+9hV3Q==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "scheduler": "^0.10.0"
+ }
+ },
+ "react-dom": {
+ "version": "16.6.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.6.0.tgz",
+ "integrity": "sha512-Stm2D9dXEUUAQdvpvhvFj/DEXwC2PAL/RwEMhoN4dvvD2ikTlJegEXf97xryg88VIAU22ZAP7n842l+9BTz6+w==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "scheduler": "^0.10.0"
+ }
+ },
+ "react-is": {
+ "version": "16.6.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.0.tgz",
+ "integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g==",
+ "dev": true
+ },
+ "react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "react-test-renderer": {
+ "version": "16.6.0",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.6.0.tgz",
+ "integrity": "sha512-w+Y3YT7OX1LP5KO7HCd0YR34Ol1qmISHaooPNMRYa6QzmwtcWhEGuZPr34wO8UCBIokswuhyLQUq7rjPDcEtJA==",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "react-is": "^16.6.0",
+ "scheduler": "^0.10.0"
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "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=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "realpath-native": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.2.tgz",
+ "integrity": "sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g==",
+ "dev": true,
+ "requires": {
+ "util.promisify": "^1.0.0"
+ }
+ },
+ "redent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
+ "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
+ "dev": true,
+ "requires": {
+ "indent-string": "^3.0.0",
+ "strip-indent": "^2.0.0"
+ }
+ },
+ "regenerate": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ },
+ "regex-cache": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "dev": 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==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexpu-core": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.2.1",
+ "regjsgen": "^0.2.0",
+ "regjsparser": "^0.1.4"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "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=",
+ "dev": true
+ }
+ }
+ },
+ "relateurl": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
+ "dev": true
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "renderkid": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz",
+ "integrity": "sha512-FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==",
+ "dev": true,
+ "requires": {
+ "css-select": "^1.1.0",
+ "dom-converter": "~0.2",
+ "htmlparser2": "~3.3.0",
+ "strip-ansi": "^3.0.0",
+ "utila": "^0.4.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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"
+ }
+ },
+ "request-promise-core": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
+ "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.13.1"
+ }
+ },
+ "request-promise-native": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz",
+ "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=",
+ "dev": true,
+ "requires": {
+ "request-promise-core": "1.1.1",
+ "stealthy-require": "^1.1.0",
+ "tough-cookie": ">=2.3.3"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
+ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.5"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.5"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "rst-selector-parser": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
+ "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=",
+ "dev": true,
+ "requires": {
+ "lodash.flattendeep": "^4.4.0",
+ "nearley": "^2.7.10"
+ }
+ },
+ "rsvp": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz",
+ "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==",
+ "dev": true
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "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=="
+ },
+ "sane": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz",
+ "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "capture-exit": "^1.2.0",
+ "exec-sh": "^0.2.0",
+ "fb-watchman": "^2.0.0",
+ "fsevents": "^1.2.3",
+ "micromatch": "^3.1.4",
+ "minimist": "^1.1.1",
+ "walker": "~1.0.5",
+ "watch": "~0.18.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ },
+ "scheduler": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.10.0.tgz",
+ "integrity": "sha512-+TSTVTCBAA3h8Anei3haDc1IRwMeDmtI/y/o3iBe3Mjl2vwYF9DtPDt929HyRmV/e7au7CLu8sc4C4W0VOs29w==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "selfsigned": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz",
+ "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.7.5"
+ }
+ },
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+ "dev": true
+ },
+ "send": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
+ "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.0",
+ "statuses": "~1.4.0"
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz",
+ "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==",
+ "dev": true
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ }
+ },
+ "serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.2",
+ "send": "0.16.2"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
+ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^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=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "sisteransi": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz",
+ "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "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=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^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=",
+ "dev": true,
+ "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==",
+ "dev": 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==",
+ "dev": 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==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "sockjs": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
+ "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "^0.10.0",
+ "uuid": "^3.0.1"
+ }
+ },
+ "sockjs-client": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz",
+ "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.5",
+ "eventsource": "^1.0.7",
+ "faye-websocket": "~0.11.1",
+ "inherits": "^2.0.3",
+ "json3": "^3.3.2",
+ "url-parse": "^1.4.3"
+ },
+ "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"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
+ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.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
+ }
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-loader": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz",
+ "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==",
+ "dev": true,
+ "requires": {
+ "async": "^2.5.0",
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz",
+ "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz",
+ "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
+ "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==",
+ "dev": true
+ },
+ "spdy": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
+ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.6.8",
+ "handle-thing": "^1.2.5",
+ "http-deceiver": "^1.2.7",
+ "safe-buffer": "^5.0.1",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^2.0.18"
+ }
+ },
+ "spdy-transport": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz",
+ "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==",
+ "dev": true,
+ "requires": {
+ "debug": "^2.6.8",
+ "detect-node": "^2.0.3",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.1",
+ "readable-stream": "^2.2.9",
+ "safe-buffer": "^5.0.1",
+ "wbuf": "^1.7.2"
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "sshpk": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz",
+ "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "stack-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz",
+ "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=",
+ "dev": true
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "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=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+ "dev": true
+ },
+ "stealthy-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
+ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+ "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "dev": true,
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+ "dev": true
+ },
+ "string-length": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
+ "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=",
+ "dev": true,
+ "requires": {
+ "astral-regex": "^1.0.0",
+ "strip-ansi": "^4.0.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"
+ }
+ },
+ "string.prototype.trim": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
+ "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.5.0",
+ "function-bind": "^1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "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"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+ "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+ "dev": true
+ },
+ "style-loader": {
+ "version": "0.23.1",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz",
+ "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.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"
+ }
+ },
+ "symbol-tree": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
+ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=",
+ "dev": true
+ },
+ "tapable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz",
+ "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==",
+ "dev": true
+ },
+ "test-exclude": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz",
+ "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "micromatch": "^2.3.11",
+ "object-assign": "^4.1.0",
+ "read-pkg-up": "^1.0.1",
+ "require-main-filename": "^1.0.1"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^1.8.1",
+ "preserve": "^0.2.0",
+ "repeat-element": "^1.1.2"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "^0.1.0"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": 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"
+ }
+ }
+ }
+ },
+ "throat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
+ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.1.5",
+ "xtend": "~4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz",
+ "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
+ "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
+ "dev": true,
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "tmpl": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
+ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": 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=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "toposort": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
+ "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
+ "dev": true
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "tr46": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+ "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "ts-jest": {
+ "version": "23.10.4",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.10.4.tgz",
+ "integrity": "sha512-oV/wBwGUS7olSk/9yWMiSIJWbz5xO4zhftnY3gwv6s4SMg6WHF1m8XZNBvQOKQRiTAexZ9754Z13dxBq3Zgssw==",
+ "dev": true,
+ "requires": {
+ "bs-logger": "0.x",
+ "buffer-from": "1.x",
+ "fast-json-stable-stringify": "2.x",
+ "json5": "2.x",
+ "make-error": "1.x",
+ "mkdirp": "0.x",
+ "semver": "^5.5",
+ "yargs-parser": "10.x"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
+ "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "ts-loader": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.2.2.tgz",
+ "integrity": "sha512-vM/TrEKXBqRYq5yLatsXyKFnYSpv53klmGtrILGlNqcMsxPVi8+e4yr1Agbu9oMZepx/4szDVn5QpFo83IQdQg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.3.0",
+ "enhanced-resolve": "^4.0.0",
+ "loader-utils": "^1.0.2",
+ "micromatch": "^3.1.4",
+ "semver": "^5.0.1"
+ }
+ },
+ "tslib": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
+ "dev": true
+ },
+ "tslint": {
+ "version": "5.11.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz",
+ "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.22.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.7.0",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.27.2"
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "type-is": {
+ "version": "1.6.16",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
+ "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.18"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "typescript": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.3.tgz",
+ "integrity": "sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA==",
+ "dev": true
+ },
+ "ua-parser-js": {
+ "version": "0.7.19",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz",
+ "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ=="
+ },
+ "uglify-es": {
+ "version": "3.3.9",
+ "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
+ "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.13.0",
+ "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==",
+ "dev": true
+ }
+ }
+ },
+ "uglifyjs-webpack-plugin": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz",
+ "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==",
+ "dev": true,
+ "requires": {
+ "cacache": "^10.0.4",
+ "find-cache-dir": "^1.0.0",
+ "schema-utils": "^0.4.5",
+ "serialize-javascript": "^1.4.0",
+ "source-map": "^0.6.1",
+ "uglify-es": "^3.3.4",
+ "webpack-sources": "^1.1.0",
+ "worker-farm": "^1.5.2"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "underscore": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
+ "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=",
+ "dev": true
+ },
+ "union-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^0.4.3"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "set-value": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
+ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.1",
+ "to-object-path": "^0.3.0"
+ }
+ }
+ }
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz",
+ "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
+ "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
+ "dev": true
+ },
+ "upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "dev": true,
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+ "dev": true
+ }
+ }
+ },
+ "url-parse": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz",
+ "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "util.promisify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
+ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "object.getownpropertydescriptors": "^2.0.3"
+ }
+ },
+ "utila": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
+ "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
+ "dev": true
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+ "dev": true
+ },
+ "v8-compile-cache": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz",
+ "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "dev": true,
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "w3c-hr-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",
+ "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=",
+ "dev": true,
+ "requires": {
+ "browser-process-hrtime": "^0.1.2"
+ }
+ },
+ "walker": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
+ "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=",
+ "dev": true,
+ "requires": {
+ "makeerror": "1.0.x"
+ }
+ },
+ "warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
+ "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "watch": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz",
+ "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=",
+ "dev": true,
+ "requires": {
+ "exec-sh": "^0.2.0",
+ "minimist": "^1.2.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "watchpack": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
+ "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.0.2",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0"
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "webidl-conversions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+ "dev": true
+ },
+ "webpack": {
+ "version": "4.23.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.23.1.tgz",
+ "integrity": "sha512-iE5Cu4rGEDk7ONRjisTOjVHv3dDtcFfwitSxT7evtYj/rANJpt1OuC/Kozh1pBa99AUBr1L/LsaNB+D9Xz3CEg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-module-context": "1.7.10",
+ "@webassemblyjs/wasm-edit": "1.7.10",
+ "@webassemblyjs/wasm-parser": "1.7.10",
+ "acorn": "^5.6.2",
+ "acorn-dynamic-import": "^3.0.0",
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chrome-trace-event": "^1.0.0",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.0",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.3.0",
+ "loader-utils": "^1.1.0",
+ "memory-fs": "~0.4.1",
+ "micromatch": "^3.1.8",
+ "mkdirp": "~0.5.0",
+ "neo-async": "^2.5.0",
+ "node-libs-browser": "^2.0.0",
+ "schema-utils": "^0.4.4",
+ "tapable": "^1.1.0",
+ "uglifyjs-webpack-plugin": "^1.2.4",
+ "watchpack": "^1.5.0",
+ "webpack-sources": "^1.3.0"
+ }
+ },
+ "webpack-cli": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz",
+ "integrity": "sha512-Cnqo7CeqeSvC6PTdts+dywNi5CRlIPbLx1AoUPK2T6vC1YAugMG3IOoO9DmEscd+Dghw7uRlnzV1KwOe5IrtgQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "enhanced-resolve": "^4.1.0",
+ "global-modules-path": "^2.3.0",
+ "import-local": "^2.0.0",
+ "interpret": "^1.1.0",
+ "loader-utils": "^1.1.0",
+ "supports-color": "^5.5.0",
+ "v8-compile-cache": "^2.0.2",
+ "yargs": "^12.0.2"
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz",
+ "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "~0.4.1",
+ "mime": "^2.3.1",
+ "range-parser": "^1.0.3",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
+ "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
+ "dev": true
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ }
+ }
+ },
+ "webpack-dev-server": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz",
+ "integrity": "sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww==",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "^3.5.0",
+ "chokidar": "^2.0.0",
+ "compression": "^1.5.2",
+ "connect-history-api-fallback": "^1.3.0",
+ "debug": "^3.1.0",
+ "del": "^3.0.0",
+ "express": "^4.16.2",
+ "html-entities": "^1.2.0",
+ "http-proxy-middleware": "~0.18.0",
+ "import-local": "^2.0.0",
+ "internal-ip": "^3.0.1",
+ "ip": "^1.1.5",
+ "killable": "^1.0.0",
+ "loglevel": "^1.4.1",
+ "opn": "^5.1.0",
+ "portfinder": "^1.0.9",
+ "schema-utils": "^1.0.0",
+ "selfsigned": "^1.9.1",
+ "serve-index": "^1.7.2",
+ "sockjs": "0.3.19",
+ "sockjs-client": "1.3.0",
+ "spdy": "^3.4.1",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^5.1.0",
+ "webpack-dev-middleware": "3.4.0",
+ "webpack-log": "^2.0.0",
+ "yargs": "12.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "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
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ }
+ }
+ },
+ "webpack-log": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz",
+ "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.1.0",
+ "log-symbols": "^2.1.0",
+ "loglevelnext": "^1.0.1",
+ "uuid": "^3.1.0"
+ }
+ },
+ "webpack-merge": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz",
+ "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.5"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
+ "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "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==",
+ "dev": true
+ }
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
+ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
+ "dev": true,
+ "requires": {
+ "http-parser-js": ">=0.4.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+ "dev": true
+ },
+ "whatwg-encoding": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
+ "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "0.4.24"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
+ }
+ },
+ "whatwg-fetch": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
+ "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
+ },
+ "whatwg-mimetype": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz",
+ "integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw==",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
+ "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^1.0.1",
+ "webidl-conversions": "^4.0.2"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.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
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "worker-farm": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
+ "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
+ "dev": true,
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
+ "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ws": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
+ "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "xml-name-validator": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
+ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
+ "dev": true
+ },
+ "xregexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz",
+ "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "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
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "12.0.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz",
+ "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^2.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^10.1.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"
+ }
+ },
+ "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"
+ }
+ },
+ "p-limit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
+ "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
+ "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.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
+ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
+ "dev": true
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
+ "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+}
diff --git a/ui/package.json b/ui/package.json
new file mode 100644
index 0000000..7e788e5
--- /dev/null
+++ b/ui/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "projectjacksonclient",
+ "version": "1.0.0",
+ "description": "Web App demo for Project Jackson ",
+ "main": "index.js",
+ "scripts": {
+ "dev": "webpack-dev-server --hot --open --config webpack.dev.js",
+ "test": "jest --config jest.config.js",
+ "build": "webpack --config webpack.prod.js",
+ "lint": "tslint -c tslint.json 'src/**/*.tsx'"
+ },
+ "author": "Ethan Arrowood",
+ "license": "MIT",
+ "dependencies": {
+ "@reach/router": "^1.2.1",
+ "msal": "^0.2.3",
+ "react": "^16.6.0",
+ "react-dom": "^16.6.0",
+ "whatwg-fetch": "^3.0.0"
+ },
+ "devDependencies": {
+ "@types/enzyme": "^3.1.15",
+ "@types/jest": "^23.3.8",
+ "@types/reach__router": "^1.2.1",
+ "@types/react": "^16.4.18",
+ "@types/react-dom": "^16.0.9",
+ "awesome-typescript-loader": "^5.2.1",
+ "css-loader": "^1.0.1",
+ "enzyme": "^3.7.0",
+ "enzyme-adapter-react-16": "^1.6.0",
+ "html-webpack-plugin": "^3.2.0",
+ "identity-obj-proxy": "^3.0.0",
+ "jest": "^23.6.0",
+ "jest-dom": "^2.1.0",
+ "react-test-renderer": "^16.6.0",
+ "source-map-loader": "^0.2.4",
+ "style-loader": "^0.23.1",
+ "ts-jest": "^23.10.4",
+ "ts-loader": "^5.2.2",
+ "tslint": "^5.11.0",
+ "typescript": "^3.1.3",
+ "webpack": "^4.23.1",
+ "webpack-cli": "^3.1.2",
+ "webpack-dev-server": "^3.1.10",
+ "webpack-merge": "^4.1.4"
+ }
+}
diff --git a/ui/src/__tests__/App.tsx b/ui/src/__tests__/App.tsx
new file mode 100644
index 0000000..8fe4e1a
--- /dev/null
+++ b/ui/src/__tests__/App.tsx
@@ -0,0 +1,13 @@
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { App } from '../components/App'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create( )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/ui/src/__tests__/DefaultComponent.tsx b/ui/src/__tests__/DefaultComponent.tsx
new file mode 100644
index 0000000..3978123
--- /dev/null
+++ b/ui/src/__tests__/DefaultComponent.tsx
@@ -0,0 +1,49 @@
+import {
+ createHistory,
+ createMemorySource,
+ LocationProvider,
+} from '@reach/router'
+import { render } from 'enzyme'
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { App } from '../components/App'
+import { DefaultComponent } from '../components/DefaultComponent'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create( )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+
+ describe('It is the default 404 page', () => {
+ test('It finds the page if user tries a nonsense path', () => {
+ const badPath = '/awefwaef'
+ const source = createMemorySource(badPath)
+ const hist = createHistory(source)
+ const r = render(
+
+
+ ,
+ )
+
+ expect(r.find('.default-component')).toHaveLength(1)
+ expect(r.find('.default-component1')).toHaveLength(0)
+ })
+
+ test('It doesn\'t find the page if user tries a valid path', () => {
+ const goodPath = '/titles'
+ const source = createMemorySource(goodPath)
+ const hist = createHistory(source)
+ const r = render(
+
+
+ ,
+ )
+
+ expect(r.find('.default-component')).toHaveLength(0)
+ })
+ })
+ })
diff --git a/ui/src/__tests__/Home.tsx b/ui/src/__tests__/Home.tsx
new file mode 100644
index 0000000..0791b62
--- /dev/null
+++ b/ui/src/__tests__/Home.tsx
@@ -0,0 +1,14 @@
+import { mount } from 'enzyme'
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { Home } from '../components/Home'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create( )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/ui/src/__tests__/Navbar.tsx b/ui/src/__tests__/Navbar.tsx
new file mode 100644
index 0000000..f7c1b4b
--- /dev/null
+++ b/ui/src/__tests__/Navbar.tsx
@@ -0,0 +1,25 @@
+import {mount } from 'enzyme'
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { Navbar } from '../components/Navbar'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create( )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+ it('should activate Home link by default', () => {
+ const navbarWrapper = mount( )
+ // @reach/router sets the 'aria-current' property to 'page' when the Link element is active
+ // The Navbar component adds the 'active' class to the className list too
+ const linkElementWrapper = navbarWrapper.find({
+ 'aria-current': 'page',
+ 'className': 'nav-link active',
+ 'href': '/',
+ })
+ expect(linkElementWrapper.text()).toBe('Home')
+ })
+})
diff --git a/ui/src/__tests__/PageForm.tsx b/ui/src/__tests__/PageForm.tsx
new file mode 100644
index 0000000..2816227
--- /dev/null
+++ b/ui/src/__tests__/PageForm.tsx
@@ -0,0 +1,49 @@
+import { mount } from 'enzyme'
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { PageForm } from '../components/PageForm'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create(
+ null}
+ onSubmitClick={() => null}
+ />,
+ )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+ it('should fire input change handler', () => {
+ const mockFn = jest.fn()
+ const pageFormWrapper = mount(
+ null}
+ />,
+ )
+ const textInput = pageFormWrapper.find('.form-field-input')
+ textInput.simulate('change', {})
+ expect(mockFn.mock.calls.length).toBe(1)
+ })
+ it('should fire submit button handler', () => {
+ const mockFn = jest.fn()
+ const pageFormWrapper = mount(
+ null}
+ onSubmitClick={mockFn}
+ />,
+ )
+ const submitButton = pageFormWrapper.find('.form-field-submit')
+ submitButton.simulate('click', {})
+ expect(mockFn.mock.calls.length).toBe(1)
+ })
+})
diff --git a/ui/src/__tests__/Person.tsx b/ui/src/__tests__/Person.tsx
new file mode 100644
index 0000000..4370cc5
--- /dev/null
+++ b/ui/src/__tests__/Person.tsx
@@ -0,0 +1,13 @@
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { Person } from '../components/Person'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create( )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/ui/src/__tests__/Title.tsx b/ui/src/__tests__/Title.tsx
new file mode 100644
index 0000000..50e964c
--- /dev/null
+++ b/ui/src/__tests__/Title.tsx
@@ -0,0 +1,13 @@
+import * as React from 'react'
+import * as renderer from 'react-test-renderer'
+
+import { Title } from '../components/Title'
+
+describe(' ', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create( )
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+})
diff --git a/ui/src/__tests__/__snapshots__/App.tsx.snap b/ui/src/__tests__/__snapshots__/App.tsx.snap
new file mode 100644
index 0000000..ea7559f
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/App.tsx.snap
@@ -0,0 +1,169 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+
+ Project Jackson
+
+
+
+
+
+
+ Welcome to Project Jackson!
+
+
+
+
+ Project Jackson
+
+ is an open-source project, created by members of Microsoft's CSE team, to demonstrate the handiness and effictiveness of Azure resources.
+
+
+ Azure resources used include
+
+ CosmosDB
+
+ ,
+
+ Traffic Manager
+
+ ,
+
+ App Service for Containers
+
+ , and
+
+ Application Gateway
+
+ .
+
+
+ In order to demonstrate Cosmos DB performance with large amounts of data, the project imports historical movie data from IMDb. See
+
+ here for downloadable IMDB datasets
+
+ . The datasets include 8.9 million people, 5.3 million movies and 30 million relationships between them.
+
+
+ Languages used for this project include Java, Javascript, and Typescript. These languages were selected because they are all well documented and well-suited for our purposes.
+
+
+ Technologies used include:
+
+
+
+
+ Java Spring
+
+ , a platform that provides infrastructure support for Java applications
+
+
+
+ Docker
+
+ , a tool used in order to isolate different microservices, allowing for easy maintenance and testing
+
+
+
+ React
+
+ , a component-based front-end Javascript library, used for building UIs
+
+
+
+ Reach Router
+
+ , a Javascript library that manages the focus of apps on route transitions and focuses on user accessibility
+
+
+
+ Jest
+
+ , a Javascript library used to test front-end rendering
+
+
+
+ Webpack
+
+ , a bundler for Javascript files
+
+
+
+ Custom Azure Resource Manager (ARM) templates
+
+ were utilized, to allow one-click deployment of Azure resources and services
+
+
+
+
+
+`;
diff --git a/ui/src/__tests__/__snapshots__/DefaultComponent.tsx.snap b/ui/src/__tests__/__snapshots__/DefaultComponent.tsx.snap
new file mode 100644
index 0000000..2424c13
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/DefaultComponent.tsx.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+ Oh Deer :(
+
+
+ Error 404
+
+
+
+ The requested resource could not be found but may be available again in the future.
+
+
+
+`;
diff --git a/ui/src/__tests__/__snapshots__/Home.tsx.snap b/ui/src/__tests__/__snapshots__/Home.tsx.snap
new file mode 100644
index 0000000..3a30d91
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/Home.tsx.snap
@@ -0,0 +1,114 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+ Welcome to Project Jackson!
+
+
+
+
+ Project Jackson
+
+ is an open-source project, created by members of Microsoft's CSE team, to demonstrate the handiness and effictiveness of Azure resources.
+
+
+ Azure resources used include
+
+ CosmosDB
+
+ ,
+
+ Traffic Manager
+
+ ,
+
+ App Service for Containers
+
+ , and
+
+ Application Gateway
+
+ .
+
+
+ In order to demonstrate Cosmos DB performance with large amounts of data, the project imports historical movie data from IMDb. See
+
+ here for downloadable IMDB datasets
+
+ . The datasets include 8.9 million people, 5.3 million movies and 30 million relationships between them.
+
+
+ Languages used for this project include Java, Javascript, and Typescript. These languages were selected because they are all well documented and well-suited for our purposes.
+
+
+ Technologies used include:
+
+
+
+
+ Java Spring
+
+ , a platform that provides infrastructure support for Java applications
+
+
+
+ Docker
+
+ , a tool used in order to isolate different microservices, allowing for easy maintenance and testing
+
+
+
+ React
+
+ , a component-based front-end Javascript library, used for building UIs
+
+
+
+ Reach Router
+
+ , a Javascript library that manages the focus of apps on route transitions and focuses on user accessibility
+
+
+
+ Jest
+
+ , a Javascript library used to test front-end rendering
+
+
+
+ Webpack
+
+ , a bundler for Javascript files
+
+
+
+ Custom Azure Resource Manager (ARM) templates
+
+ were utilized, to allow one-click deployment of Azure resources and services
+
+
+
+`;
diff --git a/ui/src/__tests__/__snapshots__/Navbar.tsx.snap b/ui/src/__tests__/__snapshots__/Navbar.tsx.snap
new file mode 100644
index 0000000..d4751c7
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/Navbar.tsx.snap
@@ -0,0 +1,45 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+ Project Jackson
+
+
+
+`;
diff --git a/ui/src/__tests__/__snapshots__/PageForm.tsx.snap b/ui/src/__tests__/__snapshots__/PageForm.tsx.snap
new file mode 100644
index 0000000..3b13883
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/PageForm.tsx.snap
@@ -0,0 +1,33 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+`;
diff --git a/ui/src/__tests__/__snapshots__/Person.tsx.snap b/ui/src/__tests__/__snapshots__/Person.tsx.snap
new file mode 100644
index 0000000..1f360ab
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/Person.tsx.snap
@@ -0,0 +1,64 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+
+ Search People
+
+
+ Enter the ID for a person to get their information from the database. Leave the form empty for a random sample of people from the database.
+
+
+
+
+
+ Results for PersonId:
+
+
+ null
+
+
+
+
+`;
diff --git a/ui/src/__tests__/__snapshots__/Title.tsx.snap b/ui/src/__tests__/__snapshots__/Title.tsx.snap
new file mode 100644
index 0000000..3516f4d
--- /dev/null
+++ b/ui/src/__tests__/__snapshots__/Title.tsx.snap
@@ -0,0 +1,64 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+
+ Search Titles
+
+
+ Enter the ID for a title to get their information from the database. Leave the form empty for a random sample of people from the database.
+
+
+
+
+
+ Results for TitleId:
+
+
+ null
+
+
+
+
+`;
diff --git a/ui/src/__tests__/setup.ts b/ui/src/__tests__/setup.ts
new file mode 100644
index 0000000..6ff272a
--- /dev/null
+++ b/ui/src/__tests__/setup.ts
@@ -0,0 +1,4 @@
+import * as Enzyme from 'enzyme'
+import * as Adapter from 'enzyme-adapter-react-16'
+
+Enzyme.configure({ adapter: new Adapter() })
diff --git a/ui/src/components/App.tsx b/ui/src/components/App.tsx
new file mode 100644
index 0000000..99d87be
--- /dev/null
+++ b/ui/src/components/App.tsx
@@ -0,0 +1,85 @@
+import { Router } from '@reach/router'
+import * as Msal from 'msal'
+import * as React from 'react'
+
+import { AuthProvider } from './AuthContext'
+import { AuthResponseBar } from './AuthResponseBar'
+import { DefaultComponent } from './DefaultComponent'
+import { Home } from './Home'
+import { Navbar } from './Navbar'
+import { Person } from './Person'
+import { PrivateRoute } from './PrivateRoute'
+import { Title } from './Title'
+
+import './../styles/App.css'
+
+const appConfig = {
+ clientID: WEBPACK_PROP_AAD_CLIENT_ID,
+}
+
+// initialize the UserAgentApplication globally so popup and iframe can run in the background
+const userAgentApp = new Msal.UserAgentApplication(appConfig.clientID, null, null)
+
+export class App extends React.Component {
+
+ // App is still responsible for managing the auth state
+ // it uses the AuthContext to share this with other aspects of the UI
+ // including the navbar, private route component, and the pages themselves
+ public state = {
+ accessToken: null,
+ authResponse: null,
+ }
+
+ public handleAuth = async () => {
+ let accessToken = null
+ try {
+ if (this.state.accessToken) {
+ // log out
+ await userAgentApp.logout()
+ } else {
+ // log in
+ if (!appConfig.clientID) {
+ throw new Error(
+ 'AAD Client ID has not been configured. See the \'deploy\' documentation for more details.')
+ }
+ const graphScopes = [appConfig.clientID]
+ await userAgentApp.loginPopup(graphScopes)
+ accessToken = await userAgentApp.acquireTokenSilent(graphScopes,
+ 'https://login.microsoftonline.com/microsoft.onmicrosoft.com')
+ }
+ this.setState({ accessToken })
+ } catch (err) {
+ this.setAuthResponse(err.toString())
+ }
+ }
+
+ public setAuthResponse = (msg: string) => {
+ this.setState({ authResponse: msg })
+ }
+
+ public render() {
+ // Implementing the authprovider at app root to share the auth state
+ // with all internal components (if they subscribe to it)
+ // by linking the accessToken to the app state we can be certain the
+ // context will always update and propogate the value to subscribed nodes
+ return (
+
+
+
+ )
+ }
+}
diff --git a/ui/src/components/AuthButton.tsx b/ui/src/components/AuthButton.tsx
new file mode 100644
index 0000000..5a2ed57
--- /dev/null
+++ b/ui/src/components/AuthButton.tsx
@@ -0,0 +1,17 @@
+import * as React from 'react'
+
+import { AuthContext } from './AuthContext'
+
+export class AuthButton extends React.Component {
+ public static contextType = AuthContext
+ public render() {
+ return (
+
+ {this.context.accessToken ? 'Log Out' : 'Log In'}
+
+ )
+ }
+}
diff --git a/ui/src/components/AuthContext.tsx b/ui/src/components/AuthContext.tsx
new file mode 100644
index 0000000..13afe7b
--- /dev/null
+++ b/ui/src/components/AuthContext.tsx
@@ -0,0 +1,21 @@
+import { createContext } from 'react'
+
+export interface IAuthContextValues {
+ accessToken: string,
+ authResponse: string,
+ handleAuth: () => void,
+ setAuthResponse: (msg?: string) => void,
+}
+
+// Default values and enforce use of interface
+const defaultAuthContextValue: IAuthContextValues = {
+ accessToken: null,
+ authResponse: null,
+ handleAuth: () => null,
+ setAuthResponse: () => null,
+}
+
+export const AuthContext = createContext(defaultAuthContextValue)
+// exporting the Provider and Consumer components for more specific imports
+export const AuthProvider = AuthContext.Provider
+export const AuthConsumer = AuthContext.Consumer
diff --git a/ui/src/components/AuthResponseBar.tsx b/ui/src/components/AuthResponseBar.tsx
new file mode 100644
index 0000000..489af11
--- /dev/null
+++ b/ui/src/components/AuthResponseBar.tsx
@@ -0,0 +1,15 @@
+import * as React from 'react'
+
+import { AuthContext } from './AuthContext'
+
+export class AuthResponseBar extends React.Component {
+ public static contextType = AuthContext
+ public render() {
+ return this.context.authResponse && (
+
+ this.context.setAuthResponse(null)}>X
+ {this.context.authResponse}
+
+ )
+ }
+}
diff --git a/ui/src/components/DefaultComponent.tsx b/ui/src/components/DefaultComponent.tsx
new file mode 100644
index 0000000..08328a7
--- /dev/null
+++ b/ui/src/components/DefaultComponent.tsx
@@ -0,0 +1,37 @@
+import * as React from 'react'
+
+export interface IDefaultComponentProps {
+ default: boolean,
+}
+
+export interface IDefaultComponentState {
+ deerSrc: string,
+}
+
+export class DefaultComponent extends React.Component {
+ public state = {
+ deerSrc: null,
+ }
+
+ public componentWillMount() {
+ this.setState({ deerSrc: 'https://i.gifer.com/KG8.gif' })
+ }
+
+ public render() {
+ return (
+
+
+ Oh Deer :(
+
+
+ Error 404
+
+
+
+ The requested resource could not be found but may be available again in the future.
+
+
+
+ )
+ }
+}
diff --git a/ui/src/components/Home.tsx b/ui/src/components/Home.tsx
new file mode 100644
index 0000000..9edfb07
--- /dev/null
+++ b/ui/src/components/Home.tsx
@@ -0,0 +1,73 @@
+import * as React from 'react'
+
+export interface IHomeProps { path?: string, }
+
+export interface IHomeState { image: string }
+
+export class Home extends React.Component {
+ public state = {
+ image: null,
+ }
+
+ public componentDidMount() {
+ this.setState({ image: 'https://media.giphy.com/media/3o6Ztrs0GnTt4GkFO0/giphy.gif' })
+ }
+
+ public componentWillUnmount() {
+ this.setState({ image: null })
+ }
+
+ public render() {
+ return(
+
+
Welcome to Project Jackson!
+
+
+
+ Project Jackson is an open-source project, created by members of Microsoft's CSE team,
+ to demonstrate the handiness and effictiveness of Azure resources.
+
+
+
+ Azure resources used include CosmosDB
+ , Traffic Manager ,
+ App Service for Containers
+ ,
+ and Application Gateway .
+
+
+
+ In order to demonstrate Cosmos DB performance with large amounts of data,
+ the project imports historical movie data from IMDb.
+ See here for downloadable IMDB datasets .
+ The datasets include 8.9 million people, 5.3 million movies and 30 million relationships between them.
+
+
+
+ Languages used for this project include Java, Javascript, and Typescript.
+ These languages were selected because they are all well documented and well-suited for our purposes.
+
+
+ Technologies used include:
+
+
+ Java Spring , a platform that provides infrastructure support for Java applications
+ Docker , a tool used in order to isolate different microservices,
+ allowing for easy maintenance and testing
+ React , a component-based front-end Javascript library,
+ used for building UIs
+ Reach Router , a Javascript library that manages the focus of apps on
+ route transitions and focuses on user accessibility
+ Jest , a Javascript library used to test front-end rendering
+ Webpack , a bundler for Javascript files
+ Custom Azure Resource Manager (ARM) templates were utilized,
+ to allow one-click deployment of Azure resources and services
+
+
+ )
+ }
+}
diff --git a/ui/src/components/Navbar.tsx b/ui/src/components/Navbar.tsx
new file mode 100644
index 0000000..c07f33a
--- /dev/null
+++ b/ui/src/components/Navbar.tsx
@@ -0,0 +1,30 @@
+import { Link } from '@reach/router'
+import * as React from 'react'
+
+import { AuthButton } from './AuthButton'
+
+import './../styles/Navbar.css'
+
+const isActive = ({ isCurrent }) => {
+ return {
+ className: isCurrent ? 'nav-link active' : 'nav-link',
+ }
+}
+
+export class Navbar extends React.Component {
+ public render() {
+ return (
+
+
+ Project Jackson
+
+
+
Home
+
People
+
Titles
+
+
+
+ )
+ }
+}
diff --git a/ui/src/components/PageForm.tsx b/ui/src/components/PageForm.tsx
new file mode 100644
index 0000000..294e3cd
--- /dev/null
+++ b/ui/src/components/PageForm.tsx
@@ -0,0 +1,32 @@
+import * as React from 'react'
+
+export interface IPageFormProps {
+ inputTitle: string,
+ inputPlaceholder: string,
+ onInputChange: (event) => void,
+ onSubmitClick: (event) => void,
+}
+
+export function PageForm(props: IPageFormProps) {
+ return (
+
+ )
+}
diff --git a/ui/src/components/Person.tsx b/ui/src/components/Person.tsx
new file mode 100644
index 0000000..2791ba1
--- /dev/null
+++ b/ui/src/components/Person.tsx
@@ -0,0 +1,94 @@
+import * as React from 'react'
+
+import { AuthContext } from './AuthContext'
+import { PageForm } from './PageForm'
+
+export interface IPersonProps { path: string }
+
+export interface IPersonState { loading: boolean, personId: string, result: object }
+
+export interface IPersonResponse extends Response {
+ _embedded?: { persons: Array<{ nconst: string }> },
+ error?: string,
+ error_description?: string
+}
+
+export interface IPersonResult { nconst: string }
+
+export class Person extends React.Component {
+ public static contextType = AuthContext
+
+ public state = {
+ loading: false,
+ personId: null,
+ result: null,
+ }
+
+ public render() {
+ return (
+
+
+
Search People
+
Enter the ID for a person to get their information from the database.
+ Leave the form empty for a random sample of people from the database.
+
+
+
+
{`Results for PersonId: ${this.state.result ? this.state.personId : ''}`}
+
{JSON.stringify(this.state.result, null, 2)}
+
{this.state.loading ? 'Loading. . .' : null}
+
+
+ )
+ }
+
+ private handleNameInputChange = (event) => this.setState({
+ personId: event.target.value,
+ result: null,
+ })
+
+ private handleFormSubmit = async (event) => {
+ event.preventDefault()
+
+ this.setState({ loading: true })
+
+ // set up endpoint
+ const id = this.state.personId && this.state.personId.replace(/\s+/g, '')
+ // const base = 'https://jackson-person.azurewebsites.net/people/'
+ const base = 'http://localhost:8080/people/'
+ const endpoint = id ? base + id : base
+
+ // set up request header with Bearer token
+ const headers = new Headers()
+ const bearer = `Bearer ${this.context.accessToken}`
+ headers.append('Authorization', bearer)
+ const options = {
+ headers,
+ method: 'GET',
+ }
+
+ try {
+ const response = await fetch(endpoint, options)
+ const resOut: IPersonResponse = await response.json()
+
+ if (resOut.hasOwnProperty('error')) {
+ throw new Error(`Error: ${resOut.error}, ${resOut.error_description}`)
+ } else if (id) {
+ this.setState({ result: resOut })
+ } else {
+ const persons = resOut._embedded.persons
+ const result: IPersonResult = persons[Math.floor(Math.random() * persons.length)]
+ this.setState({ result, personId: result.nconst })
+ }
+ } catch (err) {
+ this.setState({ result: { error: err.message } })
+ } finally {
+ this.setState({ loading: false })
+ }
+ }
+}
diff --git a/ui/src/components/PrivateRoute.tsx b/ui/src/components/PrivateRoute.tsx
new file mode 100644
index 0000000..d629dfb
--- /dev/null
+++ b/ui/src/components/PrivateRoute.tsx
@@ -0,0 +1,35 @@
+import * as React from 'react'
+
+import { AuthContext } from './AuthContext'
+import { Home } from './Home'
+
+export interface IPrivateRouteProps { as: React.ComponentType, path: string }
+
+export class PrivateRoute extends React.Component {
+ public static contextType = AuthContext
+
+ public componentDidMount() {
+ if (!this.context.accessToken) {
+ this.context.setAuthResponse(`Please log in to access: ${this.props.path}`)
+ }
+ }
+
+ public componentDidUpdate(prevProps, prevState, snapshot) {
+ if (!this.context.accessToken && this.props.path !== prevProps.path) {
+ this.context.setAuthResponse(`Please log in to access: ${this.props.path}`)
+ }
+ }
+
+ public componentWillUnmount() {
+ this.context.setAuthResponse(null)
+ }
+
+ public render() {
+ const { as: Component, ...props } = this.props
+ // this private route uses the existence of the accessToken to
+ // lock/unlock the private routes. We don't pass down the values from
+ // context as we would rather subscribe to them directly in the
+ // components themselves.
+ return this.context.accessToken ? :
+ }
+}
diff --git a/ui/src/components/Title.tsx b/ui/src/components/Title.tsx
new file mode 100644
index 0000000..4238d3f
--- /dev/null
+++ b/ui/src/components/Title.tsx
@@ -0,0 +1,94 @@
+import * as React from 'react'
+
+import { AuthContext } from './AuthContext'
+import { PageForm } from './PageForm'
+
+export interface ITitleProps { path: string }
+
+export interface ITitleState { loading: boolean, titleId: string, result: object }
+
+export interface ITitleResponse extends Response {
+ _embedded?: { titles: Array<{ tconst: string }> },
+ error?: string,
+ error_description?: string
+}
+
+export interface ITitleResult { tconst: string }
+
+export class Title extends React.Component {
+ public static contextType = AuthContext
+
+ public state = {
+ loading: false,
+ result: null,
+ titleId: null,
+ }
+
+ public render() {
+ return (
+
+
+
Search Titles
+
Enter the ID for a title to get their information from the database.
+ Leave the form empty for a random sample of people from the database.
+
+
+
+
{`Results for TitleId: ${this.state.result ? this.state.titleId : ''}`}
+
{JSON.stringify(this.state.result, null, 2)}
+
{this.state.loading ? 'Loading. . .' : null}
+
+
+ )
+ }
+
+ private handleNameInputChange = (event) => this.setState({
+ result: null,
+ titleId: event.target.value,
+ })
+
+ private handleFormSubmit = async (event) => {
+ event.preventDefault()
+
+ this.setState({ loading: true })
+
+ // set up endpoint
+ const id = this.state.titleId && this.state.titleId.replace(/\s+/g, '')
+ const base = 'https://jackson-title.azurewebsites.net/titles/'
+ // const base = 'http://localhost:8080/titles/'
+ const endpoint = id ? base + id : base
+
+ // set up request header with Bearer token
+ const headers = new Headers()
+ const bearer = `Bearer ${this.context.accessToken}`
+ headers.append('Authorization', bearer)
+ const options = {
+ headers,
+ method: 'GET',
+ }
+
+ try {
+ const response = await fetch(endpoint, options)
+ const resOut: ITitleResponse = await response.json()
+
+ if (resOut.hasOwnProperty('error')) {
+ throw new Error(`Error: ${resOut.error}, ${resOut.error_description}`)
+ } else if (id) {
+ this.setState({ result: resOut })
+ } else {
+ const titles = resOut._embedded.titles
+ const result: ITitleResult = titles[Math.floor(Math.random() * titles.length)]
+ this.setState({ result, titleId: result.tconst })
+ }
+ } catch (err) {
+ this.setState({ result: { error: err.message } })
+ } finally {
+ this.setState({ loading: false })
+ }
+ }
+}
diff --git a/ui/src/index.tsx b/ui/src/index.tsx
new file mode 100644
index 0000000..ffa9718
--- /dev/null
+++ b/ui/src/index.tsx
@@ -0,0 +1,9 @@
+import * as React from 'react'
+import * as ReactDOM from 'react-dom'
+
+import { App } from './components/App'
+
+ReactDOM.render(
+ ,
+ document.getElementById('root'),
+)
diff --git a/ui/src/public/index.html b/ui/src/public/index.html
new file mode 100644
index 0000000..d8b906c
--- /dev/null
+++ b/ui/src/public/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Project Jackson
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/public/mountains.svg b/ui/src/public/mountains.svg
new file mode 100644
index 0000000..3e03ac3
--- /dev/null
+++ b/ui/src/public/mountains.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/styles/App.css b/ui/src/styles/App.css
new file mode 100644
index 0000000..c93f1e4
--- /dev/null
+++ b/ui/src/styles/App.css
@@ -0,0 +1,122 @@
+@import url('https://fonts.googleapis.com/css?family=Open+Sans');
+
+body {
+ font-family: 'Open Sans', Helvetica, sans-serif;
+ padding: 0;
+ margin: 0;
+}
+
+.app-container {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ margin-bottom: 20px;
+}
+
+.page-container {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: row;
+ padding: 0 10px;
+ justify-content: space-around;
+}
+
+.page-container--home {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.form-container {
+ width: 300px;
+}
+
+.form-description {
+ text-align: justify;
+}
+
+.form {
+ display: flex;
+ flex-direction: column;
+}
+
+.form-field-input {
+ display: block;
+ width: 300px;
+ border-radius: 5px;
+ font-size: 1rem;
+ -webkit-box-shadow: inset 2px 2px 2px 0px #dddddd;
+ -moz-box-shadow: inset 2px 2px 2px 0px #dddddd;
+ box-shadow: inset 2px 2px 2px 0px #dddddd;
+ border: 1px solid #ccc;
+ padding: 7px 10px;
+ box-sizing: border-box;
+}
+
+.form-field-submit {
+ width: 300px;
+ margin-top: 20px;
+ background-color: rgb(50, 146, 202);
+ border: 1px solid rgb(50, 146, 202);
+ border-radius: 5px;
+ color: #FFF;
+ font-size: 1.2rem;
+ padding: 10px 0;
+}
+
+.results-container {
+ padding: 20px;
+ width: max-content;
+ max-width: 50%;
+}
+
+.results-view {
+ overflow-x: scroll;
+ border: 1px solid #ccc;
+ background: rgba(0, 0, 0, 0.1);
+ box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.2);
+ padding: 20px;
+}
+
+.home-title {
+ text-align: center;
+}
+
+.home-img {
+ width: 250px;
+ margin: auto;
+}
+
+.center {
+ margin: auto;
+ width: 50%;
+}
+
+.auth-message-container {
+ background-color: #ccc;
+ padding: 5px 15px;
+}
+.auth-message {
+ color: rgb(221, 26, 26)
+}
+
+.auth-message-close-button {
+ color: rgb(221, 26, 26);
+ font-weight: 700;
+ padding: 5px;
+ margin-right: 20px;
+ border: none;
+ cursor: pointer;
+}
+
+.login-button {
+ border: none;
+ cursor: pointer;
+ background-color: rgb(50, 146, 202);
+}
+
+.default-page-image {
+ padding-left: 33%;
+ width: 400px;
+}
diff --git a/ui/src/styles/Navbar.css b/ui/src/styles/Navbar.css
new file mode 100644
index 0000000..e80fda2
--- /dev/null
+++ b/ui/src/styles/Navbar.css
@@ -0,0 +1,32 @@
+.nav-container {
+ height: 65px;
+ background-color: rgb(43, 43, 43);
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+.nav-title {
+ font-size: 1.6rem;
+ color: rgb(50, 146, 202);
+}
+
+.nav-link-container {
+ display: flex;
+ flex-direction: row;
+ justify-content: right;
+}
+
+.nav-link {
+ margin: 0 10px;
+ font-size: 1.3rem;
+ color: rgb(50, 146, 202);
+ text-decoration: none;
+}
+
+.active {
+ color: rgb(61, 173, 85);
+}
\ No newline at end of file
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
new file mode 100644
index 0000000..95651e9
--- /dev/null
+++ b/ui/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "outDir": "./dist/",
+ "module": "commonjs",
+ "target": "es5",
+ "jsx": "react",
+ "lib": [ "es2015", "dom" ],
+ "allowSyntheticDefaultImports": true,
+ "typeRoots": [
+ "./node_modules/@types",
+ "./types"
+ ]
+ },
+ "exclude": [
+ "./node_modules/**/*"
+ ],
+ "include": [
+ "./src/**/*"
+ ]
+}
\ No newline at end of file
diff --git a/ui/tslint.json b/ui/tslint.json
new file mode 100644
index 0000000..be91fcb
--- /dev/null
+++ b/ui/tslint.json
@@ -0,0 +1,19 @@
+{
+ "defaultSeverity": "error",
+ "extends": [
+ "tslint:recommended"
+ ],
+ "jsRules": {},
+ "rules": {
+ "quotemark": [true, "single"],
+ "semicolon": [true, "never"],
+ "indent": [true, "spaces", 4],
+ "ordered-imports": [
+ true,
+ {
+ "grouped-imports": true
+ }
+ ]
+ },
+ "rulesDirectory": []
+}
\ No newline at end of file
diff --git a/ui/types/global/index.d.ts b/ui/types/global/index.d.ts
new file mode 100644
index 0000000..8445d52
--- /dev/null
+++ b/ui/types/global/index.d.ts
@@ -0,0 +1,6 @@
+/**
+ * This global variable will be injected by Webpack during build time.
+ * As defined by the documentation, this variable is defined by your AAD app
+ * and is available in the Azure Portal.
+ */
+declare const WEBPACK_PROP_AAD_CLIENT_ID: string
diff --git a/ui/webpack.common.js b/ui/webpack.common.js
new file mode 100644
index 0000000..2b1ccac
--- /dev/null
+++ b/ui/webpack.common.js
@@ -0,0 +1,32 @@
+const path = require('path')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const webpack = require('webpack')
+
+module.exports = {
+ entry: "./src/index.tsx",
+ output: {
+ path: path.resolve(__dirname + "/dist"),
+ filename: "bundle.js",
+ },
+ devtool: "source-map",
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".json"]
+ },
+ module: {
+ rules: [
+ { test: /\.tsx?$/, loader: "awesome-typescript-loader" },
+ { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
+ { test: /\.css$/, loader: ["style-loader", "css-loader"] }
+ ]
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ template: './src/public/index.html',
+ favicon: './src/public/mountains.svg'
+ }),
+ // DefinePlugin will inject this env variable anywhere in the code base it ref the attr name
+ new webpack.DefinePlugin({
+ WEBPACK_PROP_AAD_CLIENT_ID: `"${process.env.WEBPACK_PROP_AAD_CLIENT_ID}"`
+ })
+ ],
+}
\ No newline at end of file
diff --git a/ui/webpack.dev.js b/ui/webpack.dev.js
new file mode 100644
index 0000000..d32844b
--- /dev/null
+++ b/ui/webpack.dev.js
@@ -0,0 +1,15 @@
+const merge = require('webpack-merge')
+const common = require('./webpack.common.js')
+
+module.exports = merge(common, {
+ mode: 'development',
+ devtool: 'inline-source-map',
+ devServer: {
+ port: 3000,
+ open: true,
+ historyApiFallback: true,
+ proxy: {
+ '/api': 'http://localhost:8080',
+ },
+ },
+})
\ No newline at end of file
diff --git a/ui/webpack.prod.js b/ui/webpack.prod.js
new file mode 100644
index 0000000..cb68551
--- /dev/null
+++ b/ui/webpack.prod.js
@@ -0,0 +1,6 @@
+const merge = require('webpack-merge')
+const common = require('./webpack.common.js')
+
+module.exports = merge(common, {
+ mode: 'production',
+})
\ No newline at end of file