diff --git a/.travis.yml b/.travis.yml
index 23db92d987..49ececf3f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,9 @@ mono: none
os:
- linux
- osx
+env:
+ global:
+ - TRAVIS_NODE_VERSION: 8.9.3
osx_image: xcode8.2
addons:
apt:
@@ -16,6 +19,7 @@ branches:
- /^release\/.*$/
- /^(.*\/)?ci-.*$/
before_install:
+- nvm install $TRAVIS_NODE_VERSION
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s
/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
/usr/local/lib/; fi
diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml
index c2c5336fd0..86145193a5 100644
--- a/.vsts-pipelines/builds/ci-internal.yml
+++ b/.vsts-pipelines/builds/ci-internal.yml
@@ -10,4 +10,29 @@ resources:
ref: refs/heads/master
phases:
-- template: .vsts-pipelines/templates/project-ci.yml@buildtools
+- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
+ parameters:
+ agentOs: Windows
+ beforeBuild:
+ - task: NodeTool@0
+ displayName: Use Node 8.x
+ inputs:
+ versionSpec: 8.x
+
+- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
+ parameters:
+ agentOs: macOS
+ beforeBuild:
+ - task: NodeTool@0
+ displayName: Use Node 8.x
+ inputs:
+ versionSpec: 8.x
+
+- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
+ parameters:
+ agentOs: Linux
+ beforeBuild:
+ - task: NodeTool@0
+ displayName: Use Node 8.x
+ inputs:
+ versionSpec: 8.x
diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml
index 507c89b025..bc06c7a25a 100644
--- a/.vsts-pipelines/builds/ci-public.yml
+++ b/.vsts-pipelines/builds/ci-public.yml
@@ -12,4 +12,29 @@ resources:
ref: refs/heads/master
phases:
-- template: .vsts-pipelines/templates/project-ci.yml@buildtools
+- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
+ parameters:
+ agentOs: Windows
+ beforeBuild:
+ - task: NodeTool@0
+ displayName: Use Node 8.x
+ inputs:
+ versionSpec: 8.x
+
+- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
+ parameters:
+ agentOs: macOS
+ beforeBuild:
+ - task: NodeTool@0
+ displayName: Use Node 8.x
+ inputs:
+ versionSpec: 8.x
+
+- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
+ parameters:
+ agentOs: Linux
+ beforeBuild:
+ - task: NodeTool@0
+ displayName: Use Node 8.x
+ inputs:
+ versionSpec: 8.x
diff --git a/CORS.sln b/CORS.sln
index afdbf1fdc0..6ad6179b3f 100644
--- a/CORS.sln
+++ b/CORS.sln
@@ -45,6 +45,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
version.xml = version.xml
EndProjectSection
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "test\FunctionalTests\FunctionalTests.csproj", "{99EB6889-C7D8-4BC3-AF99-B966B9E64C81}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -71,6 +73,10 @@ Global
{99460370-AE5D-4DC9-8DBF-04DF66D6B21D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99460370-AE5D-4DC9-8DBF-04DF66D6B21D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99460370-AE5D-4DC9-8DBF-04DF66D6B21D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -82,6 +88,7 @@ Global
{B42D4844-FFF8-4EC2-88D1-3AE95234D9EB} = {538380BF-0D4C-4E30-8F41-E75C4B1C01FA}
{F6675DC1-AA21-453B-89B6-DA425FB9C3A5} = {960E0703-A8A5-44DF-AA87-B7C614683B3C}
{99460370-AE5D-4DC9-8DBF-04DF66D6B21D} = {960E0703-A8A5-44DF-AA87-B7C614683B3C}
+ {99EB6889-C7D8-4BC3-AF99-B966B9E64C81} = {F32074C7-087C-46CC-A913-422BFD2D6E0A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F9ED9C53-44CD-4853-9621-D028B7B6A431}
diff --git a/build/buildpipeline/linux.groovy b/build/buildpipeline/linux.groovy
index 903f218bb8..791d923d0c 100644
--- a/build/buildpipeline/linux.groovy
+++ b/build/buildpipeline/linux.groovy
@@ -1,10 +1 @@
@Library('dotnet-ci') _
-
-simpleNode('Ubuntu16.04', 'latest-or-auto-docker') {
- stage ('Checking out source') {
- checkout scm
- }
- stage ('Build') {
- sh './build.sh --ci'
- }
-}
diff --git a/build/buildpipeline/osx.groovy b/build/buildpipeline/osx.groovy
index aaac63686b..791d923d0c 100644
--- a/build/buildpipeline/osx.groovy
+++ b/build/buildpipeline/osx.groovy
@@ -1,10 +1 @@
@Library('dotnet-ci') _
-
-simpleNode('OSX10.12','latest') {
- stage ('Checking out source') {
- checkout scm
- }
- stage ('Build') {
- sh './build.sh --ci'
- }
-}
diff --git a/build/buildpipeline/windows.groovy b/build/buildpipeline/windows.groovy
index 8d26f313d4..26f49c395d 100644
--- a/build/buildpipeline/windows.groovy
+++ b/build/buildpipeline/windows.groovy
@@ -2,7 +2,7 @@
// 'node' indicates to Jenkins that the enclosed block runs on a node that matches
// the label 'windows-with-vs'
-simpleNode('Windows_NT','latest') {
+simpleNode('Windows.10.Amd64.EnterpriseRS3.ASPNET.Open') {
stage ('Checking out source') {
checkout scm
}
diff --git a/build/dependencies.props b/build/dependencies.props
index f5fc25bbcc..f2ed043cc8 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -3,22 +3,24 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
- 3.0.0-alpha1-20180919.1
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
- 3.0.0-alpha1-10549
+ 3.0.0-alpha1-20181011.11
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 0.7.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
+ 3.0.0-alpha1-10617
2.0.9
2.1.3
2.2.0-preview2-26905-02
15.6.1
- 4.9.0
+ 4.10.0
2.0.3
0.10.0
2.3.1
diff --git a/build/repo.targets b/build/repo.targets
new file mode 100644
index 0000000000..e2057ccf22
--- /dev/null
+++ b/build/repo.targets
@@ -0,0 +1,11 @@
+
+
+ $(RestoreDependsOn);RestoreNpm
+
+
+
+
+
+
+
+
diff --git a/korebuild-lock.txt b/korebuild-lock.txt
index d66a13bdc7..27b605e3c6 100644
--- a/korebuild-lock.txt
+++ b/korebuild-lock.txt
@@ -1,2 +1,2 @@
-version:3.0.0-alpha1-20180919.1
-commithash:3066ae0a230870ea07e3f132605b5e5493f8bbd4
+version:3.0.0-alpha1-20181011.11
+commithash:f57aa8ddda0abdd74ada55853587bedb4f364065
diff --git a/samples/SampleDestination/Program.cs b/samples/SampleDestination/Program.cs
index 0c2bf0968f..8cef67c306 100644
--- a/samples/SampleDestination/Program.cs
+++ b/samples/SampleDestination/Program.cs
@@ -13,7 +13,7 @@ namespace SampleDestination
{
var host = new WebHostBuilder()
.UseKestrel()
- .UseUrls("http://*:5000")
+ .UseUrls("http://+:9000")
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureLogging(factory => factory.AddConsole())
.UseStartup()
diff --git a/samples/SampleDestination/SampleMiddleware.cs b/samples/SampleDestination/SampleMiddleware.cs
new file mode 100644
index 0000000000..ac53eb5908
--- /dev/null
+++ b/samples/SampleDestination/SampleMiddleware.cs
@@ -0,0 +1,33 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+
+namespace SampleDestination
+{
+ public class SampleMiddleware
+ {
+ private readonly RequestDelegate _next;
+
+ public SampleMiddleware(RequestDelegate next)
+ {
+ _next = next;
+ }
+
+ public Task Invoke(HttpContext context)
+ {
+ var content = Encoding.UTF8.GetBytes("Hello world");
+
+ context.Response.Headers["X-AllowedHeader"] = "Test-Value";
+ context.Response.Headers["X-DisallowedHeader"] = "Test-Value";
+
+ context.Response.ContentType = "text/plain; charset=utf-8";
+ context.Response.ContentLength = content.Length;
+ context.Response.Body.Write(content, 0, content.Length);
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/samples/SampleDestination/Startup.cs b/samples/SampleDestination/Startup.cs
index 0664d84572..af93d605c9 100644
--- a/samples/SampleDestination/Startup.cs
+++ b/samples/SampleDestination/Startup.cs
@@ -1,6 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
@@ -11,6 +15,15 @@ namespace SampleDestination
{
public class Startup
{
+ private static readonly string DefaultAllowedOrigin = $"http://{Dns.GetHostName()}:9001";
+ private readonly ILogger _logger;
+
+ public Startup(ILoggerFactory loggerFactory)
+ {
+ _logger = loggerFactory.CreateLogger();
+ _logger.LogInformation($"Setting up CORS middleware to allow clients on {DefaultAllowedOrigin}");
+ }
+
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
@@ -18,21 +31,60 @@ namespace SampleDestination
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
- app.UseCors(policy => policy
- .WithOrigins("http://origin.example.com:5001")
- .WithMethods("PUT")
- .WithHeaders("Cache-Control"));
-
- app.Run(async context =>
+ app.Map("/allow-origin", innerBuilder =>
{
- var responseHeaders = context.Response.Headers;
- context.Response.ContentType = "text/plain";
- foreach (var responseHeader in responseHeaders)
- {
- await context.Response.WriteAsync("\n" + responseHeader.Key + ": " + responseHeader.Value);
- }
+ innerBuilder.UseCors(policy => policy
+ .WithOrigins(DefaultAllowedOrigin)
+ .AllowAnyMethod()
+ .AllowAnyHeader());
- await context.Response.WriteAsync("\nStatus code of your request: " + context.Response.StatusCode.ToString());
+ innerBuilder.UseMiddleware();
+ });
+
+ app.Map("/allow-header-method", innerBuilder =>
+ {
+ innerBuilder.UseCors(policy => policy
+ .WithOrigins(DefaultAllowedOrigin)
+ .WithHeaders("X-Test", "Content-Type")
+ .WithMethods("PUT"));
+
+ innerBuilder.UseMiddleware();
+ });
+
+ app.Map("/allow-credentials", innerBuilder =>
+ {
+ innerBuilder.UseCors(policy => policy
+ .WithOrigins(DefaultAllowedOrigin)
+ .AllowAnyHeader()
+ .WithMethods("GET", "PUT")
+ .AllowCredentials());
+
+ innerBuilder.UseMiddleware();
+ });
+
+ app.Map("/exposed-header", innerBuilder =>
+ {
+ innerBuilder.UseCors(policy => policy
+ .WithOrigins(DefaultAllowedOrigin)
+ .WithExposedHeaders("X-AllowedHeader", "Content-Length"));
+
+ innerBuilder.UseMiddleware();
+ });
+
+ app.Map("/allow-all", innerBuilder =>
+ {
+ innerBuilder.UseCors(policy => policy
+ .AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
+
+ innerBuilder.UseMiddleware();
+ });
+
+ app.Run(async (context) =>
+ {
+ await context.Response.WriteAsync("Hello World!");
});
}
}
diff --git a/samples/SampleOrigin/Program.cs b/samples/SampleOrigin/Program.cs
index 278c09f48a..576e25f0e3 100644
--- a/samples/SampleOrigin/Program.cs
+++ b/samples/SampleOrigin/Program.cs
@@ -13,7 +13,7 @@ namespace SampleOrigin
{
var host = new WebHostBuilder()
.UseKestrel()
- .UseUrls("http://*:5001")
+ .UseUrls("http://+:9001", "http://+:9002")
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureLogging(factory => factory.AddConsole())
.UseStartup()
diff --git a/samples/SampleOrigin/SampleOrigin.csproj b/samples/SampleOrigin/SampleOrigin.csproj
index 054a6eb713..441b40505f 100644
--- a/samples/SampleOrigin/SampleOrigin.csproj
+++ b/samples/SampleOrigin/SampleOrigin.csproj
@@ -6,7 +6,14 @@
+
+
+
+ PreserveNewest
+
+
+
diff --git a/samples/SampleOrigin/Startup.cs b/samples/SampleOrigin/Startup.cs
index a442b98d68..37f49bdee0 100644
--- a/samples/SampleOrigin/Startup.cs
+++ b/samples/SampleOrigin/Startup.cs
@@ -1,11 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
namespace SampleOrigin
{
@@ -17,13 +17,8 @@ namespace SampleOrigin
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
- app.Run(context =>
- {
- var fileInfoProvider = env.WebRootFileProvider;
- var fileInfo = fileInfoProvider.GetFileInfo("/Index.html");
- context.Response.ContentType = "text/html";
- return context.Response.SendFileAsync(fileInfo);
- });
+ app.UseDefaultFiles();
+ app.UseStaticFiles();
}
}
}
diff --git a/samples/SampleOrigin/wwwroot/Index.html b/samples/SampleOrigin/wwwroot/Index.html
deleted file mode 100644
index fad335b83f..0000000000
--- a/samples/SampleOrigin/wwwroot/Index.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
- CORS Sample
-
-
-
-
- CORS Sample
- Method:
- Header Name: Header Value:
-
-
-
- Make a CORS Request
-
- Method DELETE is not allowed:Invalid Method CORS Request
- Method PUT is allowed:Valid Method CORS Request
-
- Header 'Max-Forwards' not supported:
- Header 'Cache-Control' is supported:
-
-
\ No newline at end of file
diff --git a/samples/SampleOrigin/wwwroot/index.htm b/samples/SampleOrigin/wwwroot/index.htm
new file mode 100644
index 0000000000..dbdd96c177
--- /dev/null
+++ b/samples/SampleOrigin/wwwroot/index.htm
@@ -0,0 +1,2 @@
+Welcome to the CORS test suite. Please wait...
+Click here for the browser test suite.
diff --git a/samples/SampleOrigin/wwwroot/test.htm b/samples/SampleOrigin/wwwroot/test.htm
new file mode 100644
index 0000000000..6a2f4cddf1
--- /dev/null
+++ b/samples/SampleOrigin/wwwroot/test.htm
@@ -0,0 +1,135 @@
+
+
+
+
+
+ CORS Sample
+
+
+ CORS Sample
+
+
+
+ Scenario
+ Result
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs
index fb3df360e6..f71c198de7 100644
--- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs
+++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs
@@ -7,21 +7,19 @@ using Microsoft.AspNetCore.Cors.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Cors.Infrastructure
{
///
- /// An ASP.NET middleware for handling CORS.
+ /// A middleware for handling CORS.
///
public class CorsMiddleware
{
+ private readonly Func OnResponseStartingDelegate = OnResponseStarting;
private readonly RequestDelegate _next;
- private readonly ICorsService _corsService;
private readonly ICorsPolicyProvider _corsPolicyProvider;
private readonly CorsPolicy _policy;
private readonly string _corsPolicyName;
- private readonly ILogger _logger;
///
/// Instantiates a new .
@@ -122,10 +120,10 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
}
_next = next;
- _corsService = corsService;
+ CorsService = corsService;
_corsPolicyProvider = policyProvider;
_corsPolicyName = policyName;
- _logger = loggerFactory.CreateLogger();
+ Logger = loggerFactory.CreateLogger();
}
///
@@ -162,60 +160,65 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
}
_next = next;
- _corsService = corsService;
+ CorsService = corsService;
_policy = policy;
- _logger = loggerFactory.CreateLogger();
+ Logger = loggerFactory.CreateLogger();
}
+ private ICorsService CorsService { get; }
+
+ private ILogger Logger { get; }
+
///
- public async Task Invoke(HttpContext context)
+ public Task Invoke(HttpContext context)
{
- if (context.Request.Headers.ContainsKey(CorsConstants.Origin))
+ if (!context.Request.Headers.ContainsKey(CorsConstants.Origin))
{
- var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName);
- if (corsPolicy != null)
- {
- var accessControlRequestMethod =
- context.Request.Headers[CorsConstants.AccessControlRequestMethod];
- if (string.Equals(
- context.Request.Method,
- CorsConstants.PreflightHttpMethod,
- StringComparison.OrdinalIgnoreCase) &&
- !StringValues.IsNullOrEmpty(accessControlRequestMethod))
- {
- ApplyCorsHeaders(context, corsPolicy);
-
- // Since there is a policy which was identified,
- // always respond to preflight requests.
- context.Response.StatusCode = StatusCodes.Status204NoContent;
- return;
- }
- else
- {
- context.Response.OnStarting(state =>
- {
- var (httpContext, policy) = (Tuple)state;
- try
- {
- ApplyCorsHeaders(httpContext, policy);
- }
- catch (Exception exception)
- {
- _logger.FailedToSetCorsHeaders(exception);
- }
- return Task.CompletedTask;
- }, Tuple.Create(context, corsPolicy));
- }
- }
+ return _next(context);
}
- await _next(context);
+ return InvokeCore(context);
}
- private void ApplyCorsHeaders(HttpContext context, CorsPolicy corsPolicy)
+ private async Task InvokeCore(HttpContext context)
{
- var corsResult = _corsService.EvaluatePolicy(context, corsPolicy);
- _corsService.ApplyResult(corsResult, context.Response);
+ var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName);
+ if (corsPolicy == null)
+ {
+ Logger?.NoCorsPolicyFound();
+ await _next(context);
+ return;
+ }
+
+ var corsResult = CorsService.EvaluatePolicy(context, corsPolicy);
+ if (corsResult.IsPreflightRequest)
+ {
+ CorsService.ApplyResult(corsResult, context.Response);
+
+ // Since there is a policy which was identified,
+ // always respond to preflight requests.
+ context.Response.StatusCode = StatusCodes.Status204NoContent;
+ return;
+ }
+ else
+ {
+ context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult));
+ await _next(context);
+ }
+ }
+
+ private static Task OnResponseStarting(object state)
+ {
+ var (middleware, context, result) = (Tuple)state;
+ try
+ {
+ middleware.CorsService.ApplyResult(result, context.Response);
+ }
+ catch (Exception exception)
+ {
+ middleware.Logger?.FailedToSetCorsHeaders(exception);
+ }
+ return Task.CompletedTask;
}
}
}
diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs
index 99d38b9fd1..558a99a31d 100644
--- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs
+++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs
@@ -14,11 +14,22 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
{
private TimeSpan? _preflightMaxAge;
+ ///
+ /// Gets or sets a value that determines if the current request is a CORS-preflight request.
+ ///
+ public bool IsPreflightRequest { get; set; }
+
///
/// Gets or sets the allowed origin.
///
public string AllowedOrigin { get; set; }
+ ///
+ /// Gets or sets a value that determines if the origin is allowed.
+ /// When false , no CORS headers should be sent.
+ ///
+ public bool IsOriginAllowed { get; set; }
+
///
/// Gets or sets a value indicating whether the resource supports user credentials.
///
diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs
index 5be99f4f71..0d52489d81 100644
--- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs
+++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs
@@ -8,6 +8,7 @@ using System.Linq;
using Microsoft.AspNetCore.Cors.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
@@ -25,8 +26,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
/// Creates a new instance of the .
///
/// The option model representing .
+ [Obsolete("This constructor is obsolete and will be removed in a future version.")]
public CorsService(IOptions options)
- : this(options, loggerFactory: null)
+ : this(options, loggerFactory: NullLoggerFactory.Instance)
{
}
@@ -42,8 +44,13 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
throw new ArgumentNullException(nameof(options));
}
+ if (loggerFactory == null)
+ {
+ throw new ArgumentNullException(nameof(loggerFactory));
+ }
+
_options = options.Value;
- _logger = loggerFactory?.CreateLogger();
+ _logger = loggerFactory.CreateLogger();
}
///
@@ -78,12 +85,30 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
throw new ArgumentNullException(nameof(policy));
}
- var corsResult = new CorsResult();
- var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod];
- if (string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase) &&
- !StringValues.IsNullOrEmpty(accessControlRequestMethod))
+ if (policy.AllowAnyOrigin && policy.SupportsCredentials)
+ {
+ _logger.InsecureConfiguration();
+ }
+
+ var origin = context.Request.Headers[CorsConstants.Origin];
+ var requestHeaders = context.Request.Headers;
+
+ var isOptionsRequest = string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase);
+ var isPreflightRequest = isOptionsRequest && requestHeaders.ContainsKey(CorsConstants.AccessControlRequestMethod);
+
+ if (isOptionsRequest && !isPreflightRequest)
+ {
+ _logger.IsNotPreflightRequest();
+ }
+
+ var corsResult = new CorsResult
+ {
+ IsPreflightRequest = isPreflightRequest,
+ IsOriginAllowed = IsOriginAllowed(policy, origin),
+ };
+
+ if (isPreflightRequest)
{
- _logger?.IsPreflightRequest();
EvaluatePreflightRequest(context, policy, corsResult);
}
else
@@ -94,78 +119,37 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
return corsResult;
}
- public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
+ private static void PopulateResult(HttpContext context, CorsPolicy policy, CorsResult result)
{
- var origin = context.Request.Headers[CorsConstants.Origin];
- if (!IsOriginAllowed(policy, origin))
+ if (policy.AllowAnyOrigin)
{
- return;
+ result.AllowedOrigin = CorsConstants.AnyOrigin;
+ result.VaryByOrigin = policy.SupportsCredentials;
+ }
+ else
+ {
+ var origin = context.Request.Headers[CorsConstants.Origin];
+ result.AllowedOrigin = origin;
+ result.VaryByOrigin = policy.Origins.Count > 1;
}
- AddOriginToResult(origin, policy, result);
result.SupportsCredentials = policy.SupportsCredentials;
+ result.PreflightMaxAge = policy.PreflightMaxAge;
+
+
AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders);
- _logger?.PolicySuccess();
+ AddHeaderValues(result.AllowedMethods, policy.Methods);
+ AddHeaderValues(result.AllowedHeaders, policy.Headers);
+ }
+
+ public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
+ {
+ PopulateResult(context, policy, result);
}
public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
{
- var origin = context.Request.Headers[CorsConstants.Origin];
- if (!IsOriginAllowed(policy, origin))
- {
- return;
- }
-
- var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod];
- if (StringValues.IsNullOrEmpty(accessControlRequestMethod))
- {
- return;
- }
-
- var requestHeaders =
- context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders);
-
- if (!policy.AllowAnyMethod)
- {
- var found = false;
- for (var i = 0; i < policy.Methods.Count; i++)
- {
- var method = policy.Methods[i];
- if (string.Equals(method, accessControlRequestMethod, StringComparison.OrdinalIgnoreCase))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- _logger?.PolicyFailure();
- _logger?.AccessControlMethodNotAllowed(accessControlRequestMethod);
- return;
- }
- }
-
- if (!policy.AllowAnyHeader &&
- requestHeaders != null)
- {
- foreach (var requestHeader in requestHeaders)
- {
- if (!policy.Headers.Contains(requestHeader, StringComparer.OrdinalIgnoreCase))
- {
- _logger?.PolicyFailure();
- _logger?.RequestHeaderNotAllowed(requestHeader);
- return;
- }
- }
- }
-
- AddOriginToResult(origin, policy, result);
- result.SupportsCredentials = policy.SupportsCredentials;
- result.PreflightMaxAge = policy.PreflightMaxAge;
- result.AllowedMethods.Add(accessControlRequestMethod);
- AddHeaderValues(result.AllowedHeaders, requestHeaders);
- _logger?.PolicySuccess();
+ PopulateResult(context, policy, result);
}
///
@@ -181,86 +165,67 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
throw new ArgumentNullException(nameof(response));
}
- var headers = response.Headers;
-
- if (result.AllowedOrigin != null)
+ if (!result.IsOriginAllowed)
{
- headers[CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin;
+ // In case a server does not wish to participate in the CORS protocol, its HTTP response to the
+ // CORS or CORS-preflight request must not include any of the above headers.
+ return;
+ }
+
+ response.Headers[CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin;
+
+ if (result.SupportsCredentials)
+ {
+ response.Headers[CorsConstants.AccessControlAllowCredentials] = "true";
+ }
+
+ if (result.IsPreflightRequest)
+ {
+ _logger.IsPreflightRequest();
+
+ // An HTTP response to a CORS-preflight request can include the following headers:
+ // `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`, `Access-Control-Max-Age`
+ if (result.AllowedHeaders.Count > 0)
+ {
+ response.Headers.SetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders, result.AllowedHeaders.ToArray());
+ }
+
+ if (result.AllowedMethods.Count > 0)
+ {
+ response.Headers.SetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods, result.AllowedMethods.ToArray());
+ }
+
+ if (result.PreflightMaxAge.HasValue)
+ {
+ response.Headers[CorsConstants.AccessControlMaxAge] = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture);
+ }
+ }
+ else
+ {
+ // An HTTP response to a CORS request that is not a CORS-preflight request can also include the following header:
+ // `Access-Control-Expose-Headers`
+ if (result.AllowedExposedHeaders.Count > 0)
+ {
+ response.Headers.SetCommaSeparatedValues(CorsConstants.AccessControlExposeHeaders, result.AllowedExposedHeaders.ToArray());
+ }
}
if (result.VaryByOrigin)
{
- headers["Vary"] = "Origin";
- }
-
- if (result.SupportsCredentials)
- {
- headers[CorsConstants.AccessControlAllowCredentials] = "true";
- }
-
- if (result.AllowedMethods.Count > 0)
- {
- headers.SetCommaSeparatedValues(
- CorsConstants.AccessControlAllowMethods,
- result.AllowedMethods.ToArray());
- }
-
- if (result.AllowedHeaders.Count > 0)
- {
- headers.SetCommaSeparatedValues(
- CorsConstants.AccessControlAllowHeaders,
- result.AllowedHeaders.ToArray());
- }
-
- if (result.AllowedExposedHeaders.Count > 0)
- {
- headers.SetCommaSeparatedValues(
- CorsConstants.AccessControlExposeHeaders,
- result.AllowedExposedHeaders.ToArray());
- }
-
- if (result.PreflightMaxAge.HasValue)
- {
- headers[CorsConstants.AccessControlMaxAge]
- = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture);
+ response.Headers.Append("Vary", "Origin");
}
}
- private void AddOriginToResult(string origin, CorsPolicy policy, CorsResult result)
- {
- if (policy.AllowAnyOrigin)
- {
- if (policy.SupportsCredentials)
- {
- result.AllowedOrigin = origin;
- result.VaryByOrigin = true;
- }
- else
- {
- result.AllowedOrigin = CorsConstants.AnyOrigin;
- }
- }
- else if (policy.IsOriginAllowed(origin))
- {
- result.AllowedOrigin = origin;
-
- if(policy.Origins.Count > 1)
- {
- result.VaryByOrigin = true;
- }
- }
- }
-
- private static void AddHeaderValues(IList target, IEnumerable headerValues)
+ private static void AddHeaderValues(IList target, IList headerValues)
{
if (headerValues == null)
{
return;
}
- foreach (var current in headerValues)
+ for (var i = 0; i < headerValues.Count; i++)
{
- target.Add(current);
+ target.Add(headerValues[i]);
}
}
@@ -268,17 +233,18 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
{
if (StringValues.IsNullOrEmpty(origin))
{
- _logger?.RequestDoesNotHaveOriginHeader();
+ _logger.RequestDoesNotHaveOriginHeader();
return false;
}
- _logger?.RequestHasOriginHeader(origin);
+ _logger.RequestHasOriginHeader(origin);
if (policy.AllowAnyOrigin || policy.IsOriginAllowed(origin))
{
+ _logger.PolicySuccess();
return true;
}
- _logger?.PolicyFailure();
- _logger?.OriginNotAllowed(origin);
+ _logger.PolicyFailure();
+ _logger.OriginNotAllowed(origin);
return false;
}
}
diff --git a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs
index bfcc82a2e6..ee6533bbed 100644
--- a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs
+++ b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs
@@ -17,6 +17,9 @@ namespace Microsoft.AspNetCore.Cors.Internal
private static readonly Action _accessControlMethodNotAllowed;
private static readonly Action _requestHeaderNotAllowed;
private static readonly Action _failedToSetCorsHeaders;
+ private static readonly Action _noCorsPolicyFound;
+ private static readonly Action _insecureConfiguration;
+ private static readonly Action _isNotPreflightRequest;
static CORSLoggerExtensions()
{
@@ -64,6 +67,21 @@ namespace Microsoft.AspNetCore.Cors.Internal
LogLevel.Warning,
9,
"Failed to apply CORS Response headers.");
+
+ _noCorsPolicyFound = LoggerMessage.Define(
+ LogLevel.Information,
+ new EventId(10, "NoCorsPolicyFound"),
+ "No CORS policy found for the specified request.");
+
+ _insecureConfiguration = LoggerMessage.Define(
+ LogLevel.Warning,
+ new EventId(11, "CorsInsecureConfiguration"),
+ "The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time. Configure the policy by listing individual origins if credentials needs to be supported.");
+
+ _isNotPreflightRequest = LoggerMessage.Define(
+ LogLevel.Debug,
+ new EventId(12, "OptionsRequestWithoutAccessControlRequestMethodHeader"),
+ "This request uses the HTTP OPTIONS method but does not have an Access-Control-Request-Method header. This request will not be treated as a CORS preflight request.");
}
public static void IsPreflightRequest(this ILogger logger)
@@ -110,5 +128,20 @@ namespace Microsoft.AspNetCore.Cors.Internal
{
_failedToSetCorsHeaders(logger, exception);
}
+
+ public static void NoCorsPolicyFound(this ILogger logger)
+ {
+ _noCorsPolicyFound(logger, null);
+ }
+
+ public static void InsecureConfiguration(this ILogger logger)
+ {
+ _insecureConfiguration(logger, null);
+ }
+
+ public static void IsNotPreflightRequest(this ILogger logger)
+ {
+ _isNotPreflightRequest(logger, null);
+ }
}
}
diff --git a/test/FunctionalTests/Assert.cs b/test/FunctionalTests/Assert.cs
new file mode 100644
index 0000000000..6e1ab583d7
--- /dev/null
+++ b/test/FunctionalTests/Assert.cs
@@ -0,0 +1,45 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Text;
+using Xunit.Sdk;
+
+namespace FunctionalTests
+{
+ public class Assert : Xunit.Assert
+ {
+ public static void Success(in ProcessResult processResult)
+ {
+ if (processResult.ExitCode != 0)
+ {
+ throw new ProcessAssertException(processResult);
+ }
+ }
+
+ private class ProcessAssertException : XunitException
+ {
+ public ProcessAssertException(in ProcessResult processResult)
+ {
+ Result = processResult;
+ }
+
+ public ProcessResult Result { get; }
+
+ public override string Message
+ {
+ get
+ {
+ var message = new StringBuilder();
+ message.Append(Result.ProcessStartInfo.FileName);
+ message.Append(" ");
+ message.Append(Result.ProcessStartInfo.Arguments);
+ message.Append($" exited with {Result.ExitCode}.");
+ message.AppendLine();
+ message.AppendLine();
+ message.Append(Result.Output);
+ return message.ToString();
+ }
+ }
+ }
+ }
+}
diff --git a/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs b/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs
new file mode 100644
index 0000000000..7c61d1f77b
--- /dev/null
+++ b/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs
@@ -0,0 +1,144 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Server.IntegrationTesting;
+using Microsoft.AspNetCore.Testing;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Testing;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace FunctionalTests
+{
+ public class CorsMiddlewareFunctionalTests : LoggedTest
+ {
+ public CorsMiddlewareFunctionalTests(ITestOutputHelper output)
+ : base(output)
+ {
+ Output = output;
+ }
+
+ public ITestOutputHelper Output { get; }
+
+ [Fact]
+ public async Task RunClientTests()
+ {
+ using (StartLog(out var loggerFactory))
+ using (var deploymentResult = await CreateDeployments(loggerFactory))
+ {
+ ProcessStartInfo processStartInfo;
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ processStartInfo = new ProcessStartInfo
+ {
+ FileName = "cmd",
+ Arguments = "/c npm test --no-color",
+ };
+ }
+ else
+ {
+ processStartInfo = new ProcessStartInfo
+ {
+ FileName = "npm",
+ Arguments = "test",
+ };
+ }
+
+ // Act
+ var result = await ProcessManager.RunProcessAsync(processStartInfo);
+
+ // Assert
+ Assert.Success(result);
+ Assert.Contains("Test Suites: 1 passed, 1 total", result.Output);
+ }
+ }
+
+ private static async Task CreateDeployments(ILoggerFactory loggerFactory)
+ {
+ var solutionPath = TestPathUtilities.GetSolutionRootDirectory("CORS");
+
+ var runtimeFlavor = GetRuntimeFlavor();
+ var applicationType = runtimeFlavor == RuntimeFlavor.Clr ? ApplicationType.Standalone : ApplicationType.Portable;
+
+ var configuration =
+#if RELEASE
+ "Release";
+#else
+ "Debug";
+#endif
+
+ var destinationParameters = new DeploymentParameters
+ {
+ RuntimeFlavor = runtimeFlavor,
+ ServerType = ServerType.Kestrel,
+ ApplicationPath = Path.Combine(solutionPath, "samples", "SampleDestination"),
+ PublishApplicationBeforeDeployment = false,
+ ApplicationType = applicationType,
+ Configuration = configuration,
+ };
+
+ var destinationFactory = ApplicationDeployerFactory.Create(destinationParameters, loggerFactory);
+ var destinationDeployment = await destinationFactory.DeployAsync();
+
+ var originParameters = new DeploymentParameters
+ {
+ RuntimeFlavor = runtimeFlavor,
+ ServerType = ServerType.Kestrel,
+ ApplicationPath = Path.Combine(solutionPath, "samples", "SampleOrigin"),
+ PublishApplicationBeforeDeployment = false,
+ ApplicationType = applicationType,
+ Configuration = configuration,
+ };
+
+ var originFactory = ApplicationDeployerFactory.Create(originParameters, loggerFactory);
+ var originDeployment = await originFactory.DeployAsync();
+
+ return new SamplesDeploymentResult(originFactory, originDeployment, destinationFactory, destinationDeployment);
+ }
+
+ private static RuntimeFlavor GetRuntimeFlavor()
+ {
+#if NET461
+ return RuntimeFlavor.Clr;
+#elif NETCOREAPP2_2
+ return RuntimeFlavor.CoreClr;
+#else
+#error Target frameworks need to be updated
+#endif
+ }
+
+ private readonly struct SamplesDeploymentResult : IDisposable
+ {
+ public SamplesDeploymentResult(
+ ApplicationDeployer originDeployer,
+ DeploymentResult originResult,
+ ApplicationDeployer destinationDeployer,
+ DeploymentResult destinationResult)
+ {
+ OriginDeployer = originDeployer;
+ OriginResult = originResult;
+ DestinationDeployer = destinationDeployer;
+ DestinationResult = destinationResult;
+ }
+
+ public ApplicationDeployer OriginDeployer { get; }
+
+ public DeploymentResult OriginResult { get; }
+
+ public ApplicationDeployer DestinationDeployer { get; }
+
+ public DeploymentResult DestinationResult { get; }
+
+ public void Dispose()
+ {
+ OriginDeployer.Dispose();
+ DestinationDeployer.Dispose();
+ }
+ }
+ }
+}
diff --git a/test/FunctionalTests/FunctionalTests.csproj b/test/FunctionalTests/FunctionalTests.csproj
new file mode 100644
index 0000000000..edd7b696eb
--- /dev/null
+++ b/test/FunctionalTests/FunctionalTests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ $(StandardTestTfms)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/FunctionalTests/ProcessManager.cs b/test/FunctionalTests/ProcessManager.cs
new file mode 100644
index 0000000000..9689a2da7d
--- /dev/null
+++ b/test/FunctionalTests/ProcessManager.cs
@@ -0,0 +1,101 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FunctionalTests
+{
+ internal static class ProcessManager
+ {
+ private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(60);
+
+ public static Task RunProcessAsync(ProcessStartInfo processStartInfo)
+ {
+ processStartInfo.UseShellExecute = false;
+ processStartInfo.RedirectStandardError = true;
+ processStartInfo.RedirectStandardOutput = true;
+
+ var process = new Process()
+ {
+ StartInfo = processStartInfo,
+ EnableRaisingEvents = true,
+ };
+
+ var output = new StringBuilder();
+ var outputLock = new object();
+
+ process.ErrorDataReceived += Process_ErrorDataReceived;
+ process.OutputDataReceived += Process_OutputDataReceived;
+
+ process.Start();
+ process.BeginErrorReadLine();
+ process.BeginOutputReadLine();
+
+ var timeoutTask = Task.Delay(Timeout).ContinueWith((t) =>
+ {
+ // Don't timeout during debug sessions
+ while (Debugger.IsAttached)
+ {
+ Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+
+ if (process.HasExited)
+ {
+ // This will happen on success, the 'real' task has already completed so this value will
+ // never be visible.
+ return (ProcessResult)default;
+ }
+
+ // This is a timeout.
+ process.Kill();
+ throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {Timeout}.");
+ });
+
+ var waitTask = Task.Run(() =>
+ {
+ // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously
+ // this code used Process.Exited, which could result in us missing some output due to the ordering of
+ // events.
+ //
+ // See the remarks here: https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx
+ if (!process.WaitForExit(int.MaxValue))
+ {
+ // unreachable - the timeoutTask will kill the process before this happens.
+ throw new TimeoutException();
+ }
+
+ process.WaitForExit();
+
+ string outputString;
+ lock (outputLock)
+ {
+ outputString = output.ToString();
+ }
+
+ return new ProcessResult(processStartInfo, process.ExitCode, outputString);
+ });
+
+ return Task.WhenAny(waitTask, timeoutTask).Unwrap();
+
+ void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ lock (outputLock)
+ {
+ output.AppendLine(e.Data);
+ }
+ }
+
+ void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ lock (outputLock)
+ {
+ output.AppendLine(e.Data);
+ }
+ }
+ }
+ }
+}
diff --git a/test/FunctionalTests/ProcessResult.cs b/test/FunctionalTests/ProcessResult.cs
new file mode 100644
index 0000000000..8ff1f260bf
--- /dev/null
+++ b/test/FunctionalTests/ProcessResult.cs
@@ -0,0 +1,21 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Diagnostics;
+
+namespace FunctionalTests
+{
+ public readonly struct ProcessResult
+ {
+ public ProcessResult(ProcessStartInfo processStartInfo, int exitCode, string output)
+ {
+ ProcessStartInfo = processStartInfo;
+ ExitCode = exitCode;
+ Output = output;
+ }
+
+ public ProcessStartInfo ProcessStartInfo { get; }
+ public int ExitCode { get; }
+ public string Output { get; }
+ }
+}
diff --git a/test/FunctionalTests/package-lock.json b/test/FunctionalTests/package-lock.json
new file mode 100644
index 0000000000..93547d2bde
--- /dev/null
+++ b/test/FunctionalTests/package-lock.json
@@ -0,0 +1,5637 @@
+{
+ "requires": true,
+ "lockfileVersion": 1,
+ "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.4.1",
+ "esutils": "2.0.2",
+ "js-tokens": "4.0.0"
+ },
+ "dependencies": {
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ }
+ }
+ },
+ "abab": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
+ "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "dev": true
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.1.tgz",
+ "integrity": "sha512-SiwgrRuRD2D1R6qjwwoopKcCTkmmIWjy1M15Wv+Nk/7VUsBad4P8GOPft2t6coDZG0TuR5dq9o1v0g8wo7F6+A==",
+ "dev": true
+ }
+ }
+ },
+ "acorn-walk": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.0.1.tgz",
+ "integrity": "sha512-PqVQ8c6a3kyqdsUZlC7nljp3FFuxipBRHKu+7C1h8QygBFlzTaDX5HD383jej3Peed+1aDG8HwkfB1Z1HMNPkw==",
+ "dev": true
+ },
+ "agent-base": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "5.0.0"
+ }
+ },
+ "ajv": {
+ "version": "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.1.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "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-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": "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.3"
+ }
+ },
+ "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.10",
+ "normalize-path": "2.1.1"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "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
+ },
+ "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.3",
+ "snapdragon": "0.8.2",
+ "snapdragon-node": "2.1.1",
+ "split-string": "3.1.0",
+ "to-regex": "3.0.2"
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "posix-character-classes": "0.1.1",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "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.6"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "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.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "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.2"
+ }
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.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.1"
+ }
+ }
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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
+ },
+ "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.2",
+ "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.13",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ }
+ }
+ }
+ },
+ "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"
+ }
+ },
+ "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.3"
+ }
+ },
+ "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.1.0"
+ }
+ },
+ "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-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "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.2"
+ }
+ },
+ "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.11"
+ }
+ },
+ "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
+ },
+ "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-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.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "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.1",
+ "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.6.0",
+ "debug": "2.6.9",
+ "json5": "0.5.1",
+ "lodash": "4.17.11",
+ "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.11",
+ "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.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "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.26.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.2",
+ "test-exclude": "4.2.3"
+ }
+ },
+ "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.3",
+ "babel-runtime": "6.26.0",
+ "core-js": "2.5.7",
+ "home-or-tmp": "2.0.0",
+ "lodash": "4.17.11",
+ "mkdirp": "0.5.1",
+ "source-map-support": "0.4.18"
+ }
+ },
+ "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.5.7",
+ "regenerator-runtime": "0.11.1"
+ }
+ },
+ "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.11"
+ }
+ },
+ "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.9",
+ "globals": "9.18.0",
+ "invariant": "2.2.4",
+ "lodash": "4.17.11"
+ }
+ },
+ "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.11",
+ "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.6",
+ "component-emitter": "1.2.1",
+ "define-property": "1.0.0",
+ "isobject": "3.0.1",
+ "mixin-deep": "1.3.1",
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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
+ }
+ }
+ },
+ "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,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "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": "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.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.3"
+ }
+ },
+ "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"
+ }
+ },
+ "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-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
+ },
+ "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
+ },
+ "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"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ },
+ "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.6.2"
+ }
+ },
+ "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.5.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
+ },
+ "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.1",
+ "static-extend": "0.1.2"
+ },
+ "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.6"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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.1.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.1"
+ }
+ },
+ "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
+ },
+ "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.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "dev": true,
+ "optional": 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
+ },
+ "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.1.1",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.6",
+ "typedarray": "0.0.6"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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
+ },
+ "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.1.3",
+ "shebang-command": "1.2.0",
+ "which": "1.3.1"
+ }
+ },
+ "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.4"
+ }
+ },
+ "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.0.1",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz",
+ "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==",
+ "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"
+ }
+ }
+ }
+ },
+ "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": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "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-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-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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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
+ }
+ }
+ },
+ "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
+ },
+ "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.1"
+ }
+ },
+ "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
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "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"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1",
+ "safer-buffer": "2.1.2"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.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.3",
+ "is-callable": "1.1.4",
+ "is-regex": "1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
+ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
+ "dev": true,
+ "requires": {
+ "is-callable": "1.1.4",
+ "is-date-object": "1.0.1",
+ "is-symbol": "1.0.2"
+ }
+ },
+ "es6-promise": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
+ "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==",
+ "dev": true
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "dev": true,
+ "requires": {
+ "es6-promise": "4.2.5"
+ }
+ },
+ "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.2",
+ "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
+ }
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "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.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "5.1.0",
+ "get-stream": "3.0.0",
+ "is-stream": "1.1.0",
+ "npm-run-path": "2.0.2",
+ "p-finally": "1.0.0",
+ "signal-exit": "3.0.2",
+ "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": "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.1"
+ }
+ },
+ "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.2.4"
+ }
+ },
+ "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.1",
+ "jest-diff": "23.6.0",
+ "jest-get-type": "22.4.3",
+ "jest-matcher-utils": "23.6.0",
+ "jest-message-util": "23.4.0",
+ "jest-regex-util": "23.3.0"
+ }
+ },
+ "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": "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"
+ }
+ },
+ "extract-zip": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
+ "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
+ "dev": true,
+ "requires": {
+ "concat-stream": "1.6.2",
+ "debug": "2.6.9",
+ "mkdirp": "0.5.1",
+ "yauzl": "2.4.1"
+ }
+ },
+ "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": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "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
+ },
+ "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"
+ }
+ },
+ "fd-slicer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+ "dev": true,
+ "requires": {
+ "pend": "1.2.0"
+ }
+ },
+ "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.1.3",
+ "minimatch": "3.0.4"
+ }
+ },
+ "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.1.0",
+ "randomatic": "3.1.0",
+ "repeat-element": "1.1.3",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "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"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.2",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
+ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+ "dev": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.6",
+ "mime-types": "2.1.20"
+ },
+ "dependencies": {
+ "combined-stream": {
+ "version": "1.0.6",
+ "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ }
+ }
+ },
+ "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"
+ }
+ },
+ "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.11.0",
+ "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.3.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.4"
+ }
+ },
+ "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.2.0",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.11"
+ }
+ },
+ "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.2"
+ }
+ },
+ "minizlib": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "2.2.4"
+ }
+ },
+ "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.6.9",
+ "iconv-lite": "0.4.21",
+ "sax": "1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.10.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "1.0.3",
+ "mkdirp": "0.5.1",
+ "needle": "2.2.0",
+ "nopt": "4.0.1",
+ "npm-packlist": "1.1.10",
+ "npmlog": "4.1.2",
+ "rc": "1.2.7",
+ "rimraf": "2.6.2",
+ "semver": "5.5.0",
+ "tar": "4.4.1"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1.1.1",
+ "osenv": "0.1.5"
+ }
+ },
+ "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.3"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "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.0.2"
+ }
+ },
+ "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.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "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.5",
+ "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.2",
+ "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.2"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "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.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "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.1",
+ "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
+ },
+ "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": "https://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.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.1"
+ }
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "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
+ },
+ "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.6.1",
+ "optimist": "0.6.1",
+ "source-map": "0.6.1",
+ "uglify-js": "3.4.9"
+ },
+ "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
+ }
+ }
+ },
+ "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.5.2",
+ "har-schema": "2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "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.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "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": {
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "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.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "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
+ },
+ "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.4"
+ }
+ },
+ "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.4.1",
+ "sshpk": "1.14.2"
+ }
+ },
+ "https-proxy-agent": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+ "dev": true,
+ "requires": {
+ "agent-base": "4.2.1",
+ "debug": "3.2.5"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz",
+ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "2.1.2"
+ }
+ },
+ "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"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "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.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "1.4.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-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.2.2"
+ }
+ },
+ "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-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.1.1"
+ }
+ },
+ "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.6.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.2.2"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.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": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "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.1"
+ }
+ },
+ "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": "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"
+ }
+ },
+ "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.2.2"
+ }
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "3.0.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "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.3"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "1.0.0"
+ }
+ },
+ "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
+ },
+ "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": "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"
+ }
+ },
+ "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.6.1",
+ "fileset": "2.0.3",
+ "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.12.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.26.1",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "istanbul-lib-coverage": "1.2.1",
+ "semver": "5.5.1"
+ }
+ },
+ "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.6",
+ "supports-color": "3.2.3"
+ },
+ "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.2.5",
+ "istanbul-lib-coverage": "1.2.1",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.2",
+ "source-map": "0.5.7"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz",
+ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==",
+ "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.12"
+ }
+ },
+ "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"
+ }
+ },
+ "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.1.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.1.0",
+ "chalk": "2.4.1",
+ "exit": "0.1.2",
+ "glob": "7.1.3",
+ "graceful-fs": "4.1.11",
+ "import-local": "1.0.0",
+ "is-ci": "1.2.1",
+ "istanbul-api": "1.3.7",
+ "istanbul-lib-coverage": "1.2.1",
+ "istanbul-lib-instrument": "1.10.2",
+ "istanbul-lib-source-maps": "1.2.6",
+ "jest-changed-files": "23.4.2",
+ "jest-config": "23.6.0",
+ "jest-environment-jsdom": "23.4.0",
+ "jest-get-type": "22.4.3",
+ "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.14",
+ "realpath-native": "1.0.2",
+ "rimraf": "2.6.2",
+ "slash": "1.0.0",
+ "string-length": "2.0.0",
+ "strip-ansi": "4.0.0",
+ "which": "1.3.1",
+ "yargs": "11.1.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.26.3",
+ "babel-jest": "23.6.0",
+ "chalk": "2.4.1",
+ "glob": "7.1.3",
+ "jest-environment-jsdom": "23.4.0",
+ "jest-environment-node": "23.4.0",
+ "jest-get-type": "22.4.3",
+ "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"
+ }
+ },
+ "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.4.1",
+ "diff": "3.5.0",
+ "jest-get-type": "22.4.3",
+ "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-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.4.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.12.0"
+ }
+ },
+ "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": "https://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.5.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.26.0",
+ "chalk": "2.4.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.4.1",
+ "jest-get-type": "22.4.3",
+ "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",
+ "chalk": "2.4.1",
+ "micromatch": "2.3.11",
+ "slash": "1.0.0",
+ "stack-utils": "1.0.1"
+ }
+ },
+ "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.4.1",
+ "realpath-native": "1.0.2"
+ }
+ },
+ "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.9",
+ "throat": "4.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
+ },
+ "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.1.1",
+ "source-map": "0.6.1"
+ }
+ }
+ }
+ },
+ "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.26.3",
+ "babel-plugin-istanbul": "4.1.6",
+ "chalk": "2.4.1",
+ "convert-source-map": "1.6.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.2",
+ "slash": "1.0.0",
+ "strip-bom": "3.0.0",
+ "write-file-atomic": "2.3.0",
+ "yargs": "11.1.0"
+ },
+ "dependencies": {
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "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.26.0",
+ "chalk": "2.4.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.1"
+ }
+ },
+ "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.4.1",
+ "graceful-fs": "4.1.11",
+ "is-ci": "1.2.1",
+ "jest-message-util": "23.4.0",
+ "mkdirp": "0.5.1",
+ "slash": "1.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
+ }
+ }
+ },
+ "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.4.1",
+ "jest-get-type": "22.4.3",
+ "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.1.0",
+ "chalk": "2.4.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": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "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.10",
+ "esprima": "4.0.1"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true,
+ "optional": 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.7.3",
+ "acorn-globals": "4.3.0",
+ "array-equal": "1.0.0",
+ "cssom": "0.3.4",
+ "cssstyle": "1.1.1",
+ "data-urls": "1.0.1",
+ "domexception": "1.0.1",
+ "escodegen": "1.11.0",
+ "html-encoding-sniffer": "1.0.2",
+ "left-pad": "1.3.0",
+ "nwsapi": "2.0.9",
+ "parse5": "4.0.0",
+ "pn": "1.1.0",
+ "request": "2.88.0",
+ "request-promise-native": "1.0.5",
+ "sax": "1.2.4",
+ "symbol-tree": "3.2.2",
+ "tough-cookie": "2.4.3",
+ "w3c-hr-time": "1.0.1",
+ "webidl-conversions": "4.0.2",
+ "whatwg-encoding": "1.0.4",
+ "whatwg-mimetype": "2.2.0",
+ "whatwg-url": "6.5.0",
+ "ws": "5.2.2",
+ "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-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.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "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
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://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"
+ }
+ },
+ "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.6"
+ }
+ },
+ "kleur": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz",
+ "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "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.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.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.sortby": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "js-tokens": "3.0.2"
+ }
+ },
+ "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"
+ }
+ },
+ "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.4"
+ }
+ },
+ "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.1"
+ }
+ },
+ "math-random": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
+ "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
+ "dev": true
+ },
+ "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.2.0"
+ }
+ },
+ "merge": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
+ "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=",
+ "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.3.6"
+ }
+ },
+ "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.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.1",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.2.2",
+ "normalize-path": "2.1.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.4"
+ }
+ },
+ "mime": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
+ "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.36.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
+ "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.20",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
+ "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.36.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "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.11"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz",
+ "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==",
+ "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.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "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
+ },
+ "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
+ }
+ }
+ },
+ "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
+ },
+ "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-notifier": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz",
+ "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==",
+ "dev": true,
+ "requires": {
+ "growly": "1.3.0",
+ "semver": "5.5.1",
+ "shellwords": "0.1.1",
+ "which": "1.3.1"
+ }
+ },
+ "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.7.1",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.5.1",
+ "validate-npm-package-license": "3.0.4"
+ }
+ },
+ "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.1.0"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "2.0.1"
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "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.1",
+ "define-property": "0.2.5",
+ "kind-of": "3.2.2"
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "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.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "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.3",
+ "es-abstract": "1.12.0"
+ }
+ },
+ "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.5",
+ "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"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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.0.2"
+ }
+ },
+ "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.8",
+ "wordwrap": "0.0.3"
+ }
+ },
+ "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.6",
+ "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
+ }
+ }
+ },
+ "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": "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"
+ }
+ },
+ "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-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "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.3.0"
+ }
+ },
+ "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
+ },
+ "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.3",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
+ "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.3.2"
+ }
+ },
+ "parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+ "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-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "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-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.11",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "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": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "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.4"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "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-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.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ }
+ }
+ },
+ "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-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
+ },
+ "progress": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+ "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.2",
+ "sisteransi": "0.1.1"
+ }
+ },
+ "proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=",
+ "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
+ },
+ "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
+ },
+ "puppeteer": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.8.0.tgz",
+ "integrity": "sha512-wJ7Fxs03l4dy/ZXQACUKBBobIuJaS4NHq44q7/QinpAXFMwJMJFEIPjzoksVzUhZxQe+RXnjXH69mg13yMh0BA==",
+ "dev": true,
+ "requires": {
+ "debug": "3.2.5",
+ "extract-zip": "1.6.7",
+ "https-proxy-agent": "2.2.1",
+ "mime": "2.3.1",
+ "progress": "2.0.0",
+ "proxy-from-env": "1.0.0",
+ "rimraf": "2.6.2",
+ "ws": "5.2.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz",
+ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==",
+ "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
+ }
+ }
+ },
+ "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
+ },
+ "randomatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz",
+ "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "4.0.0",
+ "kind-of": "6.0.2",
+ "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
+ },
+ "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
+ }
+ }
+ },
+ "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.1.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "1.1.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.1.2",
+ "read-pkg": "1.1.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.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.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"
+ }
+ },
+ "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"
+ }
+ },
+ "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
+ },
+ "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.2"
+ }
+ },
+ "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.7",
+ "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.20",
+ "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.17.11"
+ }
+ },
+ "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.1",
+ "tough-cookie": "2.4.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
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ },
+ "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.1.3"
+ }
+ },
+ "rsvp": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz",
+ "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==",
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "0.1.15"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "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.2",
+ "fb-watchman": "2.0.0",
+ "fsevents": "1.2.4",
+ "micromatch": "3.1.10",
+ "minimist": "1.2.0",
+ "walker": "1.0.7",
+ "watch": "0.18.0"
+ },
+ "dependencies": {
+ "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
+ },
+ "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
+ },
+ "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.3",
+ "snapdragon": "0.8.2",
+ "snapdragon-node": "2.1.1",
+ "split-string": "3.1.0",
+ "to-regex": "3.0.2"
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "posix-character-classes": "0.1.1",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "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.6"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "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.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "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.2"
+ }
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.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.1"
+ }
+ }
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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
+ },
+ "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.2",
+ "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.13",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ }
+ },
+ "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
+ },
+ "semver": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
+ "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
+ "dev": true
+ },
+ "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.4",
+ "split-string": "3.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.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.2",
+ "debug": "2.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "map-cache": "0.2.2",
+ "source-map": "0.5.7",
+ "source-map-resolve": "0.5.2",
+ "use": "3.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.6"
+ }
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.1",
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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
+ }
+ }
+ },
+ "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.2"
+ }
+ },
+ "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-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.2",
+ "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.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.7"
+ }
+ },
+ "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.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+ "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "3.0.0",
+ "spdx-license-ids": "3.0.1"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+ "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+ "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.1"
+ }
+ },
+ "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
+ },
+ "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.2"
+ }
+ },
+ "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.14.2",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
+ "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
+ "dev": true,
+ "requires": {
+ "asn1": "0.2.4",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.2",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.2",
+ "getpass": "0.1.7",
+ "jsbn": "0.1.1",
+ "safer-buffer": "2.1.2",
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "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
+ },
+ "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_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.2"
+ }
+ },
+ "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"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ }
+ }
+ },
+ "strip-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.1"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "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
+ },
+ "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.1",
+ "read-pkg-up": "1.0.1",
+ "require-main-filename": "1.0.1"
+ }
+ },
+ "throat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
+ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=",
+ "dev": true
+ },
+ "tmpl": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
+ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
+ "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.2.2"
+ }
+ },
+ "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"
+ },
+ "dependencies": {
+ "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.2.2"
+ }
+ }
+ }
+ },
+ "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.29",
+ "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.1"
+ }
+ },
+ "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
+ },
+ "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.1.2"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true,
+ "optional": 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"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "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"
+ },
+ "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,
+ "optional": 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.1"
+ }
+ },
+ "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.4",
+ "to-object-path": "0.3.0"
+ }
+ }
+ }
+ },
+ "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.1"
+ },
+ "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.6",
+ "has-values": "0.1.4",
+ "isobject": "2.1.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
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "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-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.3",
+ "object.getownpropertydescriptors": "2.0.3"
+ }
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+ "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"
+ }
+ },
+ "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.3.0"
+ }
+ },
+ "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.3"
+ }
+ },
+ "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.11"
+ }
+ },
+ "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.2",
+ "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
+ }
+ }
+ },
+ "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
+ },
+ "whatwg-encoding": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz",
+ "integrity": "sha512-vM9KWN6MP2mIHZ86ytcyIv7e8Cj3KTfO2nd2c8PFDqcI4bxFmQp83ibq4wadq7rL9l9sZV6o9B0LTt8ygGAAXg==",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "0.4.23"
+ }
+ },
+ "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
+ },
+ "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.2",
+ "strip-ansi": "3.0.1"
+ },
+ "dependencies": {
+ "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.1"
+ }
+ },
+ "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.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ }
+ }
+ },
+ "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
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+ "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": "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.1.0",
+ "decamelize": "1.2.0",
+ "find-up": "2.1.0",
+ "get-caller-file": "1.0.3",
+ "os-locale": "2.1.0",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "2.1.1",
+ "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"
+ }
+ },
+ "yauzl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+ "dev": true,
+ "requires": {
+ "fd-slicer": "1.0.1"
+ }
+ }
+ }
+}
diff --git a/test/FunctionalTests/package.json b/test/FunctionalTests/package.json
new file mode 100644
index 0000000000..c5a8e5f365
--- /dev/null
+++ b/test/FunctionalTests/package.json
@@ -0,0 +1,10 @@
+{
+ "devDependencies": {
+ "jest": "^23.6.0",
+ "puppeteer": "^1.8.0"
+ },
+ "dependencies": {},
+ "scripts": {
+ "test": "jest"
+ }
+}
diff --git a/test/FunctionalTests/test.js b/test/FunctionalTests/test.js
new file mode 100644
index 0000000000..2fc14652e1
--- /dev/null
+++ b/test/FunctionalTests/test.js
@@ -0,0 +1,280 @@
+const puppeteer = require('puppeteer');
+const os = require("os");
+const hostname = os.hostname();
+
+const corsServerPath = `http://${hostname}:9000`;
+
+// e.g., npm test --debug
+// In debug mode we show the editor, slow down operations, and increase the timeout for each test
+const debug = process.env.npm_config_debug || false;
+jest.setTimeout(debug ? 60000 : 30000);
+
+let browser;
+
+beforeAll(async () => {
+ const options = debug ?
+ { headless: false, slowMo: 100 } :
+ { args: ['--no-sandbox'] };
+ browser = await puppeteer.launch(options);
+ expect(browser).toBeDefined();
+});
+
+afterAll(async () => {
+ await browser.close();
+});
+
+describe('CORS allowed origin tests ', () => {
+ const testPagePath = `http://${hostname}:9001/`;
+ let page;
+
+ beforeAll(async () => {
+ page = await browser.newPage();
+ await page.goto(testPagePath);
+ });
+
+ test('allows simple GET requests', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'GET', mode: 'cors' };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ test('allows simple PUT requests when any method is allowed', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'PUT', mode: 'cors' };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ // This one is weird - although the server performs a preflight request and receives a Access-Control-Allow-Methods: PUT,
+ // the browser happily ignores the disallowed POST method.
+ test('allows POST requests when not explicitly allowed', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-header-method`;
+ const options = {
+ method: 'POST',
+ mode: 'cors',
+ body: JSON.stringify({ hello: 'world' }),
+ headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' })
+ };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ test('allows header to be sent when allowed', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-header-method`;
+ const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ test('does not allow disallowed HTTP Methods', async () => {
+ expect.assertions(1);
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-header-method`;
+ const options = { method: 'DELETE', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) };
+
+ return await fetch(url, options);
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+
+ test('does not allow disallowed header', async () => {
+ expect.assertions(1);
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-header-method`;
+ const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Not-Test": "value", 'Content-Type': 'application/json' }) };
+
+ return await fetch(url, options);
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+
+ test('does not allow fetch with credentials in non-Preflighted request', async () => {
+ expect.assertions(1);
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'POST', mode: 'cors', credentials: 'include' };
+
+ return await fetch(url, options);
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+
+ test('does not allow fetch with credentials in Preflighted request', async () => {
+ expect.assertions(1);
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'PUT', mode: 'cors', credentials: 'include' };
+
+ return await fetch(url, options);
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+
+ test('allows request with credentials', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-credentials`;
+ const options = { method: 'GET', mode: 'cors', credentials: 'include' };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ test('allows Preflighted request with credentials', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-credentials`;
+ const options = { method: 'PUT', mode: 'cors', credentials: 'include' };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ test('disallows accessing header when not included in exposed-header', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/exposed-header`;
+ const options = { method: 'GET', mode: 'cors' };
+
+ const response = await fetch(url, options);
+ try {
+ return response.headers.get('x-disallowedheader');
+ } catch (e) {
+ return null;
+ }
+ }, corsServerPath);
+
+ expect(result).toBeNull();
+ });
+
+ test('allows accessing header when included in exposed-header', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/exposed-header`;
+ const options = { method: 'GET', mode: 'cors' };
+
+ const response = await fetch(url, options);
+ try {
+ return response.headers.get('x-allowedheader');
+ } catch (e) {
+ return e;
+ }
+ }, corsServerPath);
+
+ expect(result).toBe("Test-Value");
+ });
+});
+
+describe('CORS disallowed origin tests ', () => {
+ const testPagePath = `http://${hostname}:9002/`;
+ let page;
+
+ beforeAll(async () => {
+ page = await browser.newPage();
+ await page.goto(testPagePath);
+ });
+
+ test('allow opaque requests without CORS', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'GET', mode: 'no-cors' };
+
+ // The request will succeed, but we get an opaque filtered response (https://fetch.spec.whatwg.org/#concept-filtered-response).
+ const response = await fetch(url, options);
+ return response.type;
+ }, corsServerPath);
+
+ expect(result).toBe("opaque");
+ });
+
+ test('does not allow requests when origin is disallowed', async () => {
+ expect.assertions(1);
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'GET', mode: 'cors' };
+
+ return await fetch(url, options);
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+
+ test('does not allow preflight requests when origin is disallowed', async () => {
+ expect.assertions(1);
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-origin`;
+ const options = { method: 'PUT', mode: 'cors' };
+
+ return await fetch(url, options);
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+
+ test('allow requests to any origin endpoint', async () => {
+ const result = await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-all`;
+ const options = { method: 'PUT', mode: 'cors' };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+
+ expect(result).toBe(200);
+ });
+
+ test('does not allow requests to any origin endpoint with credentials', async () => {
+ expect.assertions(1);
+
+ try {
+ await page.evaluate(async (corsServerPath) => {
+ const url = `${corsServerPath}/allow-all`;
+ const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }), credentials: 'include' };
+
+ const response = await fetch(url, options);
+ return response.status;
+ }, corsServerPath);
+ } catch (e) {
+ expect(e).toBeDefined();
+ }
+ });
+});
diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs
deleted file mode 100644
index 008a4926d9..0000000000
--- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Xunit;
-
-namespace Microsoft.AspNetCore.Cors.Infrastructure
-{
- public class CorsMiddlewareFunctionalTests : IClassFixture>
- {
- public CorsMiddlewareFunctionalTests(CorsTestFixture fixture)
- {
- Client = fixture.Client;
- }
-
- public HttpClient Client { get; }
-
- [Theory]
- [InlineData("GET")]
- [InlineData("HEAD")]
- [InlineData("POST")]
- public async Task ResourceWithSimpleRequestPolicy_Allows_SimpleRequests(string method)
- {
- // Arrange
- var path = "/CorsMiddleware/EC6AA70D-BA3E-4B71-A87F-18625ADDB2BD";
- var origin = "http://example.com";
- var request = new HttpRequestMessage(new HttpMethod(method), path);
- request.Headers.Add(CorsConstants.Origin, origin);
-
- // Act
- var response = await Client.SendAsync(request);
-
- // Assert
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- var content = await response.Content.ReadAsStringAsync();
- Assert.Equal(path, content);
- var responseHeaders = response.Headers;
- var header = Assert.Single(response.Headers);
- Assert.Equal(CorsConstants.AccessControlAllowOrigin, header.Key);
- Assert.Equal(new[] { "http://example.com" }, header.Value.ToArray());
- }
-
- [Theory]
- [InlineData("GET")]
- [InlineData("HEAD")]
- [InlineData("POST")]
- [InlineData("PUT")]
- public async Task PolicyFailed_Disallows_PreFlightRequest(string method)
- {
- // Arrange
- var path = "/CorsMiddleware/9B8BB9C6-5BF2-4255-A636-DCB450D51AAE";
- var request = new HttpRequestMessage(new HttpMethod(CorsConstants.PreflightHttpMethod), path);
-
- // Adding a custom header makes it a non-simple request.
- request.Headers.Add(CorsConstants.Origin, "http://example.com");
- request.Headers.Add(CorsConstants.AccessControlRequestMethod, method);
- request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
-
- // Act
- var response = await Client.SendAsync(request);
-
- // Assert
- // Middleware applied the policy and since that did not pass, there were no access control headers.
- Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
- Assert.Empty(response.Headers);
-
- // It should short circuit and hence no result.
- var content = await response.Content.ReadAsStringAsync();
- Assert.Equal(string.Empty, content);
- }
-
- [Fact]
- public async Task PolicyFailed_Allows_ActualRequest_WithMissingResponseHeaders()
- {
- // Arrange
- var path = "/CorsMiddleware/1E6C6F4D-1E1C-450E-8BD0-73DBF089A78F";
- var request = new HttpRequestMessage(HttpMethod.Put, path);
-
- // Adding a custom header makes it a non simple request.
- request.Headers.Add(CorsConstants.Origin, "http://example2.com");
-
- // Act
- var response = await Client.SendAsync(request);
-
- // Assert
- // Middleware applied the policy and since that did not pass, there were no access control headers.
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- Assert.Empty(response.Headers);
-
- // It still has executed the action.
- var content = await response.Content.ReadAsStringAsync();
- Assert.Equal(path, content);
- }
- }
-}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs
index 44c6d5c1be..85b79949b4 100644
--- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs
+++ b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
@@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
{
public class CorsMiddlewareTests
{
+ private const string OriginUrl = "http://api.example.com";
+
[Theory]
[InlineData("PuT")]
[InlineData("PUT")]
@@ -28,7 +30,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
.Configure(app =>
{
app.UseCors(builder =>
- builder.WithOrigins("http://localhost:5001")
+ builder.WithOrigins(OriginUrl)
.WithMethods("PUT"));
app.Run(async context =>
{
@@ -42,14 +44,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Actual request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.SendAsync(accessControlRequestMethod);
// Assert
response.EnsureSuccessStatusCode();
Assert.Single(response.Headers);
Assert.Equal("Cross origin response", await response.Content.ReadAsStringAsync());
- Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
+ Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
}
}
@@ -61,7 +63,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
.Configure(app =>
{
app.UseCors(builder =>
- builder.WithOrigins("http://localhost:5001")
+ builder.WithOrigins(OriginUrl)
.WithMethods("PUT")
.WithHeaders("Header1")
.WithExposedHeaders("AllowedHeader"));
@@ -77,14 +79,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Actual request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.SendAsync("PUT");
// Assert
response.EnsureSuccessStatusCode();
Assert.Equal(2, response.Headers.Count());
Assert.Equal("Cross origin response", await response.Content.ReadAsStringAsync());
- Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
+ Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
Assert.Equal("AllowedHeader", response.Headers.GetValues(CorsConstants.AccessControlExposeHeaders).FirstOrDefault());
}
}
@@ -96,7 +98,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
{
// Arrange
var policy = new CorsPolicy();
- policy.Origins.Add("http://localhost:5001");
+ policy.Origins.Add(OriginUrl);
policy.Methods.Add("PUT");
var hostBuilder = new WebHostBuilder()
@@ -121,13 +123,13 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Preflight request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.SendAsync(preflightMethod);
// Assert
response.EnsureSuccessStatusCode();
Assert.Single(response.Headers);
- Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
+ Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
}
}
@@ -136,7 +138,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
{
// Arrange
var policy = new CorsPolicy();
- policy.Origins.Add("http://localhost:5001");
+ policy.Origins.Add(OriginUrl);
policy.Methods.Add("PUT");
policy.Headers.Add("Header1");
policy.ExposedHeaders.Add("AllowedHeader");
@@ -163,27 +165,105 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Preflight request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.AddHeader(CorsConstants.AccessControlRequestMethod, "PUT")
.SendAsync(CorsConstants.PreflightHttpMethod);
// Assert
response.EnsureSuccessStatusCode();
- Assert.Equal(2, response.Headers.Count());
- Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
- Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault());
+ Assert.Collection(
+ response.Headers.OrderBy(h => h.Key),
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key);
+ Assert.Equal(new[] { "Header1" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key);
+ Assert.Equal(new[] { "PUT" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key);
+ Assert.Equal(new[] { OriginUrl }, kvp.Value);
+ });
}
}
[Fact]
- public async Task PreFlightRequest_DoesNotMatchPolicy_DoesNotSetHeaders()
+ public async Task PreFlight_WithCredentialsAllowed_ReturnsWildcardValues()
+ {
+ // Arrange
+ var policy = new CorsPolicyBuilder(OriginUrl)
+ .AllowAnyHeader()
+ .AllowAnyMethod()
+ .AllowCredentials()
+ .Build();
+
+ var hostBuilder = new WebHostBuilder()
+ .Configure(app =>
+ {
+ app.UseCors("customPolicy");
+ app.Run(async context =>
+ {
+ await context.Response.WriteAsync("Cross origin response");
+ });
+ })
+ .ConfigureServices(services =>
+ {
+ services.AddCors(options =>
+ {
+ options.AddPolicy("customPolicy", policy);
+ });
+ });
+
+ using (var server = new TestServer(hostBuilder))
+ {
+ // Act
+ // Preflight request.
+ var response = await server.CreateRequest("/")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
+ .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT")
+ .AddHeader(CorsConstants.AccessControlRequestHeaders, "X-Test1,X-Test2")
+ .SendAsync(CorsConstants.PreflightHttpMethod);
+
+ // Assert
+ response.EnsureSuccessStatusCode();
+ Assert.Collection(
+ response.Headers.OrderBy(h => h.Key),
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowCredentials, kvp.Key);
+ Assert.Equal(new[] { "true" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key);
+ Assert.Equal(new[] { "*" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key);
+ Assert.Equal(new[] { "*" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key);
+ Assert.Equal(new[] { OriginUrl }, kvp.Value);
+ });
+ }
+ }
+
+ [Fact]
+ public async Task PreFlightRequest_DoesNotMatchPolicy_DoesNotSetHeadersAndReturnsForbidden()
{
// Arrange
var hostBuilder = new WebHostBuilder()
.Configure(app =>
{
app.UseCors(builder =>
- builder.WithOrigins("http://localhost:5001")
+ builder.WithOrigins(OriginUrl)
.WithMethods("PUT")
.WithHeaders("Header1")
.WithExposedHeaders("AllowedHeader"));
@@ -199,7 +279,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Preflight request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5002")
+ .AddHeader(CorsConstants.Origin, "http://test.example.com")
.AddHeader(CorsConstants.AccessControlRequestMethod, "PUT")
.SendAsync(CorsConstants.PreflightHttpMethod);
@@ -217,7 +297,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
.Configure(app =>
{
app.UseCors(builder =>
- builder.WithOrigins("http://localhost:5001")
+ builder.WithOrigins(OriginUrl)
.WithMethods("PUT")
.WithHeaders("Header1")
.WithExposedHeaders("AllowedHeader"));
@@ -233,7 +313,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Actual request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5002")
+ .AddHeader(CorsConstants.Origin, "http://test.example.com")
.SendAsync("PUT");
// Assert
@@ -248,7 +328,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var corsService = Mock.Of();
var mockProvider = new Mock();
- var loggerFactory = Mock.Of();
+ var loggerFactory = NullLoggerFactory.Instance;
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny(), It.IsAny()))
.Returns(Task.FromResult(null))
.Verifiable();
@@ -278,7 +358,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var corsService = Mock.Of();
var mockProvider = new Mock();
- var loggerFactory = Mock.Of();
+ var loggerFactory = NullLoggerFactory.Instance;
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny(), It.IsAny()))
.Returns(Task.FromResult(null))
.Verifiable();
@@ -324,7 +404,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
options.AddDefaultPolicy(policyBuilder =>
{
policyBuilder
- .WithOrigins("http://localhost:5001")
+ .WithOrigins(OriginUrl)
.WithMethods("PUT")
.WithHeaders("Header1")
.WithExposedHeaders("AllowedHeader")
@@ -333,7 +413,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
options.AddPolicy("policy2", policyBuilder =>
{
policyBuilder
- .WithOrigins("http://localhost:5002")
+ .WithOrigins("http://test.example.com")
.Build();
});
});
@@ -344,15 +424,29 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Preflight request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.AddHeader(CorsConstants.AccessControlRequestMethod, "PUT")
.SendAsync(CorsConstants.PreflightHttpMethod);
// Assert
response.EnsureSuccessStatusCode();
- Assert.Equal(2, response.Headers.Count());
- Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
- Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault());
+ Assert.Collection(
+ response.Headers.OrderBy(h => h.Key),
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key);
+ Assert.Equal(new[] { "Header1" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key);
+ Assert.Equal(new[] { "PUT" }, kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key);
+ Assert.Equal(new[] { OriginUrl }, kvp.Value);
+ });
}
}
@@ -364,7 +458,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
.Configure(app =>
{
app.UseCors(builder =>
- builder.WithOrigins("http://localhost:5001")
+ builder.WithOrigins(OriginUrl)
.WithMethods("PUT")
.WithHeaders("Header1")
.WithExposedHeaders("AllowedHeader"));
@@ -381,7 +475,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Actual request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.SendAsync("PUT");
// Assert
@@ -391,7 +485,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
kvp =>
{
Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key);
- Assert.Equal("http://localhost:5001", Assert.Single(kvp.Value));
+ Assert.Equal(OriginUrl, Assert.Single(kvp.Value));
},
kvp =>
{
@@ -432,7 +526,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
});
app.UseCors(builder =>
- builder.WithOrigins("http://localhost:5001")
+ builder.WithOrigins(OriginUrl)
.WithMethods("PUT")
.WithHeaders("Header1")
.WithExposedHeaders("AllowedHeader"));
@@ -450,7 +544,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Act
// Actual request.
var response = await server.CreateRequest("/")
- .AddHeader(CorsConstants.Origin, "http://localhost:5001")
+ .AddHeader(CorsConstants.Origin, OriginUrl)
.SendAsync("PUT");
// Assert
@@ -462,7 +556,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
kvp =>
{
Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key);
- Assert.Equal("http://localhost:5001", Assert.Single(kvp.Value));
+ Assert.Equal(OriginUrl, Assert.Single(kvp.Value));
},
kvp =>
{
diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs
index ebef888ad2..4430d6ec75 100644
--- a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs
+++ b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs
@@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Linq;
using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Logging.Testing;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.Cors.Infrastructure
@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_NoOrigin_ReturnsInvalidResult()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext("GET", origin: null);
// Act
@@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_NoMatchingOrigin_ReturnsInvalidResult()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
policy.Origins.Add("bar");
@@ -39,15 +39,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Null(result.AllowedOrigin);
- Assert.False(result.VaryByOrigin);
+ Assert.False(result.IsOriginAllowed);
}
[Fact]
public void EvaluatePolicy_EmptyOriginsPolicy_ReturnsInvalidResult()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
@@ -55,15 +54,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Null(result.AllowedOrigin);
- Assert.False(result.VaryByOrigin);
+ Assert.False(result.IsOriginAllowed);
}
[Fact]
public void EvaluatePolicy_IsOriginAllowedReturnsFalse_ReturnsInvalidResult()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy()
{
@@ -75,15 +73,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Null(result.AllowedOrigin);
- Assert.False(result.VaryByOrigin);
+ Assert.False(result.IsOriginAllowed);
}
[Fact]
- public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsWildcardForOrigin()
+ public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsOriginHeader()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy
@@ -101,10 +98,10 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
}
[Fact]
- public void EvaluatePolicy_AllowAnyOrigin_SupportsCredentials_AddsSpecificOrigin()
+ public void EvaluatePolicy_AllowAnyOrigin_AddsAnyOrigin()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy
{
@@ -116,15 +113,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Equal("http://example.com", result.AllowedOrigin);
- Assert.True(result.VaryByOrigin);
+ Assert.Equal("*", result.AllowedOrigin);
}
[Fact]
public void EvaluatePolicy_DoesNotSupportCredentials_AllowCredentialsReturnsFalse()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy
{
@@ -143,7 +139,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_SupportsCredentials_AllowCredentialsReturnsTrue()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy
{
@@ -158,11 +154,84 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.True(result.SupportsCredentials);
}
+ [Fact]
+ public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportsCredentials_DoesNotVaryByOrigin()
+ {
+ // Arrange
+ var corsService = GetCorsService();
+ var requestContext = GetHttpContext(origin: "http://example.com");
+ var policy = new CorsPolicy();
+ policy.Origins.Add(CorsConstants.AnyOrigin);
+
+ // Act
+ var result = corsService.EvaluatePolicy(requestContext, policy);
+
+ // Assert
+ Assert.Equal("*", result.AllowedOrigin);
+ Assert.False(result.VaryByOrigin);
+ }
+
+ [Fact]
+ public void EvaluatePolicy_AllowAnyOrigin_SupportsCredentials_DoesNotVaryByOrigin()
+ {
+ // Arrange
+ var corsService = GetCorsService();
+ var requestContext = GetHttpContext(origin: "http://example.com");
+ var policy = new CorsPolicy
+ {
+ SupportsCredentials = true
+ };
+ policy.Origins.Add(CorsConstants.AnyOrigin);
+
+ // Act
+ var result = corsService.EvaluatePolicy(requestContext, policy);
+
+ // Assert
+ Assert.Equal("*", result.AllowedOrigin);
+ Assert.True(result.SupportsCredentials);
+ Assert.True(result.VaryByOrigin);
+ }
+
+ [Fact]
+ public void EvaluatePolicy_AllowOneOrigin_DoesNotVaryByOrigin()
+ {
+ // Arrange
+ var corsService = GetCorsService();
+ var requestContext = GetHttpContext(origin: "http://example.com");
+ var policy = new CorsPolicy();
+ policy.Origins.Add("http://example.com");
+
+ // Act
+ var result = corsService.EvaluatePolicy(requestContext, policy);
+
+ // Assert
+ Assert.Equal("http://example.com", result.AllowedOrigin);
+ Assert.False(result.VaryByOrigin);
+ }
+
+ [Fact]
+ public void EvaluatePolicy_AllowMultipleOrigins_VariesByOrigin()
+ {
+ // Arrange
+ var corsService = GetCorsService();
+ var requestContext = GetHttpContext(origin: "http://example.com");
+ var policy = new CorsPolicy();
+ policy.Origins.Add("http://example.com");
+ policy.Origins.Add("http://api.example.com");
+
+ // Act
+ var result = corsService.EvaluatePolicy(requestContext, policy);
+
+ // Assert
+ Assert.Equal("http://example.com", result.AllowedOrigin);
+ Assert.True(result.VaryByOrigin);
+ }
+
[Fact]
public void EvaluatePolicy_NoExposedHeaders_NoAllowExposedHeaders()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -178,7 +247,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_OneExposedHeaders_HeadersAllowed()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -188,15 +257,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Equal(1, result.AllowedExposedHeaders.Count);
- Assert.Contains("foo", result.AllowedExposedHeaders);
+ Assert.Equal(new[] { "foo" }, result.AllowedExposedHeaders);
}
[Fact]
public void EvaluatePolicy_ManyExposedHeaders_HeadersAllowed()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -208,17 +276,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Equal(3, result.AllowedExposedHeaders.Count);
- Assert.Contains("foo", result.AllowedExposedHeaders);
- Assert.Contains("bar", result.AllowedExposedHeaders);
- Assert.Contains("baz", result.AllowedExposedHeaders);
+ Assert.Equal(new[] { "foo", "bar", "baz" }, result.AllowedExposedHeaders);
}
[Fact]
- public void EvaluatePolicy_PreflightRequest_MethodNotAllowed_ReturnsInvalidResult()
+ public void EvaluatePolicy_PreflightRequest_MethodNotAllowed()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -228,14 +293,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Empty(result.AllowedMethods);
+ Assert.Equal(new[] { "GET" }, result.AllowedMethods);
}
[Fact]
public void EvaluatePolicy_PreflightRequest_MethodAllowed_ReturnsAllowMethods()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -246,168 +311,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Assert
Assert.NotNull(result);
- Assert.Contains("PUT", result.AllowedMethods);
- }
-
- public static TheoryData PreflightRequests_LoggingData
- {
- get
- {
- return new TheoryData
- {
- {
- new LogData {
- Origin = "http://example.com",
- Method = "PUT",
- Headers = null,
- OriginLogMessage = "The request has an origin header: 'http://example.com'.",
- PolicyLogMessage = "CORS policy execution failed.",
- FailureReason = "Request origin http://example.com does not have permission to access the resource."
- }
- },
- {
- new LogData {
- Origin = "http://allowed.example.com",
- Method = "DELETE",
- Headers = null,
- OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
- PolicyLogMessage = "CORS policy execution failed.",
- FailureReason = "Request method DELETE not allowed in CORS policy."
- }
- },
- {
- new LogData {
- Origin = "http://allowed.example.com",
- Method = "PUT",
- Headers = new[] { "test" },
- OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
- PolicyLogMessage = "CORS policy execution failed.",
- FailureReason = "Request header 'test' not allowed in CORS policy."
- }
- },
- };
- }
- }
-
- [Theory]
- [MemberData(nameof(PreflightRequests_LoggingData))]
- public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicyFailed(LogData logData)
- {
- var sink = new TestSink();
- var loggerFactory = new TestLoggerFactory(sink, enabled: true);
-
- var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
- var requestContext = GetHttpContext(method: "OPTIONS", origin: logData.Origin, accessControlRequestMethod: logData.Method, accessControlRequestHeaders: logData.Headers);
- var policy = new CorsPolicy();
- policy.Origins.Add("http://allowed.example.com");
- policy.Methods.Add("PUT");
-
- // Act
- var result = corsService.EvaluatePolicy(requestContext, policy);
-
- var writeList = sink.Writes.ToList();
- Assert.Equal("The request is a preflight request.", writeList[0].State.ToString());
- Assert.Equal(logData.OriginLogMessage, writeList[1].State.ToString());
- Assert.Equal(logData.PolicyLogMessage, writeList[2].State.ToString());
- Assert.Equal(logData.FailureReason, writeList[3].State.ToString());
- }
-
- [Fact]
- public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicySucceeded()
- {
- var sink = new TestSink();
- var loggerFactory = new TestLoggerFactory(sink, enabled: true);
-
- var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
- var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://allowed.example.com", accessControlRequestMethod: "PUT");
- var policy = new CorsPolicy();
- policy.Origins.Add("http://allowed.example.com");
- policy.Methods.Add("PUT");
-
- // Act
- var result = corsService.EvaluatePolicy(requestContext, policy);
-
- var writeList = sink.Writes.ToList();
- Assert.Equal("The request is a preflight request.", writeList[0].State.ToString());
- Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[1].State.ToString());
- Assert.Equal("CORS policy execution successful.", writeList[2].State.ToString());
- }
-
- [Fact]
- public void EvaluatePolicy_LoggingForPreflightRequests_DoesNotHaveOriginHeader()
- {
- var sink = new TestSink();
- var loggerFactory = new TestLoggerFactory(sink, enabled: true);
-
- var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
- var requestContext = GetHttpContext(method: "OPTIONS", origin: null, accessControlRequestMethod: "PUT");
- var policy = new CorsPolicy();
- policy.Origins.Add("http://allowed.example.com");
- policy.Methods.Add("PUT");
-
- // Act
- var result = corsService.EvaluatePolicy(requestContext, policy);
-
- var writeList = sink.Writes.ToList();
- Assert.Equal("The request is a preflight request.", writeList[0].State.ToString());
- Assert.Equal("The request does not have an origin header.", writeList[1].State.ToString());
- }
-
- [Fact]
- public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicyFailed()
- {
- var sink = new TestSink();
- var loggerFactory = new TestLoggerFactory(sink, enabled: true);
-
- var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
- var requestContext = GetHttpContext(origin: "http://example.com");
- var policy = new CorsPolicy();
- policy.Origins.Add("http://allowed.example.com");
-
- // Act
- var result = corsService.EvaluatePolicy(requestContext, policy);
-
- var writeList = sink.Writes.ToList();
- Assert.Equal("The request has an origin header: 'http://example.com'.", writeList[0].State.ToString());
- Assert.Equal("CORS policy execution failed.", writeList[1].State.ToString());
- Assert.Equal("Request origin http://example.com does not have permission to access the resource.", writeList[2].State.ToString());
- }
-
- [Fact]
- public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicySucceeded()
- {
- var sink = new TestSink();
- var loggerFactory = new TestLoggerFactory(sink, enabled: true);
-
- var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
- var requestContext = GetHttpContext(origin: "http://allowed.example.com");
- var policy = new CorsPolicy();
- policy.Origins.Add("http://allowed.example.com");
-
- // Act
- var result = corsService.EvaluatePolicy(requestContext, policy);
-
- var writeList = sink.Writes.ToList();
- Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[0].State.ToString());
- Assert.Equal("CORS policy execution successful.", writeList[1].State.ToString());
- }
-
- [Fact]
- public void EvaluatePolicy_LoggingForNonPreflightRequests_DoesNotHaveOriginHeader()
- {
- var sink = new TestSink();
- var loggerFactory = new TestLoggerFactory(sink, enabled: true);
-
- var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
- var requestContext = GetHttpContext(origin: null);
- var policy = new CorsPolicy();
- policy.Origins.Add("http://allowed.example.com");
-
- // Act
- var result = corsService.EvaluatePolicy(requestContext, policy);
-
- var logMessage = Assert.Single(sink.Writes);
- Assert.Equal("The request does not have an origin header.", logMessage.State.ToString());
+ Assert.Equal(new[] { "PUT" }, result.AllowedMethods);
}
[Theory]
@@ -416,7 +320,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_CaseInsensitivePreflightRequest_OriginAllowed_ReturnsOrigin(string preflightMethod)
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(
method: preflightMethod,
origin: "http://example.com",
@@ -437,7 +341,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_PreflightRequest_IsOriginAllowedReturnsTrue_ReturnsOrigin()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(
method: "OPTIONS",
origin: "http://example.com",
@@ -459,7 +363,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_PreflightRequest_SupportsCredentials_AllowCredentialsReturnsTrue()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy
{
@@ -479,7 +383,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_PreflightRequest_NoPreflightMaxAge_NoPreflightMaxAgeSet()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy
{
@@ -499,7 +403,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_PreflightRequest_PreflightMaxAge_PreflightMaxAgeSet()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy
{
@@ -519,7 +423,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_PreflightRequest_AnyMethod_ReturnsRequestMethod()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "GET");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -529,17 +433,16 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Equal(1, result.AllowedMethods.Count);
- Assert.Contains("GET", result.AllowedMethods);
+ Assert.Equal(new[] { "*" }, result.AllowedMethods);
}
[Theory]
[InlineData("Put")]
[InlineData("PUT")]
- public void EvaluatePolicy_CaseInsensitivePreflightRequest_ListedMethod_ReturnsSubsetOfListedMethods(string method)
+ public void EvaluatePolicy_CaseInsensitivePreflightRequest_ReturnsAllowedMethods(string method)
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(
method: "OPTIONS",
origin: "http://example.com",
@@ -553,15 +456,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Equal(1, result.AllowedMethods.Count);
- Assert.Contains(method, result.AllowedMethods);
+ Assert.Equal(new[] { "PUT", "DELETE" }, result.AllowedMethods);
}
[Fact]
- public void EvaluatePolicy_PreflightRequest_NoHeadersRequested_AllowedAllHeaders_ReturnsEmptyHeaders()
+ public void EvaluatePolicy_PreflightRequest_NoHeadersRequested_AllowedAllHeaders()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin);
@@ -572,14 +474,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Empty(result.AllowedHeaders);
+ Assert.Equal(new[] { "*" }, result.AllowedHeaders);
+ Assert.Equal(new[] { "*" }, result.AllowedMethods);
}
[Fact]
- public void EvaluatePolicy_PreflightRequest_HeadersRequested_AllowAllHeaders_ReturnsRequestedHeaders()
+ public void EvaluatePolicy_PreflightRequest_AllowAllHeaders()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(
method: "OPTIONS",
origin: "http://example.com",
@@ -589,21 +492,21 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
policy.Origins.Add(CorsConstants.AnyOrigin);
policy.Methods.Add("*");
policy.Headers.Add("*");
+ policy.SupportsCredentials = true;
// Act
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Equal(2, result.AllowedHeaders.Count);
- Assert.Contains("foo", result.AllowedHeaders);
- Assert.Contains("bar", result.AllowedHeaders);
+ Assert.Equal(new[] { "*" }, result.AllowedHeaders);
+ Assert.Equal(new[] { "*" }, result.AllowedMethods);
}
-
+
[Fact]
public void EvaluatePolicy_PreflightRequest_HeadersRequested_NotAllHeaderMatches_ReturnsInvalidResult()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(
method: "OPTIONS",
origin: "http://example.com",
@@ -619,76 +522,30 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Empty(result.AllowedHeaders);
- Assert.Empty(result.AllowedMethods);
- Assert.Empty(result.AllowedExposedHeaders);
- Assert.Null(result.AllowedOrigin);
+ Assert.Equal(new[] { "match", "foo" }, result.AllowedHeaders);
+ Assert.Equal(new[] { "*" }, result.AllowedMethods);
}
[Fact]
- public void EvaluatePolicy_DoesCaseSensitiveComparison()
+ public void EvaluatePolicy_PreflightRequest_WithCredentials_ReturnsWildCard()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
-
+ var corsService = GetCorsService();
+ var httpContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT");
var policy = new CorsPolicy();
- policy.Methods.Add("POST");
- var httpContext = GetHttpContext(origin: null, accessControlRequestMethod: "post");
+ policy.Origins.Add(CorsConstants.AnyOrigin);
+ policy.Methods.Add("*");
+ policy.Headers.Add("*");
+ policy.SupportsCredentials = true;
// Act
var result = corsService.EvaluatePolicy(httpContext, policy);
// Assert
- Assert.Empty(result.AllowedHeaders);
- Assert.Empty(result.AllowedMethods);
- Assert.Empty(result.AllowedExposedHeaders);
- Assert.Null(result.AllowedOrigin);
- }
-
- [Fact]
- public void TryValidateOrigin_DoesCaseSensitiveComparison()
- {
- // Arrange
- var corsService = new CorsService(new TestCorsOptions());
-
- var policy = new CorsPolicy();
- policy.Origins.Add("http://Example.com");
- var httpContext = GetHttpContext(origin: "http://example.com");
-
- // Act
- var result = corsService.EvaluatePolicy(httpContext, policy);
-
- // Assert
- Assert.Empty(result.AllowedHeaders);
- Assert.Empty(result.AllowedMethods);
- Assert.Empty(result.AllowedExposedHeaders);
- Assert.Null(result.AllowedOrigin);
- }
-
- [Fact]
- public void ApplyResult_SimpleRequests_IgnoresFiltering()
- {
- // Arrange
- var result = new CorsResult();
- result.AllowedHeaders.Add("Content-Type");
- result.AllowedHeaders.Add("Date");
- result.AllowedMethods.Add("GET");
- result.AllowedMethods.Add("PUT");
-
- var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
-
-
- // Act
- service.ApplyResult(result, httpContext.Response);
-
- // Assert
- string[] arMethods = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods);
- Assert.Contains("GET", arMethods);
- Assert.Contains("PUT", arMethods);
- string[] arHeaders = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders);
- Assert.Contains("Content-Type", arHeaders);
- Assert.Contains("Date", arHeaders);
+ Assert.NotNull(result);
+ Assert.Equal(new[] { "*" }, result.AllowedMethods);
+ Assert.Equal(new[] { "*" }, result.AllowedHeaders);
+ Assert.True(result.SupportsCredentials);
}
[Fact]
@@ -697,7 +554,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult();
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -712,11 +569,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult
{
+ IsOriginAllowed = true,
AllowedOrigin = "http://example.com"
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -731,11 +589,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult
{
+ IsOriginAllowed = true,
AllowedOrigin = null
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -750,10 +609,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult
{
+ IsOriginAllowed = true,
SupportsCredentials = true
};
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
var httpContext = new DefaultHttpContext();
@@ -769,11 +629,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult
{
+ IsOriginAllowed = true,
VaryByOrigin = true
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -782,17 +643,39 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.Equal("Origin", httpContext.Response.Headers["Vary"]);
}
+ [Fact]
+ public void ApplyResult_AppendsVaryHeader()
+ {
+ // Arrange
+ var result = new CorsResult
+ {
+ IsOriginAllowed = true,
+ VaryByOrigin = true
+ };
+
+ var httpContext = new DefaultHttpContext();
+ httpContext.Response.Headers["Vary"] = "Cookie";
+ var service = GetCorsService();
+
+ // Act
+ service.ApplyResult(result, httpContext.Response);
+
+ // Assert
+ Assert.Equal("Cookie,Origin", httpContext.Response.Headers["Vary"]);
+ }
+
[Fact]
public void ApplyResult_NoAllowCredentials_AllowCredentialsHeaderNotAdded()
{
// Arrange
var result = new CorsResult
{
+ IsOriginAllowed = true,
SupportsCredentials = false
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -807,11 +690,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult
{
+ IsOriginAllowed = true,
// AllowMethods is empty by default
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -824,11 +708,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void ApplyResult_OneAllowMethods_AllowMethodsHeaderAdded()
{
// Arrange
- var result = new CorsResult();
- result.AllowedMethods.Add("PUT");
+ var result = new CorsResult
+ {
+ IsOriginAllowed = true,
+ IsPreflightRequest = true,
+ AllowedMethods = { "PUT" }
+ };
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -836,6 +724,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Assert
Assert.Equal("PUT", httpContext.Response.Headers["Access-Control-Allow-Methods"]);
}
+
[Fact]
public void ApplyResult_NoAllowHeaders_AllowHeadersHeaderNotAdded()
{
@@ -843,10 +732,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = new CorsResult
{
// AllowHeaders is empty by default
+ IsOriginAllowed = true,
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -859,11 +749,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void ApplyResult_OneAllowHeaders_AllowHeadersHeaderAdded()
{
// Arrange
- var result = new CorsResult();
- result.AllowedHeaders.Add("foo");
+ var result = new CorsResult
+ {
+ IsOriginAllowed = true,
+ IsPreflightRequest = true,
+ AllowedHeaders = { "foo" }
+ };
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -872,32 +766,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.Equal("foo", httpContext.Response.Headers["Access-Control-Allow-Headers"]);
}
- [Fact]
- public void ApplyResult_ManyAllowHeaders_AllowHeadersHeaderAdded()
- {
- // Arrange
- var result = new CorsResult();
- result.AllowedHeaders.Add("foo");
- result.AllowedHeaders.Add("bar");
- result.AllowedHeaders.Add("baz");
- var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
-
- // Act
- service.ApplyResult(result, httpContext.Response);
-
- // Assert
- Assert.Contains("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys);
- var value = Assert.Single(httpContext.Response.Headers.Values);
- Assert.Equal(new[] { "foo,bar,baz" }, value);
- string[] headerValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Headers");
- Assert.Equal(3, headerValues.Length);
- Assert.Contains("foo", headerValues);
- Assert.Contains("bar", headerValues);
- Assert.Contains("baz", headerValues);
- }
-
[Fact]
public void ApplyResult_NoAllowExposedHeaders_ExposedHeadersHeaderNotAdded()
{
@@ -905,10 +774,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = new CorsResult
{
// AllowExposedHeaders is empty by default
+ IsOriginAllowed = true,
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -917,15 +787,61 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.DoesNotContain("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys);
}
+ [Fact]
+ public void ApplyResult_PreflightRequest_ExposesHeadersNotAdded()
+ {
+ // Arrange
+ var result = new CorsResult
+ {
+ IsOriginAllowed = true,
+ IsPreflightRequest = true,
+ AllowedExposedHeaders = { "foo", "bar" },
+ };
+
+ var httpContext = new DefaultHttpContext();
+ var service = GetCorsService();
+
+ // Act
+ service.ApplyResult(result, httpContext.Response);
+
+ // Assert
+ Assert.DoesNotContain("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys);
+ }
+
+ [Fact]
+ public void ApplyResult_NoPreflightRequest_ExposesHeadersAdded()
+ {
+ // Arrange
+ var result = new CorsResult
+ {
+ IsOriginAllowed = true,
+ IsPreflightRequest = false,
+ AllowedExposedHeaders = { "foo", "bar" },
+ };
+
+ var httpContext = new DefaultHttpContext();
+ var service = GetCorsService();
+
+ // Act
+ service.ApplyResult(result, httpContext.Response);
+
+ // Assert
+ Assert.Equal("foo,bar", httpContext.Response.Headers[CorsConstants.AccessControlExposeHeaders]);
+ }
+
+
[Fact]
public void ApplyResult_OneAllowExposedHeaders_ExposedHeadersHeaderAdded()
{
// Arrange
- var result = new CorsResult();
- result.AllowedExposedHeaders.Add("foo");
+ var result = new CorsResult
+ {
+ IsOriginAllowed = true,
+ AllowedExposedHeaders = { "foo" },
+ };
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -934,43 +850,19 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.Equal("foo", httpContext.Response.Headers["Access-Control-Expose-Headers"]);
}
- [Fact]
- public void ApplyResult_ManyAllowExposedHeaders_ExposedHeadersHeaderAdded()
- {
- // Arrange
- var result = new CorsResult();
- result.AllowedExposedHeaders.Add("foo");
- result.AllowedExposedHeaders.Add("bar");
- result.AllowedExposedHeaders.Add("baz");
-
- var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
-
- // Act
- service.ApplyResult(result, httpContext.Response);
-
- // Assert
- Assert.Contains("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys);
- var value = Assert.Single(httpContext.Response.Headers.Values);
- Assert.Equal(new[] { "foo,bar,baz" }, value);
- string[] exposedHeaderValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Expose-Headers");
- Assert.Equal(3, exposedHeaderValues.Length);
- Assert.Contains("foo", exposedHeaderValues);
- Assert.Contains("bar", exposedHeaderValues);
- Assert.Contains("baz", exposedHeaderValues);
- }
-
[Fact]
public void ApplyResult_NoPreflightMaxAge_MaxAgeHeaderNotAdded()
{
// Arrange
var result = new CorsResult
{
- PreflightMaxAge = null
+ IsOriginAllowed = true,
+ IsPreflightRequest = false,
+ PreflightMaxAge = TimeSpan.FromSeconds(30),
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -985,10 +877,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Arrange
var result = new CorsResult
{
- PreflightMaxAge = TimeSpan.FromSeconds(30)
+ IsOriginAllowed = true,
+ IsPreflightRequest = true,
+ PreflightMaxAge = TimeSpan.FromSeconds(30),
};
var httpContext = new DefaultHttpContext();
- var service = new CorsService(new TestCorsOptions());
+ var service = GetCorsService();
// Act
service.ApplyResult(result, httpContext.Response);
@@ -1001,7 +895,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_MultiOriginsPolicy_ReturnsVaryByOriginHeader()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
policy.Origins.Add("http://example.com");
@@ -1019,7 +913,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void EvaluatePolicy_MultiOriginsPolicy_NoMatchingOrigin_ReturnsInvalidResult()
{
// Arrange
- var corsService = new CorsService(new TestCorsOptions());
+ var corsService = GetCorsService();
var requestContext = GetHttpContext(origin: "http://example.com");
var policy = new CorsPolicy();
policy.Origins.Add("http://example-two.com");
@@ -1029,10 +923,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var result = corsService.EvaluatePolicy(requestContext, policy);
// Assert
- Assert.Null(result.AllowedOrigin);
- Assert.False(result.VaryByOrigin);
+ Assert.False(result.IsOriginAllowed);
}
+ private static CorsService GetCorsService(CorsOptions options = null)
+ {
+ options = options ?? new CorsOptions();
+ return new CorsService(Options.Create(options), NullLoggerFactory.Instance);
+ }
private static HttpContext GetHttpContext(
string method = null,
@@ -1064,15 +962,5 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
return context;
}
-
- public class LogData
- {
- public string Origin { get; set; }
- public string Method { get; set; }
- public string[] Headers { get; set; }
- public string OriginLogMessage { get; set; }
- public string PolicyLogMessage { get; set; }
- public string FailureReason { get; set; }
- }
}
}
diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs
deleted file mode 100644
index aa698c62f2..0000000000
--- a/test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-using System.Net.Http;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.TestHost;
-
-namespace Microsoft.AspNetCore.Cors.Infrastructure
-{
- public class CorsTestFixture : IDisposable
- where TStartup : class
- {
- private readonly TestServer _server;
-
- public CorsTestFixture()
- {
- var builder = new WebHostBuilder().UseStartup();
- _server = new TestServer(builder);
-
- Client = _server.CreateClient();
- Client.BaseAddress = new Uri("http://localhost");
- }
-
- public HttpClient Client { get; }
-
- public void Dispose()
- {
- Client.Dispose();
- _server.Dispose();
- }
- }
-}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs b/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs
index d66b0e5653..e3764bc84e 100644
--- a/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs
+++ b/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs
@@ -3,6 +3,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.Cors.Infrastructure
@@ -17,10 +18,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var policy = new CorsPolicy();
options.AddPolicy(options.DefaultPolicyName, policy);
- var corsOptions = new TestCorsOptions
- {
- Value = options
- };
+ var corsOptions = Options.Create(options);
var policyProvider = new DefaultCorsPolicyProvider(corsOptions);
// Act
@@ -40,10 +38,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var policy = new CorsPolicy();
options.AddPolicy(policyName, policy);
- var corsOptions = new TestCorsOptions
- {
- Value = options
- };
+ var corsOptions = Options.Create(options);
var policyProvider = new DefaultCorsPolicyProvider(corsOptions);
// Act
diff --git a/test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs b/test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs
deleted file mode 100644
index 782ebb2db7..0000000000
--- a/test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using Microsoft.Extensions.Options;
-
-namespace Microsoft.AspNetCore.Cors.Infrastructure
-{
- public class TestCorsOptions : IOptions
- {
- public CorsOptions Value { get; set; }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs b/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs
index ac04cfc3fd..7b28d6aa64 100644
--- a/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs
+++ b/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void TestIsSubdomainOf(Uri subdomain, Uri domain)
{
// Act
- bool isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain);
+ var isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain);
// Assert
Assert.True(isSubdomain);
@@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
public void TestIsSubdomainOf_ReturnsFalse_WhenNotSubdomain(Uri subdomain, Uri domain)
{
// Act
- bool isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain);
+ var isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain);
// Assert
Assert.False(isSubdomain);