From 04e178100d1cc7fa728efdb4fd4507c972bd30b9 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 01:18:33 +0600 Subject: [PATCH 01/24] Added HTTPS support for WebSPA, WebMVC and Identity.API Apps in the docker container --- docker-compose.override.yml | 49 +++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 969cfb922..5049d39a5 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -30,11 +30,11 @@ services: identity.api: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104 + - ASPNETCORE_URLS=http://0.0.0.0:80;https://+:443 + - SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104;https://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:4104 - XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback #localhost do not work for UWP login, so we have to use "external" IP always - ConnectionString=${ESHOP_AZURE_IDENTITY_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word} - - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100 #Local: You need to open your local dev-machine firewall at range 5100-5110. + - MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100;https://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:4100 #Local: You need to open your local dev-machine firewall at range 5100-5110. - LocationApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109 - MarketingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110 - BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103 @@ -45,7 +45,11 @@ services: - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} ports: - - "5105:80" + - "5105:80" + - "4105:443" + volumes: + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw basket.api: environment: @@ -186,42 +190,59 @@ services: mobileshoppingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - - "5200:80" + - "5200:80" volumes: + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ./src/ApiGateways/Mobile.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} mobilemarketingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - "5201:80" volumes: + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ./src/ApiGateways/Mobile.Bff.Marketing/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} webshoppingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://+:80;https://+:443 + #- ASPNETCORE_URLS=http://0.0.0.0:80 + - ASPNETCORE_HTTPS_PORT=4202 + - ASPNETCORE_Kestrel__Certificates__Development__Password="RH@ssl2018" - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - - "5202:80" + - "5202:80" + - "4202:443" volumes: - - ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw + - ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}:rw webmarketingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - "5203:80" volumes: + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ./src/ApiGateways/Web.Bff.Marketing/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} mobileshoppingagg: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 - urls__basket=http://basket.api - urls__catalog=http://catalog.api - urls__orders=http://ordering.api @@ -233,6 +254,7 @@ services: webshoppingagg: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 - urls__basket=http://basket.api - urls__catalog=http://catalog.api - urls__orders=http://ordering.api @@ -277,7 +299,7 @@ services: webspa: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 + - ASPNETCORE_URLS=http://+:80;https://+:443 - IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202 - MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5203 @@ -293,11 +315,15 @@ services: - SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202 ports: - "5104:80" + - "4104:443" + volumes: + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw webmvc: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 + - ASPNETCORE_URLS=http://+:80;https://+:443 - PurchaseUrl=http://webshoppingapigw - IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. - MarketingUrl=http://webmarketingapigw @@ -314,4 +340,7 @@ services: - UseLoadTest=${USE_LOADTEST:-False} ports: - "5100:80" - + - "4100:443" + volumes: + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw From 04e754aabc897d49aec863a7df0b1c31bfeee4b4 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 01:22:59 +0600 Subject: [PATCH 02/24] Change startup page to unsecured endpoint to HTTPS endpoint --- docker-compose.dcproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.dcproj b/docker-compose.dcproj index 296c4b5e0..0a5eabea4 100644 --- a/docker-compose.dcproj +++ b/docker-compose.dcproj @@ -3,7 +3,7 @@ fea0c318-ffed-4d39-8781-265718ca43dd True - http://localhost:5100 + https://localhost:4100 webmvc Linux 2.1 From 568a092699828c396b94cfade57d1f70f40bdde7 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 01:25:20 +0600 Subject: [PATCH 03/24] Removed environment variables and volumes from api gateway and Aggregator projects from docker compose file --- docker-compose.override.yml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 5049d39a5..d17430bb4 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -190,59 +190,42 @@ services: mobileshoppingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - "5200:80" volumes: - - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro - - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ./src/ApiGateways/Mobile.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} mobilemarketingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - "5201:80" volumes: - - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro - - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ./src/ApiGateways/Mobile.Bff.Marketing/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} webshoppingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://+:80;https://+:443 - #- ASPNETCORE_URLS=http://0.0.0.0:80 - - ASPNETCORE_HTTPS_PORT=4202 - - ASPNETCORE_Kestrel__Certificates__Development__Password="RH@ssl2018" - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - "5202:80" - - "4202:443" volumes: - - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw - - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:rw - - ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}:rw + - ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} webmarketingapigw: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110. ports: - "5203:80" volumes: - - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:rw - - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - ./src/ApiGateways/Web.Bff.Marketing/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration} mobileshoppingagg: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - urls__basket=http://basket.api - urls__catalog=http://catalog.api - urls__orders=http://ordering.api @@ -254,7 +237,6 @@ services: webshoppingagg: environment: - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://0.0.0.0:80 - urls__basket=http://basket.api - urls__catalog=http://catalog.api - urls__orders=http://ordering.api From e73b25b2e825e7c01dd76734b76a8649e38bfdf7 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 01:50:50 +0600 Subject: [PATCH 04/24] a. Added RuntimeFrameworkVersion and set it to 2.1.3 b. Updated NuGet References to support ASP.NET Core 2.1.3 1. Microsoft.ApplicationInsights.AspNetCore 2.2.1->2.4.1 2. Microsoft.ApplicationInsights.DependencyCollector 2.6.1-> 2.7.2 3. Microsoft.ApplicationInsights.ServiceFabric 2.1.1-beta1->2.1.1 4. Microsoft.Extensions.Logging.AzureAppServices 2.1.0-> 2.1.1 5. Microsoft.AspNetCore.App 2.1.0->2.1.3 6. Microsoft.VisualStudio.Azure.Fabric.MSBuild 1.6.5->1.6.7 c. Updated NuGet packages 1. BuildBundleMinifier 2.6.375->2.8.391 2. Microsoft.ApplicationInsights.Kubernetes 1.0.0-beta8->1.0.0-beta9 3. Microsoft.Extensions.Http.Polly 2.1.0->2.1.1 4. Microsoft.AspNetCore.DataProtection.Redis 0.3.3->0.4.1 d. Added NuGet packages 1. Microsoft.VisualStudio.Web.CodeGeneration.Design 2.1.3 e. Removed CLIToolReference from the project file --- src/Web/WebMVC/WebMVC.csproj | 94 ++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj index 0cd7ec19b..368f35911 100644 --- a/src/Web/WebMVC/WebMVC.csproj +++ b/src/Web/WebMVC/WebMVC.csproj @@ -1,52 +1,50 @@  - - netcoreapp2.1 - aspnet-Microsoft.eShopOnContainers-946ae052-8305-4a99-965b-ec8636ddbae3 - ..\..\..\docker-compose.dcproj - - - - - PreserveNewest - PreserveNewest - - - PreserveNewest - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + netcoreapp2.1 + 2.1.3 + aspnet-Microsoft.eShopOnContainers-946ae052-8305-4a99-965b-ec8636ddbae3 + ..\..\..\docker-compose.dcproj + + + + + PreserveNewest + PreserveNewest + + + PreserveNewest + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ac8fdabe5df456e8d46612e399861c68c1d55ac5 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 01:56:09 +0600 Subject: [PATCH 05/24] 1. Specified SSL port 2. Use 64bit IIS Express Bitness 3. Specified applicationUrl for Kestrel startup --- src/Web/WebMVC/Properties/launchSettings.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Web/WebMVC/Properties/launchSettings.json b/src/Web/WebMVC/Properties/launchSettings.json index bf529db40..813c84de0 100644 --- a/src/Web/WebMVC/Properties/launchSettings.json +++ b/src/Web/WebMVC/Properties/launchSettings.json @@ -4,23 +4,25 @@ "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:5100", - "sslPort": 0 + "sslPort": 4100 } }, "profiles": { "IIS Express": { "commandName": "IISExpress", + "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "use64Bit": true }, "Microsoft.eShopOnContainers.WebMVC": { "commandName": "Project", - "launchBrowser": true, - "launchUrl": "http://localhost:5000", + "launchUrl": "/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "applicationUrl": "https://localhost:4001;http://localhost:5001" } } } \ No newline at end of file From 69e91a5ba7f2c61a6e477825fb246a3e5149191c Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:01:15 +0600 Subject: [PATCH 06/24] 1. Added _CookieConsentPartial.cshtml file for cookie privacy policy consent 2. Used "_CookieConsentPartial" partial page into Layout page to support GDPR Cookie private policy --- .../Views/Shared/_CookieConsentPartial.cshtml | 41 +++++++++++++++++++ src/Web/WebMVC/Views/Shared/_Layout.cshtml | 1 + 2 files changed, 42 insertions(+) create mode 100644 src/Web/WebMVC/Views/Shared/_CookieConsentPartial.cshtml diff --git a/src/Web/WebMVC/Views/Shared/_CookieConsentPartial.cshtml b/src/Web/WebMVC/Views/Shared/_CookieConsentPartial.cshtml new file mode 100644 index 000000000..bbfbb09ac --- /dev/null +++ b/src/Web/WebMVC/Views/Shared/_CookieConsentPartial.cshtml @@ -0,0 +1,41 @@ +@using Microsoft.AspNetCore.Http.Features + +@{ + var consentFeature = Context.Features.Get(); + var showBanner = !consentFeature?.CanTrack ?? false; + var cookieString = consentFeature?.CreateConsentCookie(); +} + +@if (showBanner) +{ + + +} \ No newline at end of file diff --git a/src/Web/WebMVC/Views/Shared/_Layout.cshtml b/src/Web/WebMVC/Views/Shared/_Layout.cshtml index 7d932770a..091695d19 100644 --- a/src/Web/WebMVC/Views/Shared/_Layout.cshtml +++ b/src/Web/WebMVC/Views/Shared/_Layout.cshtml @@ -49,6 +49,7 @@ + @RenderBody() From 07a8f8fad8cf986b19eb705d4535efee3bccfccb Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:02:25 +0600 Subject: [PATCH 07/24] Added a privacy controller and view for GDPR Cookie compliance --- src/Web/WebMVC/Controllers/HomeController.cs | 13 +++++++++++++ src/Web/WebMVC/Views/Home/Privacy.cshtml | 6 ++++++ 2 files changed, 19 insertions(+) create mode 100644 src/Web/WebMVC/Controllers/HomeController.cs create mode 100644 src/Web/WebMVC/Views/Home/Privacy.cshtml diff --git a/src/Web/WebMVC/Controllers/HomeController.cs b/src/Web/WebMVC/Controllers/HomeController.cs new file mode 100644 index 000000000..f581da670 --- /dev/null +++ b/src/Web/WebMVC/Controllers/HomeController.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Mvc; + +namespace WebMVC.Controllers +{ + public class HomeController : Controller + { + public IActionResult Privacy() + { + return View(); + } + + } +} \ No newline at end of file diff --git a/src/Web/WebMVC/Views/Home/Privacy.cshtml b/src/Web/WebMVC/Views/Home/Privacy.cshtml new file mode 100644 index 000000000..7bd38619c --- /dev/null +++ b/src/Web/WebMVC/Views/Home/Privacy.cshtml @@ -0,0 +1,6 @@ +@{ + ViewData["Title"] = "Privacy Policy"; +} +

@ViewData["Title"]

+ +

Use this page to detail your site's privacy policy.

From 87034ce8e083146d6feae34ca850f6d4d580154c Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:04:13 +0600 Subject: [PATCH 08/24] 1. Change Launch browser settings 2. Changed Launch URL to HTTPS endpoint --- src/Web/WebMVC/Properties/launchSettings.json | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Web/WebMVC/Properties/launchSettings.json b/src/Web/WebMVC/Properties/launchSettings.json index 813c84de0..5ecfabc11 100644 --- a/src/Web/WebMVC/Properties/launchSettings.json +++ b/src/Web/WebMVC/Properties/launchSettings.json @@ -10,19 +10,18 @@ "profiles": { "IIS Express": { "commandName": "IISExpress", - "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, "use64Bit": true }, - "Microsoft.eShopOnContainers.WebMVC": { - "commandName": "Project", - "launchUrl": "/", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "https://localhost:4001;http://localhost:5001" - } + "Microsoft.eShopOnContainers.WebMVC": { + "commandName": "Project", + "launchUrl": "http://localhost:4001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:4001;http://localhost:5001" + } } } \ No newline at end of file From b0b9045a08b4f4d1eb792e1ef1b6be582f7037a7 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:04:40 +0600 Subject: [PATCH 09/24] Changed coding style --- src/Web/WebMVC/Services/CatalogService.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Web/WebMVC/Services/CatalogService.cs b/src/Web/WebMVC/Services/CatalogService.cs index d4899b453..c4ba9fe3d 100644 --- a/src/Web/WebMVC/Services/CatalogService.cs +++ b/src/Web/WebMVC/Services/CatalogService.cs @@ -45,11 +45,12 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services var responseString = await _httpClient.GetStringAsync(uri); - var items = new List(); - - items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true }); + var items = new List + { + new SelectListItem() { Value = null, Text = "All", Selected = true } + }; - var brands = JArray.Parse(responseString); + var brands = JArray.Parse(responseString); foreach (var brand in brands.Children()) { From 12b1be780e416ad826d336a749e1256f7ba041fa Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:16:00 +0600 Subject: [PATCH 10/24] Used TagHelper instead of Razor to render partial view --- src/Web/WebMVC/Views/Campaigns/Details.cshtml | 42 ++-- src/Web/WebMVC/Views/Campaigns/Index.cshtml | 117 +++++------ src/Web/WebMVC/Views/Cart/Index.cshtml | 14 +- src/Web/WebMVC/Views/Catalog/Index.cshtml | 88 ++++----- src/Web/WebMVC/Views/Order/Create.cshtml | 184 +++++++++--------- src/Web/WebMVC/Views/Order/Detail.cshtml | 141 +++++++------- src/Web/WebMVC/Views/Order/Index.cshtml | 74 +++---- .../WebMVC/Views/OrderManagement/Index.cshtml | 65 ++++--- 8 files changed, 368 insertions(+), 357 deletions(-) diff --git a/src/Web/WebMVC/Views/Campaigns/Details.cshtml b/src/Web/WebMVC/Views/Campaigns/Details.cshtml index 2cb2648b6..56b80d5f0 100644 --- a/src/Web/WebMVC/Views/Campaigns/Details.cshtml +++ b/src/Web/WebMVC/Views/Campaigns/Details.cshtml @@ -1,28 +1,30 @@ @{ - ViewData["Title"] = "Campaign details"; - @model CampaignItem + ViewData["Title"] = "Campaign details"; + var headers = new List
{ + new Header { Controller = "Campaigns", Text = "Back to Campaigns" }, + new Header { Controller = "Catalog", Text = "Back to catalog" } + }; + @model CampaignItem }
-
- -
+
+ +
-@Html.Partial("_Header", new List
() { - new Header() { Controller = "Catalog", Text = "Back to catalog" }, - new Header() { Controller = "Campaigns", Text = "Back to Campaigns" } }) +
-
- Card image cap -
-

@Model.Name

-

@Model.Description

-

- - From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy") - -

-
-
+
+ Card image cap +
+

@Model.Name

+

@Model.Description

+

+ + From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy") + +

+
+
\ No newline at end of file diff --git a/src/Web/WebMVC/Views/Campaigns/Index.cshtml b/src/Web/WebMVC/Views/Campaigns/Index.cshtml index a26c6e9f3..30391ce81 100644 --- a/src/Web/WebMVC/Views/Campaigns/Index.cshtml +++ b/src/Web/WebMVC/Views/Campaigns/Index.cshtml @@ -1,72 +1,75 @@ @{ - ViewData["Title"] = "Campaigns"; -@model WebMVC.ViewModels.CampaignViewModel + ViewData["Title"] = "Campaigns"; + @model WebMVC.ViewModels.CampaignViewModel + var headers = new List
() { +new Header() { Controller = "Catalog", Text = "Back to catalog" } }; }
-
- -
+
+ +
-@Html.Partial("_Header", new List
() { - new Header() { Controller = "Catalog", Text = "Back to catalog" } }) +
-
-
- - @if (!ViewData.ModelState.IsValid) - { -
- @Html.ValidationSummary(false) -
- } +
+
-
-
- UPDATE USER LOCATION -
+ @if (!ViewData.ModelState.IsValid) + { +
+ @Html.ValidationSummary(false) +
+ } -
- - -
-
Lat
- -
+
+
+ UPDATE USER LOCATION +
-
-
Lon
- -
- -
- -
- -
-
-
- @if (Model != null && Model.CampaignItems !=null && Model.CampaignItems.Any()) - { -
- @foreach (var catalogItem in Model.CampaignItems) - { -
- @Html.Partial("_campaign", catalogItem) -
- } -
+
+ - @Html.Partial("_pagination", Model.PaginationInfo) - } - else - { -
- THERE ARE NO CAMPAIGNS -
- } +
+
Lat
+ +
+ +
+
Lon
+ +
+ +
+ +
+
+
+
+
+ @if (Model != null && Model.CampaignItems != null && Model.CampaignItems.Any()) + { +
+ @foreach (var catalogItem in Model.CampaignItems) + { +
+ @*@Html.Partial("_campaign", catalogItem)*@ + +
+ } +
+ + @*@Html.Partial("_pagination", Model.PaginationInfo)*@ + + } + else + { +
+ THERE ARE NO CAMPAIGNS +
+ }
diff --git a/src/Web/WebMVC/Views/Cart/Index.cshtml b/src/Web/WebMVC/Views/Cart/Index.cshtml index d9386a1fd..7fb4d9134 100644 --- a/src/Web/WebMVC/Views/Cart/Index.cshtml +++ b/src/Web/WebMVC/Views/Cart/Index.cshtml @@ -5,14 +5,14 @@ @inject IIdentityParser UserManager @{ - ViewData["Title"] = "My Cart"; + ViewData["Title"] = "My Cart"; + var headers = new List
() { + new Header() { Controller = "Catalog", Text = "Back to catalog" } }; }
-
- @Html.Partial("_Header", new List
() { - new Header() { Controller = "Catalog", Text = "Back to catalog" } }) - - @await Component.InvokeAsync("CartList", new { user = UserManager.Parse(User) }) -
+
+ + @await Component.InvokeAsync("CartList", new { user = UserManager.Parse(User) }) +
diff --git a/src/Web/WebMVC/Views/Catalog/Index.cshtml b/src/Web/WebMVC/Views/Catalog/Index.cshtml index c2ef7f367..cea8226ff 100644 --- a/src/Web/WebMVC/Views/Catalog/Index.cshtml +++ b/src/Web/WebMVC/Views/Catalog/Index.cshtml @@ -1,57 +1,57 @@ @{ - ViewData["Title"] = "Catalog"; - @model Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels.IndexViewModel + ViewData["Title"] = "Catalog"; + @model Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels.IndexViewModel }
-
- -
+
+ +
-
-
- - - -
-
+
+
+ + + +
+
-
-
- @if(ViewBag.BasketInoperativeMsg != null) - { - - } -
+
+
+ @if (ViewBag.BasketInoperativeMsg != null) + { + + } +
- @if (Model.CatalogItems.Count() > 0) - { - @Html.Partial("_pagination", Model.PaginationInfo) + @if (Model.CatalogItems.Count() > 0) + { + -
- @foreach (var catalogItem in Model.CatalogItems) - { -
- @Html.Partial("_product", catalogItem) -
- } -
+
+ @foreach (var catalogItem in Model.CatalogItems) + { +
+ +
+ } +
- @Html.Partial("_pagination", Model.PaginationInfo) - } - else - { -
- THERE ARE NO RESULTS THAT MATCH YOUR SEARCH -
- } + + } + else + { +
+ THERE ARE NO RESULTS THAT MATCH YOUR SEARCH +
+ }
diff --git a/src/Web/WebMVC/Views/Order/Create.cshtml b/src/Web/WebMVC/Views/Order/Create.cshtml index 24a987fa9..b17a02314 100644 --- a/src/Web/WebMVC/Views/Order/Create.cshtml +++ b/src/Web/WebMVC/Views/Order/Create.cshtml @@ -3,103 +3,105 @@ @inject IIdentityParser UserManager @{ - ViewData["Title"] = "New Order"; + ViewData["Title"] = "New Order"; + var header = new Header { Controller = "Cart", Text = "Back to cart" }; } -@Html.Partial("_Header", new List
() { - new Header() { Controller = "Cart", Text = "Back to cart" } }) + +
-
-
-
- @foreach (var error in ViewData.ModelState.Values.SelectMany(err => err.Errors)) { - - } -
-

Shipping address

-
-
-
- - - -
-
-
-
- - - -
-
-
-
- - - -
-
-
-
- - - -
-
-
-
-
-

Payment method

-
-
-
- - - -
-
-
-
- - - -
-
-
-
- - - -
-
-
-
- - - -
-
-
-
+ +
+
+ @foreach (var error in ViewData.ModelState.Values.SelectMany(err => err.Errors)) + { + + } +
+

Shipping address

+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+
+

Payment method

+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
- @await Html.PartialAsync("_OrderItems") + -
-
-
-
-
- -
-
-
- - - +
+
+
+
+
+ +
+
+
+ + +
@section Scripts { - @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} + } diff --git a/src/Web/WebMVC/Views/Order/Detail.cshtml b/src/Web/WebMVC/Views/Order/Detail.cshtml index 810a59559..c123dbd86 100644 --- a/src/Web/WebMVC/Views/Order/Detail.cshtml +++ b/src/Web/WebMVC/Views/Order/Detail.cshtml @@ -3,88 +3,89 @@ @model Microsoft.eShopOnContainers.WebMVC.ViewModels.Order @{ - ViewData["Title"] = "Order Detail"; + ViewData["Title"] = "Order Detail"; + var headers = new List
() { + new Header() { Controller = "Catalog", Text = "Back to catalog" } }; }
- @Html.Partial("_Header", new List
() { - new Header() { Controller = "Catalog", Text = "Back to catalog" } }) + -
-
-
-
Order number
-
Date
-
Total
-
Status
-
+
+
+
+
Order number
+
Date
+
Total
+
Status
+
-
-
@Model.OrderNumber
-
@Model.Date
-
$@Model.Total
-
@Model.Status
-
-
- -
-
-
Description
-
+
+
@Model.OrderNumber
+
@Model.Date
+
$@Model.Total
+
@Model.Status
+
+
-
-
@Model.Description
-
-
+
+
+
Description
+
-
-
-
Shiping address
-
+
+
@Model.Description
+
+
-
-
@Model.Street
-
+
+
+
Shiping address
+
-
-
@Model.City
-
+
+
@Model.Street
+
-
-
@Model.Country
-
-
+
+
@Model.City
+
-
-
-
ORDER DETAILS
-
+
+
@Model.Country
+
+
- @for (int i = 0; i < Model.OrderItems.Count; i++) - { - var item = Model.OrderItems[i]; -
-
- -
-
@item.ProductName
-
$ @item.UnitPrice.ToString("N2")
-
@item.Units
-
$ @Math.Round(item.Units * item.UnitPrice, 2).ToString("N2")
-
- } -
+
+
+
ORDER DETAILS
+
-
-
-
-
TOTAL
-
+ @for (int i = 0; i < Model.OrderItems.Count; i++) + { + var item = Model.OrderItems[i]; +
+
+ +
+
@item.ProductName
+
$ @item.UnitPrice.ToString("N2")
+
@item.Units
+
$ @Math.Round(item.Units * item.UnitPrice, 2).ToString("N2")
+
+ } +
-
-
-
$ @Model.Total
-
-
-
+
+
+
+
TOTAL
+
+ +
+
+
$ @Model.Total
+
+
+
diff --git a/src/Web/WebMVC/Views/Order/Index.cshtml b/src/Web/WebMVC/Views/Order/Index.cshtml index 524219922..6ac9535ac 100644 --- a/src/Web/WebMVC/Views/Order/Index.cshtml +++ b/src/Web/WebMVC/Views/Order/Index.cshtml @@ -3,45 +3,47 @@ @model IEnumerable @{ - ViewData["Title"] = "My Orders"; + ViewData["Title"] = "My Orders"; + var headers = new List
() { +new Header() { Controller = "Catalog", Text = "Back to catalog" }, +new Header() { Text = " / " }, +new Header() { Controller = "OrderManagement", Text = "Orders Management" } +}; }
- @Html.Partial("_Header", new List
() { -new Header() { Controller = "Catalog", Text = "Back to catalog" }, -new Header() { Text = " / " }, -new Header() { Controller = "OrderManagement", Text = "Orders Management" } }) - -
-
-
Order number
-
Date
-
Total
-
Status
-
-
- @if (Model != null && Model.Any()) - { - foreach (var item in Model) - { -
-
@Html.DisplayFor(modelItem => item.OrderNumber)
-
@Html.DisplayFor(modelItem => item.Date)
-
$ @Html.DisplayFor(modelItem => item.Total)
-
@Html.DisplayFor(modelItem => item.Status)
-
- Detail -
-
- @if (item.Status.ToLower() == "submitted") - { - Cancel - } -
-
- } - } -
+ + +
+
+
Order number
+
Date
+
Total
+
Status
+
+
+ @if (Model != null && Model.Any()) + { + foreach (var item in Model) + { +
+
@Html.DisplayFor(modelItem => item.OrderNumber)
+
@Html.DisplayFor(modelItem => item.Date)
+
$ @Html.DisplayFor(modelItem => item.Total)
+
@Html.DisplayFor(modelItem => item.Status)
+
+ Detail +
+
+ @if (item.Status.ToLower() == "submitted") + { + Cancel + } +
+
+ } + } +
diff --git a/src/Web/WebMVC/Views/OrderManagement/Index.cshtml b/src/Web/WebMVC/Views/OrderManagement/Index.cshtml index d108f2281..767d6a1a3 100644 --- a/src/Web/WebMVC/Views/OrderManagement/Index.cshtml +++ b/src/Web/WebMVC/Views/OrderManagement/Index.cshtml @@ -3,41 +3,42 @@ @model IEnumerable @{ - ViewData["Title"] = "My Orders"; + ViewData["Title"] = "My Orders"; + var headers = new List
() { + new Header { Controller = " Catalog", Text="Back to catalog" } }; }
- @Html.Partial("_Header", new List
() { - new Header() { Controller = "Catalog", Text = "Back to catalog" } }) + -
-
-
Order number
-
Date
-
Total
-
Status
-
-
+
+
+
Order number
+
Date
+
Total
+
Status
+
+
- @foreach (var item in Model) - { -
-
@Html.DisplayFor(modelItem => item.OrderNumber)
-
@Html.DisplayFor(modelItem => item.Date)
-
$ @Html.DisplayFor(modelItem => item.Total)
-
@Html.DisplayFor(modelItem => item.Status)
-
-
- - -
-
-
- } -
+ @foreach (var item in Model) + { +
+
@Html.DisplayFor(modelItem => item.OrderNumber)
+
@Html.DisplayFor(modelItem => item.Date)
+
$ @Html.DisplayFor(modelItem => item.Total)
+
@Html.DisplayFor(modelItem => item.Status)
+
+
+ + +
+
+
+ } +
\ No newline at end of file From e901aafc5c194adaac619ad6e6c2bccb7eac0d2e Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:29:19 +0600 Subject: [PATCH 11/24] 1. Configured CookiePolicyOptions to the DI Container (Line 39) and used CookiePolicy MiddleWare (line 76) in order to support GDPR Cookie compliance 2. Set compatibility version to 2.1 according to documentation (line 172) 3. HTTPS Support a. Updated MVC pipeline to support HTTPS and specified port (Line 166-171) b. Configure HTTPS redirection options to the DI (line 51) and used HttpsRedirection MiddleWare (Line 75) c. 4. Used var instead of type (Line 100, 123, 145, 250-252) --- src/Web/WebMVC/Startup.cs | 518 ++++++++++++++++++++------------------ 1 file changed, 269 insertions(+), 249 deletions(-) diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs index 9c1c0a3b8..563431322 100644 --- a/src/Web/WebMVC/Startup.cs +++ b/src/Web/WebMVC/Startup.cs @@ -24,258 +24,278 @@ using WebMVC.Services; namespace Microsoft.eShopOnContainers.WebMVC { - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the IoC container. - public void ConfigureServices(IServiceCollection services) - { - services.AddAppInsight(Configuration) - .AddHealthChecks(Configuration) - .AddCustomMvc(Configuration) - .AddHttpClientServices(Configuration) - //.AddHttpClientLogging(Configuration) //Opt-in HttpClientLogging config - .AddCustomAuthentication(Configuration); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) - { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - - loggerFactory.AddAzureWebAppDiagnostics(); - loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - } - - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) - { - loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); - app.UsePathBase(pathBase); - } + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the IoC container. + public void ConfigureServices(IServiceCollection services) + { + services.Configure(opts => + { + opts.MinimumSameSitePolicy = SameSiteMode.None; + opts.CheckConsentNeeded = context => true; + }); + services + .AddAppInsight(Configuration) + .AddHealthChecks(Configuration) + .AddCustomMvc(Configuration) + .AddHttpClientServices(Configuration) + //.AddHttpClientLogging(Configuration) //Opt-in HttpClientLogging config + .AddCustomAuthentication(Configuration); + services.AddHttpsRedirection(options => + { + options.HttpsPort = 4100; + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Error"); + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseCookiePolicy(); + + string pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); + app.UsePathBase(pathBase); + } #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); + app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - app.UseSession(); - app.UseStaticFiles(); - - if (Configuration.GetValue("UseLoadTest")) - { - app.UseMiddleware(); - } - - app.UseAuthentication(); - - var log = loggerFactory.CreateLogger("identity"); - - WebContextSeed.Seed(app, env, loggerFactory); - - app.UseMvc(routes => - { - routes.MapRoute( - name: "default", - template: "{controller=Catalog}/{action=Index}/{id?}"); - - routes.MapRoute( - name: "defaultError", - template: "{controller=Error}/{action=Error}"); - }); - } - } - - static class ServiceCollectionExtensions - { - - public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) - { - services.AddApplicationInsightsTelemetry(configuration); - var orchestratorType = configuration.GetValue("OrchestratorType"); - - if (orchestratorType?.ToUpper() == "K8S") - { - // Enable K8s telemetry initializer - services.EnableKubernetes(); - } - - if (orchestratorType?.ToUpper() == "SF") - { - // Enable SF telemetry initializer - services.AddSingleton((serviceProvider) => - new FabricTelemetryInitializer()); - } - - return services; - } - - public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) - { - services.AddHealthChecks(checks => - { - var minutes = 1; - if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed)) - { - minutes = minutesParsed; - } - - checks.AddUrlCheck(configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes)); - checks.AddUrlCheck(configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes)); - checks.AddUrlCheck(configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos - checks.AddUrlCheck(configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes)); - checks.AddUrlCheck(configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes)); - }); - - return services; - } - - public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions(); - services.Configure(configuration); - - services.AddMvc(); - - services.AddSession(); - - if (configuration.GetValue("IsClusterEnv") == bool.TrueString) - { - services.AddDataProtection(opts => - { - opts.ApplicationDiscriminator = "eshop.webmvc"; - }) - .PersistKeysToRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys"); - } - return services; - } - - // Adds all Http client services (like Service-Agents) using resilient Http requests based on HttpClient factory and Polly's policies - public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - - //register delegating handlers - services.AddTransient(); - services.AddTransient(); - - //set 5 min as the lifetime for each HttpMessageHandler int the pool - services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5)); - - //add http client services - services.AddHttpClient() - .SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes - .AddHttpMessageHandler() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - services.AddHttpClient() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - services.AddHttpClient() - .AddHttpMessageHandler() - .AddHttpMessageHandler() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - services.AddHttpClient() - .AddHttpMessageHandler() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - services.AddHttpClient() - .AddHttpMessageHandler() - .AddPolicyHandler(GetRetryPolicy()) - .AddPolicyHandler(GetCircuitBreakerPolicy()); - - //add custom application services - services.AddTransient, IdentityParser>(); - - return services; - } - - public static IServiceCollection AddHttpClientLogging(this IServiceCollection services, IConfiguration configuration) - { - services.AddLogging(b => - { - b.AddFilter((category, level) => true); // Spam the world with logs. - - // Add console logger so we can see all the logging produced by the client by default. - b.AddConsole(c => c.IncludeScopes = true); - - // Add console logger - b.AddDebug(); - }); - - return services; - } - - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) - { - var useLoadTest = configuration.GetValue("UseLoadTest"); - var identityUrl = configuration.GetValue("IdentityUrl"); - var callBackUrl = configuration.GetValue("CallBackUrl"); - - // Add Authentication services - - services.AddAuthentication(options => - { - options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; - }) - .AddCookie() - .AddOpenIdConnect(options => - { - options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.Authority = identityUrl.ToString(); - options.SignedOutRedirectUri = callBackUrl.ToString(); - options.ClientId = useLoadTest ? "mvctest" : "mvc"; - options.ClientSecret = "secret"; - options.ResponseType = useLoadTest ? "code id_token token" : "code id_token"; - options.SaveTokens = true; - options.GetClaimsFromUserInfoEndpoint = true; - options.RequireHttpsMetadata = false; - options.Scope.Add("openid"); - options.Scope.Add("profile"); - options.Scope.Add("orders"); - options.Scope.Add("basket"); - options.Scope.Add("marketing"); - options.Scope.Add("locations"); - options.Scope.Add("webshoppingagg"); - options.Scope.Add("orders.signalrhub"); - }); - - return services; - } - - static IAsyncPolicy GetRetryPolicy() - { - return HttpPolicyExtensions - .HandleTransientHttpError() - .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) - .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); - - } - static IAsyncPolicy GetCircuitBreakerPolicy() - { - return HttpPolicyExtensions - .HandleTransientHttpError() - .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); - } - } + app.UseSession(); + app.UseStaticFiles(); + + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } + + app.UseAuthentication(); + + ILogger log = loggerFactory.CreateLogger("identity"); + + WebContextSeed.Seed(app, env, loggerFactory); + + app.UseMvc(routes => + { + routes.MapRoute( + name: "default", + template: "{controller=Catalog}/{action=Index}/{id?}"); + + routes.MapRoute( + name: "defaultError", + template: "{controller=Error}/{action=Error}"); + }); + } + } + + static class ServiceCollectionExtensions + { + + public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) + { + services.AddApplicationInsightsTelemetry(configuration); + string orchestratorType = configuration.GetValue("OrchestratorType"); + + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + + return services; + } + + public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) + { + services.AddHealthChecks(checks => + { + int minutes = 1; + if (int.TryParse(configuration["HealthCheck:Timeout"], out int minutesParsed)) + { + minutes = minutesParsed; + } + + checks.AddUrlCheck(configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes)); + checks.AddUrlCheck(configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes)); + checks.AddUrlCheck(configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos + checks.AddUrlCheck(configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes)); + checks.AddUrlCheck(configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes)); + }); + + return services; + } + + public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + services.Configure(configuration); + + services + .AddMvc(opts => + { + opts.SslPort = 4100; + opts.RequireHttpsPermanent = true; + }) + .SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1); + + services.AddSession(); + + if (configuration.GetValue("IsClusterEnv") == bool.TrueString) + { + services.AddDataProtection(opts => + { + opts.ApplicationDiscriminator = "eshop.webmvc"; + }) + .PersistKeysToRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys"); + } + return services; + } + + // Adds all Http client services (like Service-Agents) using resilient Http requests based on HttpClient factory and Polly's policies + public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(); + + //register delegating handlers + services.AddTransient(); + services.AddTransient(); + + //set 5 min as the lifetime for each HttpMessageHandler int the pool + services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5)); + + //add http client services + services.AddHttpClient() + .SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes + .AddHttpMessageHandler() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + services.AddHttpClient() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + services.AddHttpClient() + .AddHttpMessageHandler() + .AddHttpMessageHandler() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + services.AddHttpClient() + .AddHttpMessageHandler() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + services.AddHttpClient() + .AddHttpMessageHandler() + .AddPolicyHandler(GetRetryPolicy()) + .AddPolicyHandler(GetCircuitBreakerPolicy()); + + //add custom application services + services.AddTransient, IdentityParser>(); + + return services; + } + + public static IServiceCollection AddHttpClientLogging(this IServiceCollection services, IConfiguration configuration) + { + services.AddLogging(b => + { + b.AddFilter((category, level) => true); // Spam the world with logs. + + // Add console logger so we can see all the logging produced by the client by default. + b.AddConsole(c => c.IncludeScopes = true); + + // Add console logger + b.AddDebug(); + }); + + return services; + } + + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + bool useLoadTest = configuration.GetValue("UseLoadTest"); + string identityUrl = configuration.GetValue("IdentityUrl"); + string callBackUrl = configuration.GetValue("CallBackUrl"); + + // Add Authentication services + + services.AddAuthentication(options => + { + options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; + }) + .AddCookie() + .AddOpenIdConnect(options => + { + options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.Authority = identityUrl.ToString(); + options.SignedOutRedirectUri = callBackUrl.ToString(); + options.ClientId = useLoadTest ? "mvctest" : "mvc"; + options.ClientSecret = "secret"; + options.ResponseType = useLoadTest ? "code id_token token" : "code id_token"; + options.SaveTokens = true; + options.GetClaimsFromUserInfoEndpoint = true; + options.RequireHttpsMetadata = false; + options.Scope.Add("openid"); + options.Scope.Add("profile"); + options.Scope.Add("orders"); + options.Scope.Add("basket"); + options.Scope.Add("marketing"); + options.Scope.Add("locations"); + options.Scope.Add("webshoppingagg"); + options.Scope.Add("orders.signalrhub"); + }); + + return services; + } + + static IAsyncPolicy GetRetryPolicy() + { + return HttpPolicyExtensions + .HandleTransientHttpError() + .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) + .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + + } + static IAsyncPolicy GetCircuitBreakerPolicy() + { + return HttpPolicyExtensions + .HandleTransientHttpError() + .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); + } + } } From c15c8981754f98a6203248c465fcdc79e328c916 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 02:32:08 +0600 Subject: [PATCH 12/24] 1. Updated Runtime version 2.1-2.1.3 2. Exposed 443 port for HTTPS 3. Updated SDK version 2.1-2.1.401 --- src/Web/WebMVC/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Web/WebMVC/Dockerfile b/src/Web/WebMVC/Dockerfile index 9847ad772..21be81a15 100644 --- a/src/Web/WebMVC/Dockerfile +++ b/src/Web/WebMVC/Dockerfile @@ -2,8 +2,9 @@ ARG NODE_IMAGE=node:8.11 FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 +EXPOSE 443 -FROM microsoft/dotnet:2.1-sdk as dotnet-build +FROM microsoft/dotnet:2.1.401-sdk as dotnet-build WORKDIR /src FROM ${NODE_IMAGE} as node-build @@ -16,6 +17,7 @@ FROM dotnet-build as build WORKDIR /src/src/Web/WebMVC/wwwroot COPY --from=node-build /web/wwwroot . WORKDIR /src +COPY src/Web/WebMVC/synergydev.pfx /root/.aspnet/https/ COPY . . WORKDIR /src/src/Web/WebMVC RUN dotnet restore -nowarn:msb3202,nu1503 From b4044a57b6f960387e83baa8a47bdda633bb1f30 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 03:02:44 +0600 Subject: [PATCH 13/24] 1. Added SSL certificates (pfx files) 2. Copy the certificate to the Linux Container system folder 3. Specified SSL certificate (pfx) path and password in appsettings.json --- Certificates/DotNet Foundation CA.pfx | Bin 0 -> 2970 bytes Certificates/eShopOnContainers.pfx | Bin 0 -> 3354 bytes .../aggregator/appsettings.json | 34 +++++++++++------- src/Web/WebMVC/Dockerfile | 4 +-- 4 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 Certificates/DotNet Foundation CA.pfx create mode 100644 Certificates/eShopOnContainers.pfx diff --git a/Certificates/DotNet Foundation CA.pfx b/Certificates/DotNet Foundation CA.pfx new file mode 100644 index 0000000000000000000000000000000000000000..67ce2e415e0ec2386c4f9d8311cc040adbc1794f GIT binary patch literal 2970 zcmZXVc{J327stQD7&}8KQI;vDgc*!1l`NAzA;l;n`<`70V<*el844l9ko2>KNXbvh zPL{Exm}$lmMi@Nv`<>_cJ?A;kx#xa9_rBiue$M&)b1wqRnZpEPMqoM3AnfPk^x}57 zL9C!+ET=XY%c;S@>If`^>whGc12C3l7lCEjX7~n#^WR-u93ZA*Ecg(C1@9q5Asqj~ zjK_JvY{(K~qTj*GTqY*gK`<6Pi7zpk$vF3c&at9n{M-KAVcA!Ut_BrYVII3jd2FCf z8T)Ef9?r`rGKi=Z5H~#tcJK&5Ns4k-_=I?Oh@H$1~ z_lL%UEGYipPs&NIUYL8d6Ek8pHSq2_VmYKfWsb(g%aRlUoi$Tr>)~ginV2V(W3{L2;Xi-_+}OxGSTgc|NkCig#g(*ywH8kj2RI zC_?4B9}fVmLNR%{YxhETlcAmg-tx+&{68LYIYXzOZVc$ANK6pj!wgDZYRO#t=IS}+ zlyerk7q{7uT-xoN?bYU(GnsZ9BXc7uG!|V8U!&s4SVb=$a#3=t6Dgq)}Uw@xN;hK1xjgNJqU2b z$&CnE3kxW}O-l6p8hyR5OoaN@?ob@ao(#636h4@J7qTBx<(wJw?Cdr-&erHNckNQ2 z6+Y^W63FAhKa zHsM;+F#EOA!$!n^qrgay_|ys+97tj-qSVT21zr7BQGWFO#MB1-srBW|>H0x4ewNfO zHyXNK<2eC&^=Yu3l>KO!CMwi9-uAb$-PbcOS5~0wSwHmm$GQ!_jK&I^flgVsx*6KS zdM1sU_Ohqx-jN51_TJf)ab-4Y?6yagCY0D3N$v@}$1-f?`@Z|g3kgo@A{V?CmeH+TXnU<*x8oz|x3Z&0fa7rdRS&FJ zP8uc%WJ@n_?={#!N~4p8rNWyuV_FP4)FxIJQMUXSC)F+c%NCSJ>r>!!vU8J}lA=pp z){6ya&zNGe$P)sGX+Mo!&YFVY!T17{dD*LBcGDtAr0Js*y-;}f8|ISut@ zzn?8dsov0aJr`IH_mnr@l1Mz-KfkQ?zF1-FlK=0{PZB3EU#xa>97@keb7SX0GH`HGUg{Gh>yaEcX+LnNA3*O-d=VmHOUiU*pZV)y@BD_TV{v0#-wW$|Jg9L zM$2@0XuUP4N~mb)ffh1q4sqy000oy|Ahj`>!*!?P(T^b1TF#yhA9C$ z02+`5t}%!*Ba>w~0zm!ER2WnTP-HL#hKgqRU#88-6c}8KQ5lYKhp@{)KwuE|A|D88 zbNUWo47dXK0bjry@ME|W;17s1TD<@lz>aa=2OI$h2GM3zgaAGa)f;eT#CD9>Z9Dra9ed&Mx!U`$IvYcQb0VWW@xVZnTfc}38NGL1dH%H7V ze=UJXEO=hu+D_*SECy320E^z~wjOm^7aP*1UZ;(qn;ZYgGp)`%mivwEMbUt5b+5+_ z0(-|e>EZcHRH_4iePU-)gtH2vN|rWa9;Eo~*TJKXRip3<_bd!M$8d+-A>Bc#=4A)G zno9mWHNwh!Yi!3L!rn?UYMoZ|VOCW7-AdM+Y%IMk74LAvEJgo10hh%YMLzykTTW9L zM7VpYu*LM?K+jGxD>{F`*(A=zkc|ji|CZ|5A1gH~y&Pu~*IIGMgDrq`>+E4{Vj#V} zc0Z%rjn%jVS*IVRupF?(uHMtj75notI^V;j?S9gQ4Gi~YnREJ@7duASNBX`zDV3aN z8sAE3<#Od#PqSMYemM2qjCsErY;d-&$SVrnjqT(aBk_ckRzXSLA*)0aLW{D*Zwpaw{;mcPL$v> zo$_;frKU*eA5Qr6>AiG#VVHi@Hi6sMfV{@62r6k>7@8SA%_K~EwRHZ7zivxm$D2po zm^zT?mC$6?`T3e}gHw>@I6DGuq$VYLEL?0yKxRy%pG=ycC6dTl+B?Npj^WL0m&*Ul zx|7P!J=pddlXC)+U3q*<6YX*GqBw?R&wTT;g`a#LFWaD~%j*$x$MpJXzgM2VY8dR^ z`8PEZ#`iWe6E*LR9i(o5_vp;O_h3mW=(LWOpT8R{2xL0jk!$47QEqxbv1|gA%Hvw3 z&&2W77wCr5T^^Ery62hOcZfLIw8ooBDwkj?#g*G3%ej7;-K|2Oft!hG;<^^dJ4x|l zk*HPwF^a~v{)H>{>0<`psXnA}9~#fN;F-Sbm!hikBHS_WQl9w%kOy9A=bnS28p`Cgl45AFPsOx(@OJWZ>+Q|0aP1T*8deZl&#k=0ht36|AGzmScesUre z)hR#ekXitJB27K>K!fjif?%f~grHfIME(#`K>bvbS|s-SZ52ZGoM29RigBaqN4BI3 zldGCysyD>Xnl6)vLLDdihTMGJ)J!DaszUp|+=LZMg;8T_gyG(E#+CXveE?g6y^@Eg zg>KBb$hE4dCoRwyY!JdqReOC6|1TJfOamqIH>SItVNvUQ}ac}z+Ixm*x{XCK0Hq_z`TJx<7R4>{0bI;XM2s=>-}yq TKbCK5Rr&~?ju+kjYe4=B2y$^; literal 0 HcmV?d00001 diff --git a/Certificates/eShopOnContainers.pfx b/Certificates/eShopOnContainers.pfx new file mode 100644 index 0000000000000000000000000000000000000000..c5962c1c2ca28cce03688aaeab86a83e8f24892c GIT binary patch literal 3354 zcmZWqcQoAJw*Sr;lVA`ndKW~UQAQ_9h!J8KA$keXJ5hdOj51P$AbRi7gXlG)1Q8j% zmxK^eqGTdb?&Plb?p<%awb$O~b3UKXK4+bO&W7WtuYy5ja2$*Pr4Wg^6+@&3T>|Cd zV7(9=tcygq!EsR7|B=YgAUN_9IF9_7ls}+U|I-Dd1cCE#kaIW=@*B0SEn#mS>Cz`_O^43ius6A) zh(faJ!m!lC9XDUAfMHpv^w}EEIF*=zGgb^4>m!Me&E+Z&(TDIiI6-;t1<{DTDEuI+ zL2AIfxfX5cVA%EYtNw#^T}Ob_M`7yX+@UQ;8_t|ktPC5im_^MV!N4w|T>NaeeDJ(S zRb#&n*ps)kGz`9ZhdOB8-geoO3t4o-mJxnjvWALp8Fqs;xkn9>i;V(nn}c(FdtjLd zW2XrrUa8SRDS-9)$@3 zp@wjuyqiAiA-1sygT=g~sMff9P!TPqoS)-VP<39LiIHZ&tV#}Sw8fFLLx@KmrmaT% z?N=Ic&YevyJ=wJ*dYE<9)=+$F_O@Ohz^q1@k$W?H~4*1@(XS%YOCqGQ%VOomMr_z(pLm zlHTo_-;n%*le2WXZHLZ)o0n;5cEn$3q_PW3`hY51{L?)NUHI%zd3+5{s$ERdU*2F#YvrkF^Nty1p< zi@Wsehs99eQRWC&gm4H3Sc!(KE>2V%D^V?myb%W82J{`Kei0?k3(s*r#L5w1;!jx!At z$ch~Pe2~Rhw%dy+nFsU1{lo>dxt)7fU-K)}(`A1QwwUgtUx;8pDFJ4jm#pta_%r!O z-=e^yw)LF<2UUR0YMDgt{Q>nRdRELR8=HLBHMDd%U!}n9T2uE04MrO4Un7Bqr*RT~ zwYP?;`t3^gmNsAepn_39XOFvd&re_nM^#I%&jh|Rn7t@v_n)_MT_nrYRXJQqlv!WI zc6=$|*1Tf8qMV*v(*4iob(^f=@klE%l!8sm)|4Y(fM>{6NPt7WLS5~d=;T|pUXy;Z zzR!edAdlA1E5od2JZ5{v@8jq!2(|FuAo^#MaE(YkXJvZWm{Dz-7mJEoZ$m#37T1&f z+i9}_gnByI?;xx_utK<(?;?{hs^7@$FPdz8#KFG3^0Uc6<4f@ZC`CNY^(F^u3Xwe1 zz~5avtYwVfGnmg6634I!-oJ)BKx^*{OwlZES#VudFWcVAW=d}J()?cH6p2)5tY2A9 zuR?nlm9P=VwRo61K}g{cMmBbf6L@X|vOGWDNTcQKuzcfj*DUL(E?!J^o+vy<$LlPW zgMU_mIXXZ!J5GYiO z6(a2PX7tVDTS173WjMoszDo)w1QY@R0RRBE_%F$bFyOikgaYz_EFc3&0a}1MscHk_ z00Kag;xCdRRXISDgcJY`68{%Tld23Ukt8>Qr2mbZBoqdBgHnh>K@bp5jt+#d=CTCz z0T;jl@CCd8KTIpalcBJY6I0E-cj3&tu40w}NFW>KR>3u#4WfSDPC9H(4+@ zatUQ+g%asp>b10c-Zfa~Kw0?5 zikd|q`3J83$wV;z_cUQ_gX@>_kM(+{T>q36?rx79;qizmHeE5*~M z#qsVLhC`nz|twoUSbw_u1WUkj7fr$fkFDQ0D>jX^?TE@D@QI%xH7z(u$_@ES={ zDmV(AojrM5Uh+ z%S0AE@o-iwpuQgVJ<4}!R7Q?oi;!6qJlQp4qZ08V&}Eu$wC{8B$fPnJDzjPou;`NP zkGBP7rngiYf8SL)qQ7P%_gX!)38wK_fMF&U003QN|`%zX2g?KxKOE|&{-FKvVF zHjLM46-f~I_$|?Gm)Lj(N6Ai-)^2`k8RczOpin9@w-HF)E_-s|&UvPgGv!ZT!F^!d zm}eph{}IniHQH=?=&Z8Wq5iA|r z=jF-w?Su>b*E7BzmaJYY`Hs4r?oWEz&!KYi)^*1NI@E9E2CC?IXjEBdEVlKFinsD6 zt9}1r*PNBmzcxIe;Dt56$v~$& z?Zrw&_)ME^60$00v@Yl+PgJFJ#$;&b@yE`JkBY%U zdS8_uto8i1W07Y}pPi8{@yRT5>}v#nXcX%x>pp!(n}RVxOg}fPD|f^*Kc{VDkK$~- zEewiGfM?&JHe65-K=`wk3w5U(>Hc8wYFH$$iyV9g>w7{v#U{lcDFQ8q85csbb=~G} zBa}=Se^12WVG;%H&N9vQl|rAj)CdK*5}X@;2}&+XLk4DpFoMZc)U9>%AGeG9k(XK( j2lE}y6hau^t3GJrQOjB&Q&!Aq%=3F;Zo=dBcR>9M3k&{i literal 0 HcmV?d00001 diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json index 26bb0ac7a..e1efd9d6e 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/appsettings.json @@ -1,15 +1,23 @@ { - "Logging": { - "IncludeScopes": false, - "Debug": { - "LogLevel": { - "Default": "Warning" - } - }, - "Console": { - "LogLevel": { - "Default": "Warning" - } - } - } + "Logging": { + "IncludeScopes": false, + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } + } + }, + "Kestrel": { + "Certificates": { + "Default": { + "Path": "./synergydev.pfx", + "Password": "RH@ssl2018" + } + } + } } diff --git a/src/Web/WebMVC/Dockerfile b/src/Web/WebMVC/Dockerfile index 21be81a15..3aa269654 100644 --- a/src/Web/WebMVC/Dockerfile +++ b/src/Web/WebMVC/Dockerfile @@ -1,5 +1,5 @@ ARG NODE_IMAGE=node:8.11 -FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base +FROM microsoft/dotnet:2.1.3-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 EXPOSE 443 @@ -17,7 +17,7 @@ FROM dotnet-build as build WORKDIR /src/src/Web/WebMVC/wwwroot COPY --from=node-build /web/wwwroot . WORKDIR /src -COPY src/Web/WebMVC/synergydev.pfx /root/.aspnet/https/ +COPY Certificates/eShopOnContainers.pfx /root/.aspnet/https/ COPY . . WORKDIR /src/src/Web/WebMVC RUN dotnet restore -nowarn:msb3202,nu1503 From 477fbdc97b61caac90e584d0f9b225af74b96149 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Sat, 1 Sep 2018 03:09:34 +0600 Subject: [PATCH 14/24] code style formatting --- src/Web/WebMVC/wwwroot/js/site.js | 5668 +++++++++++++------------ src/Web/WebMVC/wwwroot/js/site.min.js | 12 +- 2 files changed, 2841 insertions(+), 2839 deletions(-) diff --git a/src/Web/WebMVC/wwwroot/js/site.js b/src/Web/WebMVC/wwwroot/js/site.js index 0efaabd08..60aedcc20 100644 --- a/src/Web/WebMVC/wwwroot/js/site.js +++ b/src/Web/WebMVC/wwwroot/js/site.js @@ -4,2839 +4,2841 @@ */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.signalR = factory()); -}(this, (function () { 'use strict'; - -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function commonjsRequire () { - throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); -} - -function unwrapExports (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; -} - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var es6Promise_auto = createCommonjsModule(function (module, exports) { -/*! - * @overview es6-promise - a tiny implementation of Promises/A+. - * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) - * @license Licensed under MIT license - * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE - * @version v4.2.2+97478eb6 - */ - -(function (global, factory) { - module.exports = factory(); -}(commonjsGlobal, (function () { function objectOrFunction(x) { - var type = typeof x; - return x !== null && (type === 'object' || type === 'function'); -} - -function isFunction(x) { - return typeof x === 'function'; -} - - - -var _isArray = void 0; -if (Array.isArray) { - _isArray = Array.isArray; -} else { - _isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; -} - -var isArray = _isArray; - -var len = 0; -var vertxNext = void 0; -var customSchedulerFn = void 0; - -var asap = function asap(callback, arg) { - queue[len] = callback; - queue[len + 1] = arg; - len += 2; - if (len === 2) { - // If len is 2, that means that we need to schedule an async flush. - // If additional callbacks are queued before the queue is flushed, they - // will be processed by this flush that we are scheduling. - if (customSchedulerFn) { - customSchedulerFn(flush); - } else { - scheduleFlush(); - } - } -}; - -function setScheduler(scheduleFn) { - customSchedulerFn = scheduleFn; -} - -function setAsap(asapFn) { - asap = asapFn; -} - -var browserWindow = typeof window !== 'undefined' ? window : undefined; -var browserGlobal = browserWindow || {}; -var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; -var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; - -// test for web worker but not in IE10 -var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; - -// node -function useNextTick() { - // node version 0.10.x displays a deprecation warning when nextTick is used recursively - // see https://github.com/cujojs/when/issues/410 for details - return function () { - return process.nextTick(flush); - }; -} - -// vertx -function useVertxTimer() { - if (typeof vertxNext !== 'undefined') { - return function () { - vertxNext(flush); - }; - } - - return useSetTimeout(); -} - -function useMutationObserver() { - var iterations = 0; - var observer = new BrowserMutationObserver(flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); - - return function () { - node.data = iterations = ++iterations % 2; - }; -} - -// web worker -function useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - return function () { - return channel.port2.postMessage(0); - }; -} - -function useSetTimeout() { - // Store setTimeout reference so es6-promise will be unaffected by - // other code modifying setTimeout (like sinon.useFakeTimers()) - var globalSetTimeout = setTimeout; - return function () { - return globalSetTimeout(flush, 1); - }; -} - -var queue = new Array(1000); -function flush() { - for (var i = 0; i < len; i += 2) { - var callback = queue[i]; - var arg = queue[i + 1]; - - callback(arg); - - queue[i] = undefined; - queue[i + 1] = undefined; - } - - len = 0; -} - -function attemptVertx() { - try { - var r = commonjsRequire; - var vertx = r('vertx'); - vertxNext = vertx.runOnLoop || vertx.runOnContext; - return useVertxTimer(); - } catch (e) { - return useSetTimeout(); - } -} - -var scheduleFlush = void 0; -// Decide what async method to use to triggering processing of queued callbacks: -if (isNode) { - scheduleFlush = useNextTick(); -} else if (BrowserMutationObserver) { - scheduleFlush = useMutationObserver(); -} else if (isWorker) { - scheduleFlush = useMessageChannel(); -} else if (browserWindow === undefined && typeof commonjsRequire === 'function') { - scheduleFlush = attemptVertx(); -} else { - scheduleFlush = useSetTimeout(); -} - -function then(onFulfillment, onRejection) { - var parent = this; - - var child = new this.constructor(noop); - - if (child[PROMISE_ID] === undefined) { - makePromise(child); - } - - var _state = parent._state; - - - if (_state) { - var callback = arguments[_state - 1]; - asap(function () { - return invokeCallback(_state, child, callback, parent._result); - }); - } else { - subscribe(parent, child, onFulfillment, onRejection); - } - - return child; -} - -/** - `Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: - - ```javascript - let promise = new Promise(function(resolve, reject){ - resolve(1); - }); - - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - let promise = Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {Any} value value that the returned promise will be resolved with - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` -*/ -function resolve$1(object) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor(noop); - resolve(promise, object); - return promise; -} - -var PROMISE_ID = Math.random().toString(36).substring(16); - -function noop() {} - -var PENDING = void 0; -var FULFILLED = 1; -var REJECTED = 2; - -var GET_THEN_ERROR = new ErrorObject(); - -function selfFulfillment() { - return new TypeError("You cannot resolve a promise with itself"); -} - -function cannotReturnOwn() { - return new TypeError('A promises callback cannot return that same promise.'); -} - -function getThen(promise) { - try { - return promise.then; - } catch (error) { - GET_THEN_ERROR.error = error; - return GET_THEN_ERROR; - } -} - -function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { - try { - then$$1.call(value, fulfillmentHandler, rejectionHandler); - } catch (e) { - return e; - } -} - -function handleForeignThenable(promise, thenable, then$$1) { - asap(function (promise) { - var sealed = false; - var error = tryThen(then$$1, thenable, function (value) { - if (sealed) { - return; - } - sealed = true; - if (thenable !== value) { - resolve(promise, value); - } else { - fulfill(promise, value); - } - }, function (reason) { - if (sealed) { - return; - } - sealed = true; - - reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - reject(promise, error); - } - }, promise); -} - -function handleOwnThenable(promise, thenable) { - if (thenable._state === FULFILLED) { - fulfill(promise, thenable._result); - } else if (thenable._state === REJECTED) { - reject(promise, thenable._result); - } else { - subscribe(thenable, undefined, function (value) { - return resolve(promise, value); - }, function (reason) { - return reject(promise, reason); - }); - } -} - -function handleMaybeThenable(promise, maybeThenable, then$$1) { - if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) { - handleOwnThenable(promise, maybeThenable); - } else { - if (then$$1 === GET_THEN_ERROR) { - reject(promise, GET_THEN_ERROR.error); - GET_THEN_ERROR.error = null; - } else if (then$$1 === undefined) { - fulfill(promise, maybeThenable); - } else if (isFunction(then$$1)) { - handleForeignThenable(promise, maybeThenable, then$$1); - } else { - fulfill(promise, maybeThenable); - } - } -} - -function resolve(promise, value) { - if (promise === value) { - reject(promise, selfFulfillment()); - } else if (objectOrFunction(value)) { - handleMaybeThenable(promise, value, getThen(value)); - } else { - fulfill(promise, value); - } -} - -function publishRejection(promise) { - if (promise._onerror) { - promise._onerror(promise._result); - } - - publish(promise); -} - -function fulfill(promise, value) { - if (promise._state !== PENDING) { - return; - } - - promise._result = value; - promise._state = FULFILLED; - - if (promise._subscribers.length !== 0) { - asap(publish, promise); - } -} - -function reject(promise, reason) { - if (promise._state !== PENDING) { - return; - } - promise._state = REJECTED; - promise._result = reason; - - asap(publishRejection, promise); -} - -function subscribe(parent, child, onFulfillment, onRejection) { - var _subscribers = parent._subscribers; - var length = _subscribers.length; - - - parent._onerror = null; - - _subscribers[length] = child; - _subscribers[length + FULFILLED] = onFulfillment; - _subscribers[length + REJECTED] = onRejection; - - if (length === 0 && parent._state) { - asap(publish, parent); - } -} - -function publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; - - if (subscribers.length === 0) { - return; - } - - var child = void 0, - callback = void 0, - detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - invokeCallback(settled, child, callback, detail); - } else { - callback(detail); - } - } - - promise._subscribers.length = 0; -} - -function ErrorObject() { - this.error = null; -} - -var TRY_CATCH_ERROR = new ErrorObject(); - -function tryCatch(callback, detail) { - try { - return callback(detail); - } catch (e) { - TRY_CATCH_ERROR.error = e; - return TRY_CATCH_ERROR; - } -} - -function invokeCallback(settled, promise, callback, detail) { - var hasCallback = isFunction(callback), - value = void 0, - error = void 0, - succeeded = void 0, - failed = void 0; - - if (hasCallback) { - value = tryCatch(callback, detail); - - if (value === TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value.error = null; - } else { - succeeded = true; - } - - if (promise === value) { - reject(promise, cannotReturnOwn()); - return; - } - } else { - value = detail; - succeeded = true; - } - - if (promise._state !== PENDING) { - // noop - } else if (hasCallback && succeeded) { - resolve(promise, value); - } else if (failed) { - reject(promise, error); - } else if (settled === FULFILLED) { - fulfill(promise, value); - } else if (settled === REJECTED) { - reject(promise, value); - } -} - -function initializePromise(promise, resolver) { - try { - resolver(function resolvePromise(value) { - resolve(promise, value); - }, function rejectPromise(reason) { - reject(promise, reason); - }); - } catch (e) { - reject(promise, e); - } -} - -var id = 0; -function nextId() { - return id++; -} - -function makePromise(promise) { - promise[PROMISE_ID] = id++; - promise._state = undefined; - promise._result = undefined; - promise._subscribers = []; -} - -function validationError() { - return new Error('Array Methods must be provided an Array'); -} - -function validationError() { - return new Error('Array Methods must be provided an Array'); -} - -var Enumerator = function () { - function Enumerator(Constructor, input) { - this._instanceConstructor = Constructor; - this.promise = new Constructor(noop); - - if (!this.promise[PROMISE_ID]) { - makePromise(this.promise); - } - - if (isArray(input)) { - this.length = input.length; - this._remaining = input.length; - - this._result = new Array(this.length); - - if (this.length === 0) { - fulfill(this.promise, this._result); - } else { - this.length = this.length || 0; - this._enumerate(input); - if (this._remaining === 0) { - fulfill(this.promise, this._result); - } - } - } else { - reject(this.promise, validationError()); - } - } - - Enumerator.prototype._enumerate = function _enumerate(input) { - for (var i = 0; this._state === PENDING && i < input.length; i++) { - this._eachEntry(input[i], i); - } - }; - - Enumerator.prototype._eachEntry = function _eachEntry(entry, i) { - var c = this._instanceConstructor; - var resolve$$1 = c.resolve; - - - if (resolve$$1 === resolve$1) { - var _then = getThen(entry); - - if (_then === then && entry._state !== PENDING) { - this._settledAt(entry._state, i, entry._result); - } else if (typeof _then !== 'function') { - this._remaining--; - this._result[i] = entry; - } else if (c === Promise$2) { - var promise = new c(noop); - handleMaybeThenable(promise, entry, _then); - this._willSettleAt(promise, i); - } else { - this._willSettleAt(new c(function (resolve$$1) { - return resolve$$1(entry); - }), i); - } - } else { - this._willSettleAt(resolve$$1(entry), i); - } - }; - - Enumerator.prototype._settledAt = function _settledAt(state, i, value) { - var promise = this.promise; - - - if (promise._state === PENDING) { - this._remaining--; - - if (state === REJECTED) { - reject(promise, value); - } else { - this._result[i] = value; - } - } - - if (this._remaining === 0) { - fulfill(promise, this._result); - } - }; - - Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) { - var enumerator = this; - - subscribe(promise, undefined, function (value) { - return enumerator._settledAt(FULFILLED, i, value); - }, function (reason) { - return enumerator._settledAt(REJECTED, i, reason); - }); - }; - - return Enumerator; -}(); - -/** - `Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. - - Example: - - ```javascript - let promise1 = resolve(1); - let promise2 = resolve(2); - let promise3 = resolve(3); - let promises = [ promise1, promise2, promise3 ]; - - Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` - - If any of the `promises` given to `all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: - - Example: - - ```javascript - let promise1 = resolve(1); - let promise2 = reject(new Error("2")); - let promise3 = reject(new Error("3")); - let promises = [ promise1, promise2, promise3 ]; - - Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` - - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static -*/ -function all(entries) { - return new Enumerator(this, entries).promise; -} - -/** - `Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. - - Example: - - ```javascript - let promise1 = new Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - let promise2 = new Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); - - Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` - - `Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: - - ```javascript - let promise1 = new Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - let promise2 = new Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); - - Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` - - An example real-world use case is implementing timeouts: - - ```javascript - Promise.race([ajax('foo.json'), timeout(5000)]) - ``` - - @method race - @static - @param {Array} promises array of promises to observe - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. -*/ -function race(entries) { - /*jshint validthis:true */ - var Constructor = this; - - if (!isArray(entries)) { - return new Constructor(function (_, reject) { - return reject(new TypeError('You must pass an array to race.')); - }); - } else { - return new Constructor(function (resolve, reject) { - var length = entries.length; - for (var i = 0; i < length; i++) { - Constructor.resolve(entries[i]).then(resolve, reject); - } - }); - } -} - -/** - `Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - let promise = new Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - let promise = Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {Any} reason value that the returned promise will be rejected with. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. -*/ -function reject$1(reason) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(noop); - reject(promise, reason); - return promise; -} - -function needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); -} - -function needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); -} - -/** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise's eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - let promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - let xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; - }); - } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class Promise - @param {Function} resolver - Useful for tooling. - @constructor -*/ - -var Promise$2 = function () { - function Promise(resolver) { - this[PROMISE_ID] = nextId(); - this._result = this._state = undefined; - this._subscribers = []; - - if (noop !== resolver) { - typeof resolver !== 'function' && needsResolver(); - this instanceof Promise ? initializePromise(this, resolver) : needsNew(); - } - } - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - Chaining - -------- - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we're unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - Assimilation - ------------ - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - If the assimliated promise rejects, then the downstream promise will also reject. - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - Simple Example - -------------- - Synchronous Example - ```javascript - let result; - try { - result = findResult(); - // success - } catch(reason) { - // failure - } - ``` - Errback Example - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success - } - }); - ``` - Promise Example; - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` - Advanced Example - -------------- - Synchronous Example - ```javascript - let author, books; - try { - author = findAuthor(); - books = findBooksByAuthor(author); - // success - } catch(reason) { - // failure - } - ``` - Errback Example - ```js - function foundBooks(books) { - } - function failure(reason) { - } - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { - try { - findBoooksByAuthor(author, function(books, err) { - if (err) { - failure(err); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } - } - }); - } catch(error) { - failure(err); - } - // success - } - }); - ``` - Promise Example; - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - @method then - @param {Function} onFulfilled - @param {Function} onRejected - Useful for tooling. - @return {Promise} - */ - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - ```js - function findAuthor(){ - throw new Error('couldn't find that author'); - } - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - @method catch - @param {Function} onRejection - Useful for tooling. - @return {Promise} - */ - - - Promise.prototype.catch = function _catch(onRejection) { - return this.then(null, onRejection); - }; - - /** - `finally` will be invoked regardless of the promise's fate just as native - try/catch/finally behaves - - Synchronous example: - - ```js - findAuthor() { - if (Math.random() > 0.5) { - throw new Error(); - } - return new Author(); - } - - try { - return findAuthor(); // succeed or fail - } catch(error) { - return findOtherAuther(); - } finally { - // always runs - // doesn't affect the return value - } - ``` - - Asynchronous example: - - ```js - findAuthor().catch(function(reason){ - return findOtherAuther(); - }).finally(function(){ - // author was either found, or not - }); - ``` - - @method finally - @param {Function} callback - @return {Promise} - */ - - - Promise.prototype.finally = function _finally(callback) { - var promise = this; - var constructor = promise.constructor; - - return promise.then(function (value) { - return constructor.resolve(callback()).then(function () { - return value; - }); - }, function (reason) { - return constructor.resolve(callback()).then(function () { - throw reason; - }); - }); - }; - - return Promise; -}(); - -Promise$2.prototype.then = then; -Promise$2.all = all; -Promise$2.race = race; -Promise$2.resolve = resolve$1; -Promise$2.reject = reject$1; -Promise$2._setScheduler = setScheduler; -Promise$2._setAsap = setAsap; -Promise$2._asap = asap; - -/*global self*/ -function polyfill() { - var local = void 0; - - if (typeof commonjsGlobal !== 'undefined') { - local = commonjsGlobal; - } else if (typeof self !== 'undefined') { - local = self; - } else { - try { - local = Function('return this')(); - } catch (e) { - throw new Error('polyfill failed because global object is unavailable in this environment'); - } - } - - var P = local.Promise; - - if (P) { - var promiseToString = null; - try { - promiseToString = Object.prototype.toString.call(P.resolve()); - } catch (e) { - // silently ignored - } - - if (promiseToString === '[object Promise]' && !P.cast) { - return; - } - } - - local.Promise = Promise$2; -} - -// Strange compat.. -Promise$2.polyfill = polyfill; -Promise$2.Promise = Promise$2; - -Promise$2.polyfill(); - -return Promise$2; - -}))); - - - - -}); - -var Errors = createCommonjsModule(function (module, exports) { -var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var HttpError = /** @class */ (function (_super) { - __extends(HttpError, _super); - function HttpError(errorMessage, statusCode) { - var _newTarget = this.constructor; - var _this = this; - var trueProto = _newTarget.prototype; - _this = _super.call(this, errorMessage) || this; - _this.statusCode = statusCode; - // Workaround issue in Typescript compiler - // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200 - _this.__proto__ = trueProto; - return _this; - } - return HttpError; -}(Error)); -exports.HttpError = HttpError; -var TimeoutError = /** @class */ (function (_super) { - __extends(TimeoutError, _super); - function TimeoutError(errorMessage) { - var _newTarget = this.constructor; - if (errorMessage === void 0) { errorMessage = "A timeout occurred."; } - var _this = this; - var trueProto = _newTarget.prototype; - _this = _super.call(this, errorMessage) || this; - // Workaround issue in Typescript compiler - // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200 - _this.__proto__ = trueProto; - return _this; - } - return TimeoutError; -}(Error)); -exports.TimeoutError = TimeoutError; - -}); - -unwrapExports(Errors); -var Errors_1 = Errors.HttpError; -var Errors_2 = Errors.TimeoutError; - -var ILogger = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); -var LogLevel; -(function (LogLevel) { - LogLevel[LogLevel["Trace"] = 0] = "Trace"; - LogLevel[LogLevel["Information"] = 1] = "Information"; - LogLevel[LogLevel["Warning"] = 2] = "Warning"; - LogLevel[LogLevel["Error"] = 3] = "Error"; - LogLevel[LogLevel["None"] = 4] = "None"; -})(LogLevel = exports.LogLevel || (exports.LogLevel = {})); - -}); - -unwrapExports(ILogger); -var ILogger_1 = ILogger.LogLevel; - -var HttpClient_1 = createCommonjsModule(function (module, exports) { -var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __assign = (commonjsGlobal && commonjsGlobal.__assign) || Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; -}; -Object.defineProperty(exports, "__esModule", { value: true }); - - -var HttpResponse = /** @class */ (function () { - function HttpResponse(statusCode, statusText, content) { - this.statusCode = statusCode; - this.statusText = statusText; - this.content = content; - } - return HttpResponse; -}()); -exports.HttpResponse = HttpResponse; -var HttpClient = /** @class */ (function () { - function HttpClient() { - } - HttpClient.prototype.get = function (url, options) { - return this.send(__assign({}, options, { method: "GET", url: url })); - }; - HttpClient.prototype.post = function (url, options) { - return this.send(__assign({}, options, { method: "POST", url: url })); - }; - return HttpClient; -}()); -exports.HttpClient = HttpClient; -var DefaultHttpClient = /** @class */ (function (_super) { - __extends(DefaultHttpClient, _super); - function DefaultHttpClient(logger) { - var _this = _super.call(this) || this; - _this.logger = logger; - return _this; - } - DefaultHttpClient.prototype.send = function (request) { - var _this = this; - return new Promise(function (resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open(request.method, request.url, true); - xhr.withCredentials = true; - xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); - if (request.headers) { - Object.keys(request.headers) - .forEach(function (header) { return xhr.setRequestHeader(header, request.headers[header]); }); - } - if (request.responseType) { - xhr.responseType = request.responseType; - } - if (request.abortSignal) { - request.abortSignal.onabort = function () { - xhr.abort(); - }; - } - if (request.timeout) { - xhr.timeout = request.timeout; - } - xhr.onload = function () { - if (request.abortSignal) { - request.abortSignal.onabort = null; - } - if (xhr.status >= 200 && xhr.status < 300) { - resolve(new HttpResponse(xhr.status, xhr.statusText, xhr.response || xhr.responseText)); - } - else { - reject(new Errors.HttpError(xhr.statusText, xhr.status)); - } - }; - xhr.onerror = function () { - _this.logger.log(ILogger.LogLevel.Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText); - reject(new Errors.HttpError(xhr.statusText, xhr.status)); - }; - xhr.ontimeout = function () { - _this.logger.log(ILogger.LogLevel.Warning, "Timeout from HTTP request."); - reject(new Errors.TimeoutError()); - }; - xhr.send(request.content || ""); - }); - }; - return DefaultHttpClient; -}(HttpClient)); -exports.DefaultHttpClient = DefaultHttpClient; - -}); - -unwrapExports(HttpClient_1); -var HttpClient_2 = HttpClient_1.HttpResponse; -var HttpClient_3 = HttpClient_1.HttpClient; -var HttpClient_4 = HttpClient_1.DefaultHttpClient; - -var Loggers = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); - -var NullLogger = /** @class */ (function () { - function NullLogger() { - } - NullLogger.prototype.log = function (logLevel, message) { - }; - return NullLogger; -}()); -exports.NullLogger = NullLogger; -var ConsoleLogger = /** @class */ (function () { - function ConsoleLogger(minimumLogLevel) { - this.minimumLogLevel = minimumLogLevel; - } - ConsoleLogger.prototype.log = function (logLevel, message) { - if (logLevel >= this.minimumLogLevel) { - switch (logLevel) { - case ILogger.LogLevel.Error: - console.error(ILogger.LogLevel[logLevel] + ": " + message); - break; - case ILogger.LogLevel.Warning: - console.warn(ILogger.LogLevel[logLevel] + ": " + message); - break; - case ILogger.LogLevel.Information: - console.info(ILogger.LogLevel[logLevel] + ": " + message); - break; - default: - console.log(ILogger.LogLevel[logLevel] + ": " + message); - break; - } - } - }; - return ConsoleLogger; -}()); -exports.ConsoleLogger = ConsoleLogger; -var LoggerFactory = /** @class */ (function () { - function LoggerFactory() { - } - LoggerFactory.createLogger = function (logging) { - if (logging === undefined) { - return new ConsoleLogger(ILogger.LogLevel.Information); - } - if (logging === null) { - return new NullLogger(); - } - if (logging.log) { - return logging; - } - return new ConsoleLogger(logging); - }; - return LoggerFactory; -}()); -exports.LoggerFactory = LoggerFactory; - -}); - -unwrapExports(Loggers); -var Loggers_1 = Loggers.NullLogger; -var Loggers_2 = Loggers.ConsoleLogger; -var Loggers_3 = Loggers.LoggerFactory; - -var AbortController_1 = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); -// Rough polyfill of https://developer.mozilla.org/en-US/docs/Web/API/AbortController -// We don't actually ever use the API being polyfilled, we always use the polyfill because -// it's a very new API right now. -var AbortController = /** @class */ (function () { - function AbortController() { - this.isAborted = false; - } - AbortController.prototype.abort = function () { - if (!this.isAborted) { - this.isAborted = true; - if (this.onabort) { - this.onabort(); - } - } - }; - Object.defineProperty(AbortController.prototype, "signal", { - get: function () { - return this; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(AbortController.prototype, "aborted", { - get: function () { - return this.isAborted; - }, - enumerable: true, - configurable: true - }); - return AbortController; -}()); -exports.AbortController = AbortController; - -}); - -unwrapExports(AbortController_1); -var AbortController_2 = AbortController_1.AbortController; - -var Utils = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); -var Arg = /** @class */ (function () { - function Arg() { - } - Arg.isRequired = function (val, name) { - if (val === null || val === undefined) { - throw new Error("The '" + name + "' argument is required."); - } - }; - Arg.isIn = function (val, values, name) { - // TypeScript enums have keys for **both** the name and the value of each enum member on the type itself. - if (!(val in values)) { - throw new Error("Unknown " + name + " value: " + val + "."); - } - }; - return Arg; -}()); -exports.Arg = Arg; - -}); - -unwrapExports(Utils); -var Utils_1 = Utils.Arg; - -var Transports = createCommonjsModule(function (module, exports) { -var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [0, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); - - - - -var TransportType; -(function (TransportType) { - TransportType[TransportType["WebSockets"] = 0] = "WebSockets"; - TransportType[TransportType["ServerSentEvents"] = 1] = "ServerSentEvents"; - TransportType[TransportType["LongPolling"] = 2] = "LongPolling"; -})(TransportType = exports.TransportType || (exports.TransportType = {})); -var TransferFormat; -(function (TransferFormat) { - TransferFormat[TransferFormat["Text"] = 1] = "Text"; - TransferFormat[TransferFormat["Binary"] = 2] = "Binary"; -})(TransferFormat = exports.TransferFormat || (exports.TransferFormat = {})); -var WebSocketTransport = /** @class */ (function () { - function WebSocketTransport(accessTokenFactory, logger) { - this.logger = logger; - this.accessTokenFactory = accessTokenFactory || (function () { return null; }); - } - WebSocketTransport.prototype.connect = function (url, transferFormat, connection) { - var _this = this; - Utils.Arg.isRequired(url, "url"); - Utils.Arg.isRequired(transferFormat, "transferFormat"); - Utils.Arg.isIn(transferFormat, TransferFormat, "transferFormat"); - Utils.Arg.isRequired(connection, "connection"); - if (typeof (WebSocket) === "undefined") { - throw new Error("'WebSocket' is not supported in your environment."); - } - this.logger.log(ILogger.LogLevel.Trace, "(WebSockets transport) Connecting"); - return new Promise(function (resolve, reject) { - url = url.replace(/^http/, "ws"); - var token = _this.accessTokenFactory(); - if (token) { - url += (url.indexOf("?") < 0 ? "?" : "&") + ("access_token=" + encodeURIComponent(token)); - } - var webSocket = new WebSocket(url); - if (transferFormat === TransferFormat.Binary) { - webSocket.binaryType = "arraybuffer"; - } - webSocket.onopen = function (event) { - _this.logger.log(ILogger.LogLevel.Information, "WebSocket connected to " + url); - _this.webSocket = webSocket; - resolve(); - }; - webSocket.onerror = function (event) { - reject(event.error); - }; - webSocket.onmessage = function (message) { - _this.logger.log(ILogger.LogLevel.Trace, "(WebSockets transport) data received. " + getDataDetail(message.data) + "."); - if (_this.onreceive) { - _this.onreceive(message.data); - } - }; - webSocket.onclose = function (event) { - // webSocket will be null if the transport did not start successfully - if (_this.onclose && _this.webSocket) { - if (event.wasClean === false || event.code !== 1000) { - _this.onclose(new Error("Websocket closed with status code: " + event.code + " (" + event.reason + ")")); - } - else { - _this.onclose(); - } - } - }; - }); - }; - WebSocketTransport.prototype.send = function (data) { - if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) { - this.logger.log(ILogger.LogLevel.Trace, "(WebSockets transport) sending data. " + getDataDetail(data) + "."); - this.webSocket.send(data); - return Promise.resolve(); - } - return Promise.reject("WebSocket is not in the OPEN state"); - }; - WebSocketTransport.prototype.stop = function () { - if (this.webSocket) { - this.webSocket.close(); - this.webSocket = null; - } - return Promise.resolve(); - }; - return WebSocketTransport; -}()); -exports.WebSocketTransport = WebSocketTransport; -var ServerSentEventsTransport = /** @class */ (function () { - function ServerSentEventsTransport(httpClient, accessTokenFactory, logger) { - this.httpClient = httpClient; - this.accessTokenFactory = accessTokenFactory || (function () { return null; }); - this.logger = logger; - } - ServerSentEventsTransport.prototype.connect = function (url, transferFormat, connection) { - var _this = this; - Utils.Arg.isRequired(url, "url"); - Utils.Arg.isRequired(transferFormat, "transferFormat"); - Utils.Arg.isIn(transferFormat, TransferFormat, "transferFormat"); - Utils.Arg.isRequired(connection, "connection"); - if (typeof (EventSource) === "undefined") { - throw new Error("'EventSource' is not supported in your environment."); - } - this.logger.log(ILogger.LogLevel.Trace, "(SSE transport) Connecting"); - this.url = url; - return new Promise(function (resolve, reject) { - if (transferFormat !== TransferFormat.Text) { - reject(new Error("The Server-Sent Events transport only supports the 'Text' transfer format")); - } - var token = _this.accessTokenFactory(); - if (token) { - url += (url.indexOf("?") < 0 ? "?" : "&") + ("access_token=" + encodeURIComponent(token)); - } - var eventSource = new EventSource(url, { withCredentials: true }); - try { - eventSource.onmessage = function (e) { - if (_this.onreceive) { - try { - _this.logger.log(ILogger.LogLevel.Trace, "(SSE transport) data received. " + getDataDetail(e.data) + "."); - _this.onreceive(e.data); - } - catch (error) { - if (_this.onclose) { - _this.onclose(error); - } - return; - } - } - }; - eventSource.onerror = function (e) { - reject(new Error(e.message || "Error occurred")); - // don't report an error if the transport did not start successfully - if (_this.eventSource && _this.onclose) { - _this.onclose(new Error(e.message || "Error occurred")); - } - }; - eventSource.onopen = function () { - _this.logger.log(ILogger.LogLevel.Information, "SSE connected to " + _this.url); - _this.eventSource = eventSource; - // SSE is a text protocol - resolve(); - }; - } - catch (e) { - return Promise.reject(e); - } - }); - }; - ServerSentEventsTransport.prototype.send = function (data) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, send(this.logger, "SSE", this.httpClient, this.url, this.accessTokenFactory, data)]; - }); - }); - }; - ServerSentEventsTransport.prototype.stop = function () { - if (this.eventSource) { - this.eventSource.close(); - this.eventSource = null; - } - return Promise.resolve(); - }; - return ServerSentEventsTransport; -}()); -exports.ServerSentEventsTransport = ServerSentEventsTransport; -var LongPollingTransport = /** @class */ (function () { - function LongPollingTransport(httpClient, accessTokenFactory, logger) { - this.httpClient = httpClient; - this.accessTokenFactory = accessTokenFactory || (function () { return null; }); - this.logger = logger; - this.pollAbort = new AbortController_1.AbortController(); - } - LongPollingTransport.prototype.connect = function (url, transferFormat, connection) { - Utils.Arg.isRequired(url, "url"); - Utils.Arg.isRequired(transferFormat, "transferFormat"); - Utils.Arg.isIn(transferFormat, TransferFormat, "transferFormat"); - Utils.Arg.isRequired(connection, "connection"); - this.url = url; - this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) Connecting"); - // Set a flag indicating we have inherent keep-alive in this transport. - connection.features.inherentKeepAlive = true; - if (transferFormat === TransferFormat.Binary && (typeof new XMLHttpRequest().responseType !== "string")) { - // This will work if we fix: https://github.com/aspnet/SignalR/issues/742 - throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported."); - } - this.poll(this.url, transferFormat); - return Promise.resolve(); - }; - LongPollingTransport.prototype.poll = function (url, transferFormat) { - return __awaiter(this, void 0, void 0, function () { - var pollOptions, token, pollUrl, response, e_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - pollOptions = { - abortSignal: this.pollAbort.signal, - headers: {}, - timeout: 90000, - }; - if (transferFormat === TransferFormat.Binary) { - pollOptions.responseType = "arraybuffer"; - } - token = this.accessTokenFactory(); - if (token) { - // tslint:disable-next-line:no-string-literal - pollOptions.headers["Authorization"] = "Bearer " + token; - } - _a.label = 1; - case 1: - if (!!this.pollAbort.signal.aborted) return [3 /*break*/, 6]; - _a.label = 2; - case 2: - _a.trys.push([2, 4, , 5]); - pollUrl = url + "&_=" + Date.now(); - this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl); - return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)]; - case 3: - response = _a.sent(); - if (response.statusCode === 204) { - this.logger.log(ILogger.LogLevel.Information, "(LongPolling transport) Poll terminated by server"); - // Poll terminated by server - if (this.onclose) { - this.onclose(); - } - this.pollAbort.abort(); - } - else if (response.statusCode !== 200) { - this.logger.log(ILogger.LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode); - // Unexpected status code - if (this.onclose) { - this.onclose(new Errors.HttpError(response.statusText, response.statusCode)); - } - this.pollAbort.abort(); - } - else { - // Process the response - if (response.content) { - this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) data received. " + getDataDetail(response.content) + "."); - if (this.onreceive) { - this.onreceive(response.content); - } - } - else { - // This is another way timeout manifest. - this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) Poll timed out, reissuing."); - } - } - return [3 /*break*/, 5]; - case 4: - e_1 = _a.sent(); - if (e_1 instanceof Errors.TimeoutError) { - // Ignore timeouts and reissue the poll. - this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) Poll timed out, reissuing."); - } - else { - // Close the connection with the error as the result. - if (this.onclose) { - this.onclose(e_1); - } - this.pollAbort.abort(); - } - return [3 /*break*/, 5]; - case 5: return [3 /*break*/, 1]; - case 6: return [2 /*return*/]; - } - }); - }); - }; - LongPollingTransport.prototype.send = function (data) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, send(this.logger, "LongPolling", this.httpClient, this.url, this.accessTokenFactory, data)]; - }); - }); - }; - LongPollingTransport.prototype.stop = function () { - this.pollAbort.abort(); - return Promise.resolve(); - }; - return LongPollingTransport; -}()); -exports.LongPollingTransport = LongPollingTransport; -function getDataDetail(data) { - var length = null; - if (data instanceof ArrayBuffer) { - length = "Binary data of length " + data.byteLength; - } - else if (typeof data === "string") { - length = "String data of length " + data.length; - } - return length; -} -function send(logger, transportName, httpClient, url, accessTokenFactory, content) { - return __awaiter(this, void 0, void 0, function () { - var headers, token, response, _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - token = accessTokenFactory(); - if (token) { - headers = (_a = {}, _a["Authorization"] = "Bearer " + accessTokenFactory(), _a); - } - logger.log(ILogger.LogLevel.Trace, "(" + transportName + " transport) sending data. " + getDataDetail(content) + "."); - return [4 /*yield*/, httpClient.post(url, { - content: content, - headers: headers, - })]; - case 1: - response = _b.sent(); - logger.log(ILogger.LogLevel.Trace, "(" + transportName + " transport) request complete. Response status: " + response.statusCode + "."); - return [2 /*return*/]; - } - }); - }); -} - -}); - -unwrapExports(Transports); -var Transports_1 = Transports.TransportType; -var Transports_2 = Transports.TransferFormat; -var Transports_3 = Transports.WebSocketTransport; -var Transports_4 = Transports.ServerSentEventsTransport; -var Transports_5 = Transports.LongPollingTransport; - -var HttpConnection_1 = createCommonjsModule(function (module, exports) { -var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [0, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); - - - - - -var HttpConnection = /** @class */ (function () { - function HttpConnection(url, options) { - if (options === void 0) { options = {}; } - this.features = {}; - Utils.Arg.isRequired(url, "url"); - this.logger = Loggers.LoggerFactory.createLogger(options.logger); - this.baseUrl = this.resolveUrl(url); - options = options || {}; - options.accessTokenFactory = options.accessTokenFactory || (function () { return null; }); - this.httpClient = options.httpClient || new HttpClient_1.DefaultHttpClient(this.logger); - this.connectionState = 2 /* Disconnected */; - this.options = options; - } - HttpConnection.prototype.start = function (transferFormat) { - Utils.Arg.isRequired(transferFormat, "transferFormat"); - Utils.Arg.isIn(transferFormat, Transports.TransferFormat, "transferFormat"); - this.logger.log(ILogger.LogLevel.Trace, "Starting connection with transfer format '" + Transports.TransferFormat[transferFormat] + "'."); - if (this.connectionState !== 2 /* Disconnected */) { - return Promise.reject(new Error("Cannot start a connection that is not in the 'Disconnected' state.")); - } - this.connectionState = 0 /* Connecting */; - this.startPromise = this.startInternal(transferFormat); - return this.startPromise; - }; - HttpConnection.prototype.startInternal = function (transferFormat) { - return __awaiter(this, void 0, void 0, function () { - var _this = this; - var token, headers, negotiateResponse, e_1, _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - _b.trys.push([0, 6, , 7]); - if (!(this.options.transport === Transports.TransportType.WebSockets)) return [3 /*break*/, 2]; - // No need to add a connection ID in this case - this.url = this.baseUrl; - this.transport = this.constructTransport(Transports.TransportType.WebSockets); - // We should just call connect directly in this case. - // No fallback or negotiate in this case. - return [4 /*yield*/, this.transport.connect(this.url, transferFormat, this)]; - case 1: - // We should just call connect directly in this case. - // No fallback or negotiate in this case. - _b.sent(); - return [3 /*break*/, 5]; - case 2: - token = this.options.accessTokenFactory(); - headers = void 0; - if (token) { - headers = (_a = {}, _a["Authorization"] = "Bearer " + token, _a); - } - return [4 /*yield*/, this.getNegotiationResponse(headers)]; - case 3: - negotiateResponse = _b.sent(); - // the user tries to stop the the connection when it is being started - if (this.connectionState === 2 /* Disconnected */) { - return [2 /*return*/]; - } - return [4 /*yield*/, this.createTransport(this.options.transport, negotiateResponse, transferFormat, headers)]; - case 4: - _b.sent(); - _b.label = 5; - case 5: - this.transport.onreceive = this.onreceive; - this.transport.onclose = function (e) { return _this.stopConnection(true, e); }; - // only change the state if we were connecting to not overwrite - // the state if the connection is already marked as Disconnected - this.changeState(0 /* Connecting */, 1 /* Connected */); - return [3 /*break*/, 7]; - case 6: - e_1 = _b.sent(); - this.logger.log(ILogger.LogLevel.Error, "Failed to start the connection: " + e_1); - this.connectionState = 2 /* Disconnected */; - this.transport = null; - throw e_1; - case 7: return [2 /*return*/]; - } - }); - }); - }; - HttpConnection.prototype.getNegotiationResponse = function (headers) { - return __awaiter(this, void 0, void 0, function () { - var negotiateUrl, response, e_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - negotiateUrl = this.resolveNegotiateUrl(this.baseUrl); - this.logger.log(ILogger.LogLevel.Trace, "Sending negotiation request: " + negotiateUrl); - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.httpClient.post(negotiateUrl, { - content: "", - headers: headers, - })]; - case 2: - response = _a.sent(); - return [2 /*return*/, JSON.parse(response.content)]; - case 3: - e_2 = _a.sent(); - this.logger.log(ILogger.LogLevel.Error, "Failed to complete negotiation with the server: " + e_2); - throw e_2; - case 4: return [2 /*return*/]; - } - }); - }); - }; - HttpConnection.prototype.updateConnectionId = function (negotiateResponse) { - this.connectionId = negotiateResponse.connectionId; - this.url = this.baseUrl + (this.baseUrl.indexOf("?") === -1 ? "?" : "&") + ("id=" + this.connectionId); - }; - HttpConnection.prototype.createTransport = function (requestedTransport, negotiateResponse, requestedTransferFormat, headers) { - return __awaiter(this, void 0, void 0, function () { - var transports, _i, transports_1, endpoint, transport, ex_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.updateConnectionId(negotiateResponse); - if (!this.isITransport(requestedTransport)) return [3 /*break*/, 2]; - this.logger.log(ILogger.LogLevel.Trace, "Connection was provided an instance of ITransport, using that directly."); - this.transport = requestedTransport; - return [4 /*yield*/, this.transport.connect(this.url, requestedTransferFormat, this)]; - case 1: - _a.sent(); - // only change the state if we were connecting to not overwrite - // the state if the connection is already marked as Disconnected - this.changeState(0 /* Connecting */, 1 /* Connected */); - return [2 /*return*/]; - case 2: - transports = negotiateResponse.availableTransports; - _i = 0, transports_1 = transports; - _a.label = 3; - case 3: - if (!(_i < transports_1.length)) return [3 /*break*/, 9]; - endpoint = transports_1[_i]; - this.connectionState = 0 /* Connecting */; - transport = this.resolveTransport(endpoint, requestedTransport, requestedTransferFormat); - if (!(typeof transport === "number")) return [3 /*break*/, 8]; - this.transport = this.constructTransport(transport); - if (!(negotiateResponse.connectionId === null)) return [3 /*break*/, 5]; - return [4 /*yield*/, this.getNegotiationResponse(headers)]; - case 4: - negotiateResponse = _a.sent(); - this.updateConnectionId(negotiateResponse); - _a.label = 5; - case 5: - _a.trys.push([5, 7, , 8]); - return [4 /*yield*/, this.transport.connect(this.url, requestedTransferFormat, this)]; - case 6: - _a.sent(); - this.changeState(0 /* Connecting */, 1 /* Connected */); - return [2 /*return*/]; - case 7: - ex_1 = _a.sent(); - this.logger.log(ILogger.LogLevel.Error, "Failed to start the transport '" + Transports.TransportType[transport] + "': " + ex_1); - this.connectionState = 2 /* Disconnected */; - negotiateResponse.connectionId = null; - return [3 /*break*/, 8]; - case 8: - _i++; - return [3 /*break*/, 3]; - case 9: throw new Error("Unable to initialize any of the available transports."); - } - }); - }); - }; - HttpConnection.prototype.constructTransport = function (transport) { - switch (transport) { - case Transports.TransportType.WebSockets: - return new Transports.WebSocketTransport(this.options.accessTokenFactory, this.logger); - case Transports.TransportType.ServerSentEvents: - return new Transports.ServerSentEventsTransport(this.httpClient, this.options.accessTokenFactory, this.logger); - case Transports.TransportType.LongPolling: - return new Transports.LongPollingTransport(this.httpClient, this.options.accessTokenFactory, this.logger); - default: - throw new Error("Unknown transport: " + transport + "."); - } - }; - HttpConnection.prototype.resolveTransport = function (endpoint, requestedTransport, requestedTransferFormat) { - var transport = Transports.TransportType[endpoint.transport]; - if (transport === null || transport === undefined) { - this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + endpoint.transport + "' because it is not supported by this client."); - } - else { - var transferFormats = endpoint.transferFormats.map(function (s) { return Transports.TransferFormat[s]; }); - if (!requestedTransport || transport === requestedTransport) { - if (transferFormats.indexOf(requestedTransferFormat) >= 0) { - if ((transport === Transports.TransportType.WebSockets && typeof WebSocket === "undefined") || - (transport === Transports.TransportType.ServerSentEvents && typeof EventSource === "undefined")) { - this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + Transports.TransportType[transport] + "' because it is not supported in your environment.'"); - } - else { - this.logger.log(ILogger.LogLevel.Trace, "Selecting transport '" + Transports.TransportType[transport] + "'"); - return transport; - } - } - else { - this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + Transports.TransportType[transport] + "' because it does not support the requested transfer format '" + Transports.TransferFormat[requestedTransferFormat] + "'."); - } - } - else { - this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + Transports.TransportType[transport] + "' because it was disabled by the client."); - } - } - return null; - }; - HttpConnection.prototype.isITransport = function (transport) { - return typeof (transport) === "object" && "connect" in transport; - }; - HttpConnection.prototype.changeState = function (from, to) { - if (this.connectionState === from) { - this.connectionState = to; - return true; - } - return false; - }; - HttpConnection.prototype.send = function (data) { - if (this.connectionState !== 1 /* Connected */) { - throw new Error("Cannot send data if the connection is not in the 'Connected' State."); - } - return this.transport.send(data); - }; - HttpConnection.prototype.stop = function (error) { - return __awaiter(this, void 0, void 0, function () { - var previousState, e_3; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - previousState = this.connectionState; - this.connectionState = 2 /* Disconnected */; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.startPromise]; - case 2: - _a.sent(); - return [3 /*break*/, 4]; - case 3: - e_3 = _a.sent(); - return [3 /*break*/, 4]; - case 4: - this.stopConnection(/*raiseClosed*/ previousState === 1 /* Connected */, error); - return [2 /*return*/]; - } - }); - }); - }; - HttpConnection.prototype.stopConnection = function (raiseClosed, error) { - if (this.transport) { - this.transport.stop(); - this.transport = null; - } - if (error) { - this.logger.log(ILogger.LogLevel.Error, "Connection disconnected with error '" + error + "'."); - } - else { - this.logger.log(ILogger.LogLevel.Information, "Connection disconnected."); - } - this.connectionState = 2 /* Disconnected */; - if (raiseClosed && this.onclose) { - this.onclose(error); - } - }; - HttpConnection.prototype.resolveUrl = function (url) { - // startsWith is not supported in IE - if (url.lastIndexOf("https://", 0) === 0 || url.lastIndexOf("http://", 0) === 0) { - return url; - } - if (typeof window === "undefined" || !window || !window.document) { - throw new Error("Cannot resolve '" + url + "'."); - } - var parser = window.document.createElement("a"); - parser.href = url; - var baseUrl = (!parser.protocol || parser.protocol === ":") - ? window.document.location.protocol + "//" + (parser.host || window.document.location.host) - : parser.protocol + "//" + parser.host; - if (!url || url[0] !== "/") { - url = "/" + url; - } - var normalizedUrl = baseUrl + url; - this.logger.log(ILogger.LogLevel.Information, "Normalizing '" + url + "' to '" + normalizedUrl + "'."); - return normalizedUrl; - }; - HttpConnection.prototype.resolveNegotiateUrl = function (url) { - var index = url.indexOf("?"); - var negotiateUrl = url.substring(0, index === -1 ? url.length : index); - if (negotiateUrl[negotiateUrl.length - 1] !== "/") { - negotiateUrl += "/"; - } - negotiateUrl += "negotiate"; - negotiateUrl += index === -1 ? "" : url.substring(index); - return negotiateUrl; - }; - return HttpConnection; -}()); -exports.HttpConnection = HttpConnection; - -}); - -unwrapExports(HttpConnection_1); -var HttpConnection_2 = HttpConnection_1.HttpConnection; - -var TextMessageFormat_1 = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); -var TextMessageFormat = /** @class */ (function () { - function TextMessageFormat() { - } - TextMessageFormat.write = function (output) { - return "" + output + TextMessageFormat.RecordSeparator; - }; - TextMessageFormat.parse = function (input) { - if (input[input.length - 1] !== TextMessageFormat.RecordSeparator) { - throw new Error("Message is incomplete."); - } - var messages = input.split(TextMessageFormat.RecordSeparator); - messages.pop(); - return messages; - }; - TextMessageFormat.RecordSeparatorCode = 0x1e; - TextMessageFormat.RecordSeparator = String.fromCharCode(TextMessageFormat.RecordSeparatorCode); - return TextMessageFormat; -}()); -exports.TextMessageFormat = TextMessageFormat; - -}); - -unwrapExports(TextMessageFormat_1); -var TextMessageFormat_2 = TextMessageFormat_1.TextMessageFormat; - -var JsonHubProtocol_1 = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); - - - - -exports.JSON_HUB_PROTOCOL_NAME = "json"; -var JsonHubProtocol = /** @class */ (function () { - function JsonHubProtocol() { - this.name = exports.JSON_HUB_PROTOCOL_NAME; - this.version = 1; - this.transferFormat = Transports.TransferFormat.Text; - } - JsonHubProtocol.prototype.parseMessages = function (input, logger) { - if (!input) { - return []; - } - if (logger === null) { - logger = new Loggers.NullLogger(); - } - // Parse the messages - var messages = TextMessageFormat_1.TextMessageFormat.parse(input); - var hubMessages = []; - for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) { - var message = messages_1[_i]; - var parsedMessage = JSON.parse(message); - if (typeof parsedMessage.type !== "number") { - throw new Error("Invalid payload."); - } - switch (parsedMessage.type) { - case 1 /* Invocation */: - this.isInvocationMessage(parsedMessage); - break; - case 2 /* StreamItem */: - this.isStreamItemMessage(parsedMessage); - break; - case 3 /* Completion */: - this.isCompletionMessage(parsedMessage); - break; - case 6 /* Ping */: - // Single value, no need to validate - break; - case 7 /* Close */: - // All optional values, no need to validate - break; - default: - // Future protocol changes can add message types, old clients can ignore them - logger.log(ILogger.LogLevel.Information, "Unknown message type '" + parsedMessage.type + "' ignored."); - continue; - } - hubMessages.push(parsedMessage); - } - return hubMessages; - }; - JsonHubProtocol.prototype.writeMessage = function (message) { - return TextMessageFormat_1.TextMessageFormat.write(JSON.stringify(message)); - }; - JsonHubProtocol.prototype.isInvocationMessage = function (message) { - this.assertNotEmptyString(message.target, "Invalid payload for Invocation message."); - if (message.invocationId !== undefined) { - this.assertNotEmptyString(message.invocationId, "Invalid payload for Invocation message."); - } - }; - JsonHubProtocol.prototype.isStreamItemMessage = function (message) { - this.assertNotEmptyString(message.invocationId, "Invalid payload for StreamItem message."); - if (message.item === undefined) { - throw new Error("Invalid payload for StreamItem message."); - } - }; - JsonHubProtocol.prototype.isCompletionMessage = function (message) { - if (message.result && message.error) { - throw new Error("Invalid payload for Completion message."); - } - if (!message.result && message.error) { - this.assertNotEmptyString(message.error, "Invalid payload for Completion message."); - } - this.assertNotEmptyString(message.invocationId, "Invalid payload for Completion message."); - }; - JsonHubProtocol.prototype.assertNotEmptyString = function (value, errorMessage) { - if (typeof value !== "string" || value === "") { - throw new Error(errorMessage); - } - }; - return JsonHubProtocol; -}()); -exports.JsonHubProtocol = JsonHubProtocol; - -}); - -unwrapExports(JsonHubProtocol_1); -var JsonHubProtocol_2 = JsonHubProtocol_1.JSON_HUB_PROTOCOL_NAME; -var JsonHubProtocol_3 = JsonHubProtocol_1.JsonHubProtocol; - -var Observable = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); -var Subscription = /** @class */ (function () { - function Subscription(subject, observer) { - this.subject = subject; - this.observer = observer; - } - Subscription.prototype.dispose = function () { - var index = this.subject.observers.indexOf(this.observer); - if (index > -1) { - this.subject.observers.splice(index, 1); - } - if (this.subject.observers.length === 0) { - this.subject.cancelCallback().catch(function (_) { }); - } - }; - return Subscription; -}()); -exports.Subscription = Subscription; -var Subject = /** @class */ (function () { - function Subject(cancelCallback) { - this.observers = []; - this.cancelCallback = cancelCallback; - } - Subject.prototype.next = function (item) { - for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { - var observer = _a[_i]; - observer.next(item); - } - }; - Subject.prototype.error = function (err) { - for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { - var observer = _a[_i]; - if (observer.error) { - observer.error(err); - } - } - }; - Subject.prototype.complete = function () { - for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { - var observer = _a[_i]; - if (observer.complete) { - observer.complete(); - } - } - }; - Subject.prototype.subscribe = function (observer) { - this.observers.push(observer); - return new Subscription(this, observer); - }; - return Subject; -}()); -exports.Subject = Subject; - -}); - -unwrapExports(Observable); -var Observable_1 = Observable.Subscription; -var Observable_2 = Observable.Subject; - -var HubConnection_1 = createCommonjsModule(function (module, exports) { -var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [0, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); - - - -exports.JsonHubProtocol = JsonHubProtocol_1.JsonHubProtocol; - - - -var DEFAULT_TIMEOUT_IN_MS = 30 * 1000; -var HubConnection = /** @class */ (function () { - function HubConnection(urlOrConnection, options) { - if (options === void 0) { options = {}; } - var _this = this; - options = options || {}; - this.timeoutInMilliseconds = options.timeoutInMilliseconds || DEFAULT_TIMEOUT_IN_MS; - this.protocol = options.protocol || new JsonHubProtocol_1.JsonHubProtocol(); - if (typeof urlOrConnection === "string") { - this.connection = new HttpConnection_1.HttpConnection(urlOrConnection, options); - } - else { - this.connection = urlOrConnection; - } - this.logger = Loggers.LoggerFactory.createLogger(options.logger); - this.connection.onreceive = function (data) { return _this.processIncomingData(data); }; - this.connection.onclose = function (error) { return _this.connectionClosed(error); }; - this.callbacks = {}; - this.methods = {}; - this.closedCallbacks = []; - this.id = 0; - } - HubConnection.prototype.processIncomingData = function (data) { - this.cleanupTimeout(); - if (!this.receivedHandshakeResponse) { - data = this.processHandshakeResponse(data); - this.receivedHandshakeResponse = true; - } - // Data may have all been read when processing handshake response - if (data) { - // Parse the messages - var messages = this.protocol.parseMessages(data, this.logger); - for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) { - var message = messages_1[_i]; - switch (message.type) { - case 1 /* Invocation */: - this.invokeClientMethod(message); - break; - case 2 /* StreamItem */: - case 3 /* Completion */: - var callback = this.callbacks[message.invocationId]; - if (callback != null) { - if (message.type === 3 /* Completion */) { - delete this.callbacks[message.invocationId]; - } - callback(message); - } - break; - case 6 /* Ping */: - // Don't care about pings - break; - case 7 /* Close */: - this.logger.log(ILogger.LogLevel.Information, "Close message received from server."); - this.connection.stop(message.error ? new Error("Server returned an error on close: " + message.error) : null); - break; - default: - this.logger.log(ILogger.LogLevel.Warning, "Invalid message type: " + message.type); - break; - } - } - } - this.configureTimeout(); - }; - HubConnection.prototype.processHandshakeResponse = function (data) { - var responseMessage; - var messageData; - var remainingData; - try { - if (data instanceof ArrayBuffer) { - // Format is binary but still need to read JSON text from handshake response - var binaryData = new Uint8Array(data); - var separatorIndex = binaryData.indexOf(TextMessageFormat_1.TextMessageFormat.RecordSeparatorCode); - if (separatorIndex === -1) { - throw new Error("Message is incomplete."); - } - // content before separator is handshake response - // optional content after is additional messages - var responseLength = separatorIndex + 1; - messageData = String.fromCharCode.apply(null, binaryData.slice(0, responseLength)); - remainingData = (binaryData.byteLength > responseLength) ? binaryData.slice(responseLength).buffer : null; - } - else { - var textData = data; - var separatorIndex = textData.indexOf(TextMessageFormat_1.TextMessageFormat.RecordSeparator); - if (separatorIndex === -1) { - throw new Error("Message is incomplete."); - } - // content before separator is handshake response - // optional content after is additional messages - var responseLength = separatorIndex + 1; - messageData = textData.substring(0, responseLength); - remainingData = (textData.length > responseLength) ? textData.substring(responseLength) : null; - } - // At this point we should have just the single handshake message - var messages = TextMessageFormat_1.TextMessageFormat.parse(messageData); - responseMessage = JSON.parse(messages[0]); - } - catch (e) { - var message = "Error parsing handshake response: " + e; - this.logger.log(ILogger.LogLevel.Error, message); - var error = new Error(message); - this.connection.stop(error); - throw error; - } - if (responseMessage.error) { - var message = "Server returned handshake error: " + responseMessage.error; - this.logger.log(ILogger.LogLevel.Error, message); - this.connection.stop(new Error(message)); - } - else { - this.logger.log(ILogger.LogLevel.Trace, "Server handshake complete."); - } - // multiple messages could have arrived with handshake - // return additional data to be parsed as usual, or null if all parsed - return remainingData; - }; - HubConnection.prototype.configureTimeout = function () { - var _this = this; - if (!this.connection.features || !this.connection.features.inherentKeepAlive) { - // Set the timeout timer - this.timeoutHandle = setTimeout(function () { return _this.serverTimeout(); }, this.timeoutInMilliseconds); - } - }; - HubConnection.prototype.serverTimeout = function () { - // The server hasn't talked to us in a while. It doesn't like us anymore ... :( - // Terminate the connection - this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server.")); - }; - HubConnection.prototype.invokeClientMethod = function (invocationMessage) { - var _this = this; - var methods = this.methods[invocationMessage.target.toLowerCase()]; - if (methods) { - methods.forEach(function (m) { return m.apply(_this, invocationMessage.arguments); }); - if (invocationMessage.invocationId) { - // This is not supported in v1. So we return an error to avoid blocking the server waiting for the response. - var message = "Server requested a response, which is not supported in this version of the client."; - this.logger.log(ILogger.LogLevel.Error, message); - this.connection.stop(new Error(message)); - } - } - else { - this.logger.log(ILogger.LogLevel.Warning, "No client method with the name '" + invocationMessage.target + "' found."); - } - }; - HubConnection.prototype.connectionClosed = function (error) { - var _this = this; - var callbacks = this.callbacks; - this.callbacks = {}; - Object.keys(callbacks) - .forEach(function (key) { - var callback = callbacks[key]; - callback(undefined, error ? error : new Error("Invocation canceled due to connection being closed.")); - }); - this.cleanupTimeout(); - this.closedCallbacks.forEach(function (c) { return c.apply(_this, [error]); }); - }; - HubConnection.prototype.start = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.logger.log(ILogger.LogLevel.Trace, "Starting HubConnection."); - this.receivedHandshakeResponse = false; - return [4 /*yield*/, this.connection.start(this.protocol.transferFormat)]; - case 1: - _a.sent(); - this.logger.log(ILogger.LogLevel.Trace, "Sending handshake request."); - // Handshake request is always JSON - return [4 /*yield*/, this.connection.send(TextMessageFormat_1.TextMessageFormat.write(JSON.stringify({ protocol: this.protocol.name, version: this.protocol.version })))]; - case 2: - // Handshake request is always JSON - _a.sent(); - this.logger.log(ILogger.LogLevel.Information, "Using HubProtocol '" + this.protocol.name + "'."); - // defensively cleanup timeout in case we receive a message from the server before we finish start - this.cleanupTimeout(); - this.configureTimeout(); - return [2 /*return*/]; - } - }); - }); - }; - HubConnection.prototype.stop = function () { - this.logger.log(ILogger.LogLevel.Trace, "Stopping HubConnection."); - this.cleanupTimeout(); - return this.connection.stop(); - }; - HubConnection.prototype.stream = function (methodName) { - var _this = this; - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - var invocationDescriptor = this.createStreamInvocation(methodName, args); - var subject = new Observable.Subject(function () { - var cancelInvocation = _this.createCancelInvocation(invocationDescriptor.invocationId); - var cancelMessage = _this.protocol.writeMessage(cancelInvocation); - delete _this.callbacks[invocationDescriptor.invocationId]; - return _this.connection.send(cancelMessage); - }); - this.callbacks[invocationDescriptor.invocationId] = function (invocationEvent, error) { - if (error) { - subject.error(error); - return; - } - if (invocationEvent.type === 3 /* Completion */) { - if (invocationEvent.error) { - subject.error(new Error(invocationEvent.error)); - } - else { - subject.complete(); - } - } - else { - subject.next((invocationEvent.item)); - } - }; - var message = this.protocol.writeMessage(invocationDescriptor); - this.connection.send(message) - .catch(function (e) { - subject.error(e); - delete _this.callbacks[invocationDescriptor.invocationId]; - }); - return subject; - }; - HubConnection.prototype.send = function (methodName) { - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - var invocationDescriptor = this.createInvocation(methodName, args, true); - var message = this.protocol.writeMessage(invocationDescriptor); - return this.connection.send(message); - }; - HubConnection.prototype.invoke = function (methodName) { - var _this = this; - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - var invocationDescriptor = this.createInvocation(methodName, args, false); - var p = new Promise(function (resolve, reject) { - _this.callbacks[invocationDescriptor.invocationId] = function (invocationEvent, error) { - if (error) { - reject(error); - return; - } - if (invocationEvent.type === 3 /* Completion */) { - var completionMessage = invocationEvent; - if (completionMessage.error) { - reject(new Error(completionMessage.error)); - } - else { - resolve(completionMessage.result); - } - } - else { - reject(new Error("Unexpected message type: " + invocationEvent.type)); - } - }; - var message = _this.protocol.writeMessage(invocationDescriptor); - _this.connection.send(message) - .catch(function (e) { - reject(e); - delete _this.callbacks[invocationDescriptor.invocationId]; - }); - }); - return p; - }; - HubConnection.prototype.on = function (methodName, newMethod) { - if (!methodName || !newMethod) { - return; - } - methodName = methodName.toLowerCase(); - if (!this.methods[methodName]) { - this.methods[methodName] = []; - } - // Preventing adding the same handler multiple times. - if (this.methods[methodName].indexOf(newMethod) !== -1) { - return; - } - this.methods[methodName].push(newMethod); - }; - HubConnection.prototype.off = function (methodName, method) { - if (!methodName) { - return; - } - methodName = methodName.toLowerCase(); - var handlers = this.methods[methodName]; - if (!handlers) { - return; - } - if (method) { - var removeIdx = handlers.indexOf(method); - if (removeIdx !== -1) { - handlers.splice(removeIdx, 1); - if (handlers.length === 0) { - delete this.methods[methodName]; - } - } - } - else { - delete this.methods[methodName]; - } - }; - HubConnection.prototype.onclose = function (callback) { - if (callback) { - this.closedCallbacks.push(callback); - } - }; - HubConnection.prototype.cleanupTimeout = function () { - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); - } - }; - HubConnection.prototype.createInvocation = function (methodName, args, nonblocking) { - if (nonblocking) { - return { - arguments: args, - target: methodName, - type: 1 /* Invocation */, - }; - } - else { - var id = this.id; - this.id++; - return { - arguments: args, - invocationId: id.toString(), - target: methodName, - type: 1 /* Invocation */, - }; - } - }; - HubConnection.prototype.createStreamInvocation = function (methodName, args) { - var id = this.id; - this.id++; - return { - arguments: args, - invocationId: id.toString(), - target: methodName, - type: 4 /* StreamInvocation */, - }; - }; - HubConnection.prototype.createCancelInvocation = function (id) { - return { - invocationId: id, - type: 5 /* CancelInvocation */, - }; - }; - return HubConnection; -}()); -exports.HubConnection = HubConnection; - -}); - -unwrapExports(HubConnection_1); -var HubConnection_2 = HubConnection_1.JsonHubProtocol; -var HubConnection_3 = HubConnection_1.HubConnection; - -var IHubProtocol = createCommonjsModule(function (module, exports) { -Object.defineProperty(exports, "__esModule", { value: true }); - -}); - -unwrapExports(IHubProtocol); - -var cjs = createCommonjsModule(function (module, exports) { -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(Errors); -__export(HttpClient_1); -__export(HttpConnection_1); -__export(HubConnection_1); -__export(IHubProtocol); -__export(ILogger); -__export(Loggers); -__export(Transports); -__export(Observable); - -}); - -unwrapExports(cjs); - -var browserIndex = createCommonjsModule(function (module, exports) { -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -// This is where we add any polyfills we'll need for the browser. It is the entry module for browser-specific builds. - -__export(cjs); - -}); - -var browserIndex$1 = unwrapExports(browserIndex); - -return browserIndex$1; + typeof define === 'function' && define.amd ? define(factory) : + (global.signalR = factory()); +}(this, (function () { + 'use strict'; + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function commonjsRequire() { + throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); + } + + function unwrapExports(x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var es6Promise_auto = createCommonjsModule(function (module, exports) { + /*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version v4.2.2+97478eb6 + */ + + (function (global, factory) { + module.exports = factory(); + }(commonjsGlobal, (function () { + function objectOrFunction(x) { + var type = typeof x; + return x !== null && (type === 'object' || type === 'function'); + } + + function isFunction(x) { + return typeof x === 'function'; + } + + + + var _isArray = void 0; + if (Array.isArray) { + _isArray = Array.isArray; + } else { + _isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; + } + + var isArray = _isArray; + + var len = 0; + var vertxNext = void 0; + var customSchedulerFn = void 0; + + var asap = function asap(callback, arg) { + queue[len] = callback; + queue[len + 1] = arg; + len += 2; + if (len === 2) { + // If len is 2, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + if (customSchedulerFn) { + customSchedulerFn(flush); + } else { + scheduleFlush(); + } + } + }; + + function setScheduler(scheduleFn) { + customSchedulerFn = scheduleFn; + } + + function setAsap(asapFn) { + asap = asapFn; + } + + var browserWindow = typeof window !== 'undefined' ? window : undefined; + var browserGlobal = browserWindow || {}; + var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; + var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; + + // test for web worker but not in IE10 + var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; + + // node + function useNextTick() { + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // see https://github.com/cujojs/when/issues/410 for details + return function () { + return process.nextTick(flush); + }; + } + + // vertx + function useVertxTimer() { + if (typeof vertxNext !== 'undefined') { + return function () { + vertxNext(flush); + }; + } + + return useSetTimeout(); + } + + function useMutationObserver() { + var iterations = 0; + var observer = new BrowserMutationObserver(flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + + return function () { + node.data = iterations = ++iterations % 2; + }; + } + + // web worker + function useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = flush; + return function () { + return channel.port2.postMessage(0); + }; + } + + function useSetTimeout() { + // Store setTimeout reference so es6-promise will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + var globalSetTimeout = setTimeout; + return function () { + return globalSetTimeout(flush, 1); + }; + } + + var queue = new Array(1000); + function flush() { + for (var i = 0; i < len; i += 2) { + var callback = queue[i]; + var arg = queue[i + 1]; + + callback(arg); + + queue[i] = undefined; + queue[i + 1] = undefined; + } + + len = 0; + } + + function attemptVertx() { + try { + var r = commonjsRequire; + var vertx = r('vertx'); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch (e) { + return useSetTimeout(); + } + } + + var scheduleFlush = void 0; + // Decide what async method to use to triggering processing of queued callbacks: + if (isNode) { + scheduleFlush = useNextTick(); + } else if (BrowserMutationObserver) { + scheduleFlush = useMutationObserver(); + } else if (isWorker) { + scheduleFlush = useMessageChannel(); + } else if (browserWindow === undefined && typeof commonjsRequire === 'function') { + scheduleFlush = attemptVertx(); + } else { + scheduleFlush = useSetTimeout(); + } + + function then(onFulfillment, onRejection) { + var parent = this; + + var child = new this.constructor(noop); + + if (child[PROMISE_ID] === undefined) { + makePromise(child); + } + + var _state = parent._state; + + + if (_state) { + var callback = arguments[_state - 1]; + asap(function () { + return invokeCallback(_state, child, callback, parent._result); + }); + } else { + subscribe(parent, child, onFulfillment, onRejection); + } + + return child; + } + + /** + `Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @static + @param {Any} value value that the returned promise will be resolved with + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` + */ + function resolve$1(object) { + /*jshint validthis:true */ + var Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + var promise = new Constructor(noop); + resolve(promise, object); + return promise; + } + + var PROMISE_ID = Math.random().toString(36).substring(16); + + function noop() { } + + var PENDING = void 0; + var FULFILLED = 1; + var REJECTED = 2; + + var GET_THEN_ERROR = new ErrorObject(); + + function selfFulfillment() { + return new TypeError("You cannot resolve a promise with itself"); + } + + function cannotReturnOwn() { + return new TypeError('A promises callback cannot return that same promise.'); + } + + function getThen(promise) { + try { + return promise.then; + } catch (error) { + GET_THEN_ERROR.error = error; + return GET_THEN_ERROR; + } + } + + function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { + try { + then$$1.call(value, fulfillmentHandler, rejectionHandler); + } catch (e) { + return e; + } + } + + function handleForeignThenable(promise, thenable, then$$1) { + asap(function (promise) { + var sealed = false; + var error = tryThen(then$$1, thenable, function (value) { + if (sealed) { + return; + } + sealed = true; + if (thenable !== value) { + resolve(promise, value); + } else { + fulfill(promise, value); + } + }, function (reason) { + if (sealed) { + return; + } + sealed = true; + + reject(promise, reason); + }, 'Settle: ' + (promise._label || ' unknown promise')); + + if (!sealed && error) { + sealed = true; + reject(promise, error); + } + }, promise); + } + + function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + reject(promise, thenable._result); + } else { + subscribe(thenable, undefined, function (value) { + return resolve(promise, value); + }, function (reason) { + return reject(promise, reason); + }); + } + } + + function handleMaybeThenable(promise, maybeThenable, then$$1) { + if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) { + handleOwnThenable(promise, maybeThenable); + } else { + if (then$$1 === GET_THEN_ERROR) { + reject(promise, GET_THEN_ERROR.error); + GET_THEN_ERROR.error = null; + } else if (then$$1 === undefined) { + fulfill(promise, maybeThenable); + } else if (isFunction(then$$1)) { + handleForeignThenable(promise, maybeThenable, then$$1); + } else { + fulfill(promise, maybeThenable); + } + } + } + + function resolve(promise, value) { + if (promise === value) { + reject(promise, selfFulfillment()); + } else if (objectOrFunction(value)) { + handleMaybeThenable(promise, value, getThen(value)); + } else { + fulfill(promise, value); + } + } + + function publishRejection(promise) { + if (promise._onerror) { + promise._onerror(promise._result); + } + + publish(promise); + } + + function fulfill(promise, value) { + if (promise._state !== PENDING) { + return; + } + + promise._result = value; + promise._state = FULFILLED; + + if (promise._subscribers.length !== 0) { + asap(publish, promise); + } + } + + function reject(promise, reason) { + if (promise._state !== PENDING) { + return; + } + promise._state = REJECTED; + promise._result = reason; + + asap(publishRejection, promise); + } + + function subscribe(parent, child, onFulfillment, onRejection) { + var _subscribers = parent._subscribers; + var length = _subscribers.length; + + + parent._onerror = null; + + _subscribers[length] = child; + _subscribers[length + FULFILLED] = onFulfillment; + _subscribers[length + REJECTED] = onRejection; + + if (length === 0 && parent._state) { + asap(publish, parent); + } + } + + function publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; + + if (subscribers.length === 0) { + return; + } + + var child = void 0, + callback = void 0, + detail = promise._result; + + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + + if (child) { + invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } + + promise._subscribers.length = 0; + } + + function ErrorObject() { + this.error = null; + } + + var TRY_CATCH_ERROR = new ErrorObject(); + + function tryCatch(callback, detail) { + try { + return callback(detail); + } catch (e) { + TRY_CATCH_ERROR.error = e; + return TRY_CATCH_ERROR; + } + } + + function invokeCallback(settled, promise, callback, detail) { + var hasCallback = isFunction(callback), + value = void 0, + error = void 0, + succeeded = void 0, + failed = void 0; + + if (hasCallback) { + value = tryCatch(callback, detail); + + if (value === TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value.error = null; + } else { + succeeded = true; + } + + if (promise === value) { + reject(promise, cannotReturnOwn()); + return; + } + } else { + value = detail; + succeeded = true; + } + + if (promise._state !== PENDING) { + // noop + } else if (hasCallback && succeeded) { + resolve(promise, value); + } else if (failed) { + reject(promise, error); + } else if (settled === FULFILLED) { + fulfill(promise, value); + } else if (settled === REJECTED) { + reject(promise, value); + } + } + + function initializePromise(promise, resolver) { + try { + resolver(function resolvePromise(value) { + resolve(promise, value); + }, function rejectPromise(reason) { + reject(promise, reason); + }); + } catch (e) { + reject(promise, e); + } + } + + var id = 0; + function nextId() { + return id++; + } + + function makePromise(promise) { + promise[PROMISE_ID] = id++; + promise._state = undefined; + promise._result = undefined; + promise._subscribers = []; + } + + function validationError() { + return new Error('Array Methods must be provided an Array'); + } + + function validationError() { + return new Error('Array Methods must be provided an Array'); + } + + var Enumerator = function () { + function Enumerator(Constructor, input) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop); + + if (!this.promise[PROMISE_ID]) { + makePromise(this.promise); + } + + if (isArray(input)) { + this.length = input.length; + this._remaining = input.length; + + this._result = new Array(this.length); + + if (this.length === 0) { + fulfill(this.promise, this._result); + } else { + this.length = this.length || 0; + this._enumerate(input); + if (this._remaining === 0) { + fulfill(this.promise, this._result); + } + } + } else { + reject(this.promise, validationError()); + } + } + + Enumerator.prototype._enumerate = function _enumerate(input) { + for (var i = 0; this._state === PENDING && i < input.length; i++) { + this._eachEntry(input[i], i); + } + }; + + Enumerator.prototype._eachEntry = function _eachEntry(entry, i) { + var c = this._instanceConstructor; + var resolve$$1 = c.resolve; + + + if (resolve$$1 === resolve$1) { + var _then = getThen(entry); + + if (_then === then && entry._state !== PENDING) { + this._settledAt(entry._state, i, entry._result); + } else if (typeof _then !== 'function') { + this._remaining--; + this._result[i] = entry; + } else if (c === Promise$2) { + var promise = new c(noop); + handleMaybeThenable(promise, entry, _then); + this._willSettleAt(promise, i); + } else { + this._willSettleAt(new c(function (resolve$$1) { + return resolve$$1(entry); + }), i); + } + } else { + this._willSettleAt(resolve$$1(entry), i); + } + }; + + Enumerator.prototype._settledAt = function _settledAt(state, i, value) { + var promise = this.promise; + + + if (promise._state === PENDING) { + this._remaining--; + + if (state === REJECTED) { + reject(promise, value); + } else { + this._result[i] = value; + } + } + + if (this._remaining === 0) { + fulfill(promise, this._result); + } + }; + + Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) { + var enumerator = this; + + subscribe(promise, undefined, function (value) { + return enumerator._settledAt(FULFILLED, i, value); + }, function (reason) { + return enumerator._settledAt(REJECTED, i, reason); + }); + }; + + return Enumerator; + }(); + + /** + `Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = reject(new Error("2")); + let promise3 = reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static + */ + function all(entries) { + return new Enumerator(this, entries).promise; + } + + /** + `Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} promises array of promises to observe + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. + */ + function race(entries) { + /*jshint validthis:true */ + var Constructor = this; + + if (!isArray(entries)) { + return new Constructor(function (_, reject) { + return reject(new TypeError('You must pass an array to race.')); + }); + } else { + return new Constructor(function (resolve, reject) { + var length = entries.length; + for (var i = 0; i < length; i++) { + Constructor.resolve(entries[i]).then(resolve, reject); + } + }); + } + } + + /** + `Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {Any} reason value that the returned promise will be rejected with. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + function reject$1(reason) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(noop); + reject(promise, reason); + return promise; + } + + function needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); + } + + function needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); + } + + /** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise's eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @param {Function} resolver + Useful for tooling. + @constructor + */ + + var Promise$2 = function () { + function Promise(resolver) { + this[PROMISE_ID] = nextId(); + this._result = this._state = undefined; + this._subscribers = []; + + if (noop !== resolver) { + typeof resolver !== 'function' && needsResolver(); + this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + } + } + + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + Chaining + -------- + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we're unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + Assimilation + ------------ + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + If the assimliated promise rejects, then the downstream promise will also reject. + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + Simple Example + -------------- + Synchronous Example + ```javascript + let result; + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + Errback Example + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + Promise Example; + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + Advanced Example + -------------- + Synchronous Example + ```javascript + let author, books; + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + Errback Example + ```js + function foundBooks(books) { + } + function failure(reason) { + } + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + Promise Example; + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + @method then + @param {Function} onFulfilled + @param {Function} onRejected + Useful for tooling. + @return {Promise} + */ + + /** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + ```js + function findAuthor(){ + throw new Error('couldn't find that author'); + } + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + @method catch + @param {Function} onRejection + Useful for tooling. + @return {Promise} + */ + + + Promise.prototype.catch = function _catch(onRejection) { + return this.then(null, onRejection); + }; + + /** + `finally` will be invoked regardless of the promise's fate just as native + try/catch/finally behaves + + Synchronous example: + + ```js + findAuthor() { + if (Math.random() > 0.5) { + throw new Error(); + } + return new Author(); + } + + try { + return findAuthor(); // succeed or fail + } catch(error) { + return findOtherAuther(); + } finally { + // always runs + // doesn't affect the return value + } + ``` + + Asynchronous example: + + ```js + findAuthor().catch(function(reason){ + return findOtherAuther(); + }).finally(function(){ + // author was either found, or not + }); + ``` + + @method finally + @param {Function} callback + @return {Promise} + */ + + + Promise.prototype.finally = function _finally(callback) { + var promise = this; + var constructor = promise.constructor; + + return promise.then(function (value) { + return constructor.resolve(callback()).then(function () { + return value; + }); + }, function (reason) { + return constructor.resolve(callback()).then(function () { + throw reason; + }); + }); + }; + + return Promise; + }(); + + Promise$2.prototype.then = then; + Promise$2.all = all; + Promise$2.race = race; + Promise$2.resolve = resolve$1; + Promise$2.reject = reject$1; + Promise$2._setScheduler = setScheduler; + Promise$2._setAsap = setAsap; + Promise$2._asap = asap; + + /*global self*/ + function polyfill() { + var local = void 0; + + if (typeof commonjsGlobal !== 'undefined') { + local = commonjsGlobal; + } else if (typeof self !== 'undefined') { + local = self; + } else { + try { + local = Function('return this')(); + } catch (e) { + throw new Error('polyfill failed because global object is unavailable in this environment'); + } + } + + var P = local.Promise; + + if (P) { + var promiseToString = null; + try { + promiseToString = Object.prototype.toString.call(P.resolve()); + } catch (e) { + // silently ignored + } + + if (promiseToString === '[object Promise]' && !P.cast) { + return; + } + } + + local.Promise = Promise$2; + } + + // Strange compat.. + Promise$2.polyfill = polyfill; + Promise$2.Promise = Promise$2; + + Promise$2.polyfill(); + + return Promise$2; + + }))); + + + + + }); + + var Errors = createCommonjsModule(function (module, exports) { + var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + Object.defineProperty(exports, "__esModule", { value: true }); + var HttpError = /** @class */ (function (_super) { + __extends(HttpError, _super); + function HttpError(errorMessage, statusCode) { + var _newTarget = this.constructor; + var _this = this; + var trueProto = _newTarget.prototype; + _this = _super.call(this, errorMessage) || this; + _this.statusCode = statusCode; + // Workaround issue in Typescript compiler + // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200 + _this.__proto__ = trueProto; + return _this; + } + return HttpError; + }(Error)); + exports.HttpError = HttpError; + var TimeoutError = /** @class */ (function (_super) { + __extends(TimeoutError, _super); + function TimeoutError(errorMessage) { + var _newTarget = this.constructor; + if (errorMessage === void 0) { errorMessage = "A timeout occurred."; } + var _this = this; + var trueProto = _newTarget.prototype; + _this = _super.call(this, errorMessage) || this; + // Workaround issue in Typescript compiler + // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200 + _this.__proto__ = trueProto; + return _this; + } + return TimeoutError; + }(Error)); + exports.TimeoutError = TimeoutError; + + }); + + unwrapExports(Errors); + var Errors_1 = Errors.HttpError; + var Errors_2 = Errors.TimeoutError; + + var ILogger = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + var LogLevel; + (function (LogLevel) { + LogLevel[LogLevel["Trace"] = 0] = "Trace"; + LogLevel[LogLevel["Information"] = 1] = "Information"; + LogLevel[LogLevel["Warning"] = 2] = "Warning"; + LogLevel[LogLevel["Error"] = 3] = "Error"; + LogLevel[LogLevel["None"] = 4] = "None"; + })(LogLevel = exports.LogLevel || (exports.LogLevel = {})); + + }); + + unwrapExports(ILogger); + var ILogger_1 = ILogger.LogLevel; + + var HttpClient_1 = createCommonjsModule(function (module, exports) { + var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + var __assign = (commonjsGlobal && commonjsGlobal.__assign) || Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + + + var HttpResponse = /** @class */ (function () { + function HttpResponse(statusCode, statusText, content) { + this.statusCode = statusCode; + this.statusText = statusText; + this.content = content; + } + return HttpResponse; + }()); + exports.HttpResponse = HttpResponse; + var HttpClient = /** @class */ (function () { + function HttpClient() { + } + HttpClient.prototype.get = function (url, options) { + return this.send(__assign({}, options, { method: "GET", url: url })); + }; + HttpClient.prototype.post = function (url, options) { + return this.send(__assign({}, options, { method: "POST", url: url })); + }; + return HttpClient; + }()); + exports.HttpClient = HttpClient; + var DefaultHttpClient = /** @class */ (function (_super) { + __extends(DefaultHttpClient, _super); + function DefaultHttpClient(logger) { + var _this = _super.call(this) || this; + _this.logger = logger; + return _this; + } + DefaultHttpClient.prototype.send = function (request) { + var _this = this; + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open(request.method, request.url, true); + xhr.withCredentials = true; + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + if (request.headers) { + Object.keys(request.headers) + .forEach(function (header) { return xhr.setRequestHeader(header, request.headers[header]); }); + } + if (request.responseType) { + xhr.responseType = request.responseType; + } + if (request.abortSignal) { + request.abortSignal.onabort = function () { + xhr.abort(); + }; + } + if (request.timeout) { + xhr.timeout = request.timeout; + } + xhr.onload = function () { + if (request.abortSignal) { + request.abortSignal.onabort = null; + } + if (xhr.status >= 200 && xhr.status < 300) { + resolve(new HttpResponse(xhr.status, xhr.statusText, xhr.response || xhr.responseText)); + } + else { + reject(new Errors.HttpError(xhr.statusText, xhr.status)); + } + }; + xhr.onerror = function () { + _this.logger.log(ILogger.LogLevel.Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText); + reject(new Errors.HttpError(xhr.statusText, xhr.status)); + }; + xhr.ontimeout = function () { + _this.logger.log(ILogger.LogLevel.Warning, "Timeout from HTTP request."); + reject(new Errors.TimeoutError()); + }; + xhr.send(request.content || ""); + }); + }; + return DefaultHttpClient; + }(HttpClient)); + exports.DefaultHttpClient = DefaultHttpClient; + + }); + + unwrapExports(HttpClient_1); + var HttpClient_2 = HttpClient_1.HttpResponse; + var HttpClient_3 = HttpClient_1.HttpClient; + var HttpClient_4 = HttpClient_1.DefaultHttpClient; + + var Loggers = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + + var NullLogger = /** @class */ (function () { + function NullLogger() { + } + NullLogger.prototype.log = function (logLevel, message) { + }; + return NullLogger; + }()); + exports.NullLogger = NullLogger; + var ConsoleLogger = /** @class */ (function () { + function ConsoleLogger(minimumLogLevel) { + this.minimumLogLevel = minimumLogLevel; + } + ConsoleLogger.prototype.log = function (logLevel, message) { + if (logLevel >= this.minimumLogLevel) { + switch (logLevel) { + case ILogger.LogLevel.Error: + console.error(ILogger.LogLevel[logLevel] + ": " + message); + break; + case ILogger.LogLevel.Warning: + console.warn(ILogger.LogLevel[logLevel] + ": " + message); + break; + case ILogger.LogLevel.Information: + console.info(ILogger.LogLevel[logLevel] + ": " + message); + break; + default: + console.log(ILogger.LogLevel[logLevel] + ": " + message); + break; + } + } + }; + return ConsoleLogger; + }()); + exports.ConsoleLogger = ConsoleLogger; + var LoggerFactory = /** @class */ (function () { + function LoggerFactory() { + } + LoggerFactory.createLogger = function (logging) { + if (logging === undefined) { + return new ConsoleLogger(ILogger.LogLevel.Information); + } + if (logging === null) { + return new NullLogger(); + } + if (logging.log) { + return logging; + } + return new ConsoleLogger(logging); + }; + return LoggerFactory; + }()); + exports.LoggerFactory = LoggerFactory; + + }); + + unwrapExports(Loggers); + var Loggers_1 = Loggers.NullLogger; + var Loggers_2 = Loggers.ConsoleLogger; + var Loggers_3 = Loggers.LoggerFactory; + + var AbortController_1 = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + // Rough polyfill of https://developer.mozilla.org/en-US/docs/Web/API/AbortController + // We don't actually ever use the API being polyfilled, we always use the polyfill because + // it's a very new API right now. + var AbortController = /** @class */ (function () { + function AbortController() { + this.isAborted = false; + } + AbortController.prototype.abort = function () { + if (!this.isAborted) { + this.isAborted = true; + if (this.onabort) { + this.onabort(); + } + } + }; + Object.defineProperty(AbortController.prototype, "signal", { + get: function () { + return this; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AbortController.prototype, "aborted", { + get: function () { + return this.isAborted; + }, + enumerable: true, + configurable: true + }); + return AbortController; + }()); + exports.AbortController = AbortController; + + }); + + unwrapExports(AbortController_1); + var AbortController_2 = AbortController_1.AbortController; + + var Utils = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + var Arg = /** @class */ (function () { + function Arg() { + } + Arg.isRequired = function (val, name) { + if (val === null || val === undefined) { + throw new Error("The '" + name + "' argument is required."); + } + }; + Arg.isIn = function (val, values, name) { + // TypeScript enums have keys for **both** the name and the value of each enum member on the type itself. + if (!(val in values)) { + throw new Error("Unknown " + name + " value: " + val + "."); + } + }; + return Arg; + }()); + exports.Arg = Arg; + + }); + + unwrapExports(Utils); + var Utils_1 = Utils.Arg; + + var Transports = createCommonjsModule(function (module, exports) { + var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + Object.defineProperty(exports, "__esModule", { value: true }); + + + + + var TransportType; + (function (TransportType) { + TransportType[TransportType["WebSockets"] = 0] = "WebSockets"; + TransportType[TransportType["ServerSentEvents"] = 1] = "ServerSentEvents"; + TransportType[TransportType["LongPolling"] = 2] = "LongPolling"; + })(TransportType = exports.TransportType || (exports.TransportType = {})); + var TransferFormat; + (function (TransferFormat) { + TransferFormat[TransferFormat["Text"] = 1] = "Text"; + TransferFormat[TransferFormat["Binary"] = 2] = "Binary"; + })(TransferFormat = exports.TransferFormat || (exports.TransferFormat = {})); + var WebSocketTransport = /** @class */ (function () { + function WebSocketTransport(accessTokenFactory, logger) { + this.logger = logger; + this.accessTokenFactory = accessTokenFactory || (function () { return null; }); + } + WebSocketTransport.prototype.connect = function (url, transferFormat, connection) { + var _this = this; + Utils.Arg.isRequired(url, "url"); + Utils.Arg.isRequired(transferFormat, "transferFormat"); + Utils.Arg.isIn(transferFormat, TransferFormat, "transferFormat"); + Utils.Arg.isRequired(connection, "connection"); + if (typeof (WebSocket) === "undefined") { + throw new Error("'WebSocket' is not supported in your environment."); + } + this.logger.log(ILogger.LogLevel.Trace, "(WebSockets transport) Connecting"); + return new Promise(function (resolve, reject) { + url = url.replace(/^http/, "ws"); + var token = _this.accessTokenFactory(); + if (token) { + url += (url.indexOf("?") < 0 ? "?" : "&") + ("access_token=" + encodeURIComponent(token)); + } + var webSocket = new WebSocket(url); + if (transferFormat === TransferFormat.Binary) { + webSocket.binaryType = "arraybuffer"; + } + webSocket.onopen = function (event) { + _this.logger.log(ILogger.LogLevel.Information, "WebSocket connected to " + url); + _this.webSocket = webSocket; + resolve(); + }; + webSocket.onerror = function (event) { + reject(event.error); + }; + webSocket.onmessage = function (message) { + _this.logger.log(ILogger.LogLevel.Trace, "(WebSockets transport) data received. " + getDataDetail(message.data) + "."); + if (_this.onreceive) { + _this.onreceive(message.data); + } + }; + webSocket.onclose = function (event) { + // webSocket will be null if the transport did not start successfully + if (_this.onclose && _this.webSocket) { + if (event.wasClean === false || event.code !== 1000) { + _this.onclose(new Error("Websocket closed with status code: " + event.code + " (" + event.reason + ")")); + } + else { + _this.onclose(); + } + } + }; + }); + }; + WebSocketTransport.prototype.send = function (data) { + if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) { + this.logger.log(ILogger.LogLevel.Trace, "(WebSockets transport) sending data. " + getDataDetail(data) + "."); + this.webSocket.send(data); + return Promise.resolve(); + } + return Promise.reject("WebSocket is not in the OPEN state"); + }; + WebSocketTransport.prototype.stop = function () { + if (this.webSocket) { + this.webSocket.close(); + this.webSocket = null; + } + return Promise.resolve(); + }; + return WebSocketTransport; + }()); + exports.WebSocketTransport = WebSocketTransport; + var ServerSentEventsTransport = /** @class */ (function () { + function ServerSentEventsTransport(httpClient, accessTokenFactory, logger) { + this.httpClient = httpClient; + this.accessTokenFactory = accessTokenFactory || (function () { return null; }); + this.logger = logger; + } + ServerSentEventsTransport.prototype.connect = function (url, transferFormat, connection) { + var _this = this; + Utils.Arg.isRequired(url, "url"); + Utils.Arg.isRequired(transferFormat, "transferFormat"); + Utils.Arg.isIn(transferFormat, TransferFormat, "transferFormat"); + Utils.Arg.isRequired(connection, "connection"); + if (typeof (EventSource) === "undefined") { + throw new Error("'EventSource' is not supported in your environment."); + } + this.logger.log(ILogger.LogLevel.Trace, "(SSE transport) Connecting"); + this.url = url; + return new Promise(function (resolve, reject) { + if (transferFormat !== TransferFormat.Text) { + reject(new Error("The Server-Sent Events transport only supports the 'Text' transfer format")); + } + var token = _this.accessTokenFactory(); + if (token) { + url += (url.indexOf("?") < 0 ? "?" : "&") + ("access_token=" + encodeURIComponent(token)); + } + var eventSource = new EventSource(url, { withCredentials: true }); + try { + eventSource.onmessage = function (e) { + if (_this.onreceive) { + try { + _this.logger.log(ILogger.LogLevel.Trace, "(SSE transport) data received. " + getDataDetail(e.data) + "."); + _this.onreceive(e.data); + } + catch (error) { + if (_this.onclose) { + _this.onclose(error); + } + return; + } + } + }; + eventSource.onerror = function (e) { + reject(new Error(e.message || "Error occurred")); + // don't report an error if the transport did not start successfully + if (_this.eventSource && _this.onclose) { + _this.onclose(new Error(e.message || "Error occurred")); + } + }; + eventSource.onopen = function () { + _this.logger.log(ILogger.LogLevel.Information, "SSE connected to " + _this.url); + _this.eventSource = eventSource; + // SSE is a text protocol + resolve(); + }; + } + catch (e) { + return Promise.reject(e); + } + }); + }; + ServerSentEventsTransport.prototype.send = function (data) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, send(this.logger, "SSE", this.httpClient, this.url, this.accessTokenFactory, data)]; + }); + }); + }; + ServerSentEventsTransport.prototype.stop = function () { + if (this.eventSource) { + this.eventSource.close(); + this.eventSource = null; + } + return Promise.resolve(); + }; + return ServerSentEventsTransport; + }()); + exports.ServerSentEventsTransport = ServerSentEventsTransport; + var LongPollingTransport = /** @class */ (function () { + function LongPollingTransport(httpClient, accessTokenFactory, logger) { + this.httpClient = httpClient; + this.accessTokenFactory = accessTokenFactory || (function () { return null; }); + this.logger = logger; + this.pollAbort = new AbortController_1.AbortController(); + } + LongPollingTransport.prototype.connect = function (url, transferFormat, connection) { + Utils.Arg.isRequired(url, "url"); + Utils.Arg.isRequired(transferFormat, "transferFormat"); + Utils.Arg.isIn(transferFormat, TransferFormat, "transferFormat"); + Utils.Arg.isRequired(connection, "connection"); + this.url = url; + this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) Connecting"); + // Set a flag indicating we have inherent keep-alive in this transport. + connection.features.inherentKeepAlive = true; + if (transferFormat === TransferFormat.Binary && (typeof new XMLHttpRequest().responseType !== "string")) { + // This will work if we fix: https://github.com/aspnet/SignalR/issues/742 + throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported."); + } + this.poll(this.url, transferFormat); + return Promise.resolve(); + }; + LongPollingTransport.prototype.poll = function (url, transferFormat) { + return __awaiter(this, void 0, void 0, function () { + var pollOptions, token, pollUrl, response, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + pollOptions = { + abortSignal: this.pollAbort.signal, + headers: {}, + timeout: 90000, + }; + if (transferFormat === TransferFormat.Binary) { + pollOptions.responseType = "arraybuffer"; + } + token = this.accessTokenFactory(); + if (token) { + // tslint:disable-next-line:no-string-literal + pollOptions.headers["Authorization"] = "Bearer " + token; + } + _a.label = 1; + case 1: + if (!!this.pollAbort.signal.aborted) return [3 /*break*/, 6]; + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + pollUrl = url + "&_=" + Date.now(); + this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl); + return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)]; + case 3: + response = _a.sent(); + if (response.statusCode === 204) { + this.logger.log(ILogger.LogLevel.Information, "(LongPolling transport) Poll terminated by server"); + // Poll terminated by server + if (this.onclose) { + this.onclose(); + } + this.pollAbort.abort(); + } + else if (response.statusCode !== 200) { + this.logger.log(ILogger.LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode); + // Unexpected status code + if (this.onclose) { + this.onclose(new Errors.HttpError(response.statusText, response.statusCode)); + } + this.pollAbort.abort(); + } + else { + // Process the response + if (response.content) { + this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) data received. " + getDataDetail(response.content) + "."); + if (this.onreceive) { + this.onreceive(response.content); + } + } + else { + // This is another way timeout manifest. + this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) Poll timed out, reissuing."); + } + } + return [3 /*break*/, 5]; + case 4: + e_1 = _a.sent(); + if (e_1 instanceof Errors.TimeoutError) { + // Ignore timeouts and reissue the poll. + this.logger.log(ILogger.LogLevel.Trace, "(LongPolling transport) Poll timed out, reissuing."); + } + else { + // Close the connection with the error as the result. + if (this.onclose) { + this.onclose(e_1); + } + this.pollAbort.abort(); + } + return [3 /*break*/, 5]; + case 5: return [3 /*break*/, 1]; + case 6: return [2 /*return*/]; + } + }); + }); + }; + LongPollingTransport.prototype.send = function (data) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, send(this.logger, "LongPolling", this.httpClient, this.url, this.accessTokenFactory, data)]; + }); + }); + }; + LongPollingTransport.prototype.stop = function () { + this.pollAbort.abort(); + return Promise.resolve(); + }; + return LongPollingTransport; + }()); + exports.LongPollingTransport = LongPollingTransport; + function getDataDetail(data) { + var length = null; + if (data instanceof ArrayBuffer) { + length = "Binary data of length " + data.byteLength; + } + else if (typeof data === "string") { + length = "String data of length " + data.length; + } + return length; + } + function send(logger, transportName, httpClient, url, accessTokenFactory, content) { + return __awaiter(this, void 0, void 0, function () { + var headers, token, response, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + token = accessTokenFactory(); + if (token) { + headers = (_a = {}, _a["Authorization"] = "Bearer " + accessTokenFactory(), _a); + } + logger.log(ILogger.LogLevel.Trace, "(" + transportName + " transport) sending data. " + getDataDetail(content) + "."); + return [4 /*yield*/, httpClient.post(url, { + content: content, + headers: headers, + })]; + case 1: + response = _b.sent(); + logger.log(ILogger.LogLevel.Trace, "(" + transportName + " transport) request complete. Response status: " + response.statusCode + "."); + return [2 /*return*/]; + } + }); + }); + } + + }); + + unwrapExports(Transports); + var Transports_1 = Transports.TransportType; + var Transports_2 = Transports.TransferFormat; + var Transports_3 = Transports.WebSocketTransport; + var Transports_4 = Transports.ServerSentEventsTransport; + var Transports_5 = Transports.LongPollingTransport; + + var HttpConnection_1 = createCommonjsModule(function (module, exports) { + var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + Object.defineProperty(exports, "__esModule", { value: true }); + + + + + + var HttpConnection = /** @class */ (function () { + function HttpConnection(url, options) { + if (options === void 0) { options = {}; } + this.features = {}; + Utils.Arg.isRequired(url, "url"); + this.logger = Loggers.LoggerFactory.createLogger(options.logger); + this.baseUrl = this.resolveUrl(url); + options = options || {}; + options.accessTokenFactory = options.accessTokenFactory || (function () { return null; }); + this.httpClient = options.httpClient || new HttpClient_1.DefaultHttpClient(this.logger); + this.connectionState = 2 /* Disconnected */; + this.options = options; + } + HttpConnection.prototype.start = function (transferFormat) { + Utils.Arg.isRequired(transferFormat, "transferFormat"); + Utils.Arg.isIn(transferFormat, Transports.TransferFormat, "transferFormat"); + this.logger.log(ILogger.LogLevel.Trace, "Starting connection with transfer format '" + Transports.TransferFormat[transferFormat] + "'."); + if (this.connectionState !== 2 /* Disconnected */) { + return Promise.reject(new Error("Cannot start a connection that is not in the 'Disconnected' state.")); + } + this.connectionState = 0 /* Connecting */; + this.startPromise = this.startInternal(transferFormat); + return this.startPromise; + }; + HttpConnection.prototype.startInternal = function (transferFormat) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + var token, headers, negotiateResponse, e_1, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _b.trys.push([0, 6, , 7]); + if (!(this.options.transport === Transports.TransportType.WebSockets)) return [3 /*break*/, 2]; + // No need to add a connection ID in this case + this.url = this.baseUrl; + this.transport = this.constructTransport(Transports.TransportType.WebSockets); + // We should just call connect directly in this case. + // No fallback or negotiate in this case. + return [4 /*yield*/, this.transport.connect(this.url, transferFormat, this)]; + case 1: + // We should just call connect directly in this case. + // No fallback or negotiate in this case. + _b.sent(); + return [3 /*break*/, 5]; + case 2: + token = this.options.accessTokenFactory(); + headers = void 0; + if (token) { + headers = (_a = {}, _a["Authorization"] = "Bearer " + token, _a); + } + return [4 /*yield*/, this.getNegotiationResponse(headers)]; + case 3: + negotiateResponse = _b.sent(); + // the user tries to stop the the connection when it is being started + if (this.connectionState === 2 /* Disconnected */) { + return [2 /*return*/]; + } + return [4 /*yield*/, this.createTransport(this.options.transport, negotiateResponse, transferFormat, headers)]; + case 4: + _b.sent(); + _b.label = 5; + case 5: + this.transport.onreceive = this.onreceive; + this.transport.onclose = function (e) { return _this.stopConnection(true, e); }; + // only change the state if we were connecting to not overwrite + // the state if the connection is already marked as Disconnected + this.changeState(0 /* Connecting */, 1 /* Connected */); + return [3 /*break*/, 7]; + case 6: + e_1 = _b.sent(); + this.logger.log(ILogger.LogLevel.Error, "Failed to start the connection: " + e_1); + this.connectionState = 2 /* Disconnected */; + this.transport = null; + throw e_1; + case 7: return [2 /*return*/]; + } + }); + }); + }; + HttpConnection.prototype.getNegotiationResponse = function (headers) { + return __awaiter(this, void 0, void 0, function () { + var negotiateUrl, response, e_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + negotiateUrl = this.resolveNegotiateUrl(this.baseUrl); + this.logger.log(ILogger.LogLevel.Trace, "Sending negotiation request: " + negotiateUrl); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.httpClient.post(negotiateUrl, { + content: "", + headers: headers, + })]; + case 2: + response = _a.sent(); + return [2 /*return*/, JSON.parse(response.content)]; + case 3: + e_2 = _a.sent(); + this.logger.log(ILogger.LogLevel.Error, "Failed to complete negotiation with the server: " + e_2); + throw e_2; + case 4: return [2 /*return*/]; + } + }); + }); + }; + HttpConnection.prototype.updateConnectionId = function (negotiateResponse) { + this.connectionId = negotiateResponse.connectionId; + this.url = this.baseUrl + (this.baseUrl.indexOf("?") === -1 ? "?" : "&") + ("id=" + this.connectionId); + }; + HttpConnection.prototype.createTransport = function (requestedTransport, negotiateResponse, requestedTransferFormat, headers) { + return __awaiter(this, void 0, void 0, function () { + var transports, _i, transports_1, endpoint, transport, ex_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.updateConnectionId(negotiateResponse); + if (!this.isITransport(requestedTransport)) return [3 /*break*/, 2]; + this.logger.log(ILogger.LogLevel.Trace, "Connection was provided an instance of ITransport, using that directly."); + this.transport = requestedTransport; + return [4 /*yield*/, this.transport.connect(this.url, requestedTransferFormat, this)]; + case 1: + _a.sent(); + // only change the state if we were connecting to not overwrite + // the state if the connection is already marked as Disconnected + this.changeState(0 /* Connecting */, 1 /* Connected */); + return [2 /*return*/]; + case 2: + transports = negotiateResponse.availableTransports; + _i = 0, transports_1 = transports; + _a.label = 3; + case 3: + if (!(_i < transports_1.length)) return [3 /*break*/, 9]; + endpoint = transports_1[_i]; + this.connectionState = 0 /* Connecting */; + transport = this.resolveTransport(endpoint, requestedTransport, requestedTransferFormat); + if (!(typeof transport === "number")) return [3 /*break*/, 8]; + this.transport = this.constructTransport(transport); + if (!(negotiateResponse.connectionId === null)) return [3 /*break*/, 5]; + return [4 /*yield*/, this.getNegotiationResponse(headers)]; + case 4: + negotiateResponse = _a.sent(); + this.updateConnectionId(negotiateResponse); + _a.label = 5; + case 5: + _a.trys.push([5, 7, , 8]); + return [4 /*yield*/, this.transport.connect(this.url, requestedTransferFormat, this)]; + case 6: + _a.sent(); + this.changeState(0 /* Connecting */, 1 /* Connected */); + return [2 /*return*/]; + case 7: + ex_1 = _a.sent(); + this.logger.log(ILogger.LogLevel.Error, "Failed to start the transport '" + Transports.TransportType[transport] + "': " + ex_1); + this.connectionState = 2 /* Disconnected */; + negotiateResponse.connectionId = null; + return [3 /*break*/, 8]; + case 8: + _i++; + return [3 /*break*/, 3]; + case 9: throw new Error("Unable to initialize any of the available transports."); + } + }); + }); + }; + HttpConnection.prototype.constructTransport = function (transport) { + switch (transport) { + case Transports.TransportType.WebSockets: + return new Transports.WebSocketTransport(this.options.accessTokenFactory, this.logger); + case Transports.TransportType.ServerSentEvents: + return new Transports.ServerSentEventsTransport(this.httpClient, this.options.accessTokenFactory, this.logger); + case Transports.TransportType.LongPolling: + return new Transports.LongPollingTransport(this.httpClient, this.options.accessTokenFactory, this.logger); + default: + throw new Error("Unknown transport: " + transport + "."); + } + }; + HttpConnection.prototype.resolveTransport = function (endpoint, requestedTransport, requestedTransferFormat) { + var transport = Transports.TransportType[endpoint.transport]; + if (transport === null || transport === undefined) { + this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + endpoint.transport + "' because it is not supported by this client."); + } + else { + var transferFormats = endpoint.transferFormats.map(function (s) { return Transports.TransferFormat[s]; }); + if (!requestedTransport || transport === requestedTransport) { + if (transferFormats.indexOf(requestedTransferFormat) >= 0) { + if ((transport === Transports.TransportType.WebSockets && typeof WebSocket === "undefined") || + (transport === Transports.TransportType.ServerSentEvents && typeof EventSource === "undefined")) { + this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + Transports.TransportType[transport] + "' because it is not supported in your environment.'"); + } + else { + this.logger.log(ILogger.LogLevel.Trace, "Selecting transport '" + Transports.TransportType[transport] + "'"); + return transport; + } + } + else { + this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + Transports.TransportType[transport] + "' because it does not support the requested transfer format '" + Transports.TransferFormat[requestedTransferFormat] + "'."); + } + } + else { + this.logger.log(ILogger.LogLevel.Trace, "Skipping transport '" + Transports.TransportType[transport] + "' because it was disabled by the client."); + } + } + return null; + }; + HttpConnection.prototype.isITransport = function (transport) { + return typeof (transport) === "object" && "connect" in transport; + }; + HttpConnection.prototype.changeState = function (from, to) { + if (this.connectionState === from) { + this.connectionState = to; + return true; + } + return false; + }; + HttpConnection.prototype.send = function (data) { + if (this.connectionState !== 1 /* Connected */) { + throw new Error("Cannot send data if the connection is not in the 'Connected' State."); + } + return this.transport.send(data); + }; + HttpConnection.prototype.stop = function (error) { + return __awaiter(this, void 0, void 0, function () { + var previousState, e_3; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + previousState = this.connectionState; + this.connectionState = 2 /* Disconnected */; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.startPromise]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + e_3 = _a.sent(); + return [3 /*break*/, 4]; + case 4: + this.stopConnection(/*raiseClosed*/ previousState === 1 /* Connected */, error); + return [2 /*return*/]; + } + }); + }); + }; + HttpConnection.prototype.stopConnection = function (raiseClosed, error) { + if (this.transport) { + this.transport.stop(); + this.transport = null; + } + if (error) { + this.logger.log(ILogger.LogLevel.Error, "Connection disconnected with error '" + error + "'."); + } + else { + this.logger.log(ILogger.LogLevel.Information, "Connection disconnected."); + } + this.connectionState = 2 /* Disconnected */; + if (raiseClosed && this.onclose) { + this.onclose(error); + } + }; + HttpConnection.prototype.resolveUrl = function (url) { + // startsWith is not supported in IE + if (url.lastIndexOf("https://", 0) === 0 || url.lastIndexOf("http://", 0) === 0) { + return url; + } + if (typeof window === "undefined" || !window || !window.document) { + throw new Error("Cannot resolve '" + url + "'."); + } + var parser = window.document.createElement("a"); + parser.href = url; + var baseUrl = (!parser.protocol || parser.protocol === ":") + ? window.document.location.protocol + "//" + (parser.host || window.document.location.host) + : parser.protocol + "//" + parser.host; + if (!url || url[0] !== "/") { + url = "/" + url; + } + var normalizedUrl = baseUrl + url; + this.logger.log(ILogger.LogLevel.Information, "Normalizing '" + url + "' to '" + normalizedUrl + "'."); + return normalizedUrl; + }; + HttpConnection.prototype.resolveNegotiateUrl = function (url) { + var index = url.indexOf("?"); + var negotiateUrl = url.substring(0, index === -1 ? url.length : index); + if (negotiateUrl[negotiateUrl.length - 1] !== "/") { + negotiateUrl += "/"; + } + negotiateUrl += "negotiate"; + negotiateUrl += index === -1 ? "" : url.substring(index); + return negotiateUrl; + }; + return HttpConnection; + }()); + exports.HttpConnection = HttpConnection; + + }); + + unwrapExports(HttpConnection_1); + var HttpConnection_2 = HttpConnection_1.HttpConnection; + + var TextMessageFormat_1 = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + var TextMessageFormat = /** @class */ (function () { + function TextMessageFormat() { + } + TextMessageFormat.write = function (output) { + return "" + output + TextMessageFormat.RecordSeparator; + }; + TextMessageFormat.parse = function (input) { + if (input[input.length - 1] !== TextMessageFormat.RecordSeparator) { + throw new Error("Message is incomplete."); + } + var messages = input.split(TextMessageFormat.RecordSeparator); + messages.pop(); + return messages; + }; + TextMessageFormat.RecordSeparatorCode = 0x1e; + TextMessageFormat.RecordSeparator = String.fromCharCode(TextMessageFormat.RecordSeparatorCode); + return TextMessageFormat; + }()); + exports.TextMessageFormat = TextMessageFormat; + + }); + + unwrapExports(TextMessageFormat_1); + var TextMessageFormat_2 = TextMessageFormat_1.TextMessageFormat; + + var JsonHubProtocol_1 = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + + + + + exports.JSON_HUB_PROTOCOL_NAME = "json"; + var JsonHubProtocol = /** @class */ (function () { + function JsonHubProtocol() { + this.name = exports.JSON_HUB_PROTOCOL_NAME; + this.version = 1; + this.transferFormat = Transports.TransferFormat.Text; + } + JsonHubProtocol.prototype.parseMessages = function (input, logger) { + if (!input) { + return []; + } + if (logger === null) { + logger = new Loggers.NullLogger(); + } + // Parse the messages + var messages = TextMessageFormat_1.TextMessageFormat.parse(input); + var hubMessages = []; + for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) { + var message = messages_1[_i]; + var parsedMessage = JSON.parse(message); + if (typeof parsedMessage.type !== "number") { + throw new Error("Invalid payload."); + } + switch (parsedMessage.type) { + case 1 /* Invocation */: + this.isInvocationMessage(parsedMessage); + break; + case 2 /* StreamItem */: + this.isStreamItemMessage(parsedMessage); + break; + case 3 /* Completion */: + this.isCompletionMessage(parsedMessage); + break; + case 6 /* Ping */: + // Single value, no need to validate + break; + case 7 /* Close */: + // All optional values, no need to validate + break; + default: + // Future protocol changes can add message types, old clients can ignore them + logger.log(ILogger.LogLevel.Information, "Unknown message type '" + parsedMessage.type + "' ignored."); + continue; + } + hubMessages.push(parsedMessage); + } + return hubMessages; + }; + JsonHubProtocol.prototype.writeMessage = function (message) { + return TextMessageFormat_1.TextMessageFormat.write(JSON.stringify(message)); + }; + JsonHubProtocol.prototype.isInvocationMessage = function (message) { + this.assertNotEmptyString(message.target, "Invalid payload for Invocation message."); + if (message.invocationId !== undefined) { + this.assertNotEmptyString(message.invocationId, "Invalid payload for Invocation message."); + } + }; + JsonHubProtocol.prototype.isStreamItemMessage = function (message) { + this.assertNotEmptyString(message.invocationId, "Invalid payload for StreamItem message."); + if (message.item === undefined) { + throw new Error("Invalid payload for StreamItem message."); + } + }; + JsonHubProtocol.prototype.isCompletionMessage = function (message) { + if (message.result && message.error) { + throw new Error("Invalid payload for Completion message."); + } + if (!message.result && message.error) { + this.assertNotEmptyString(message.error, "Invalid payload for Completion message."); + } + this.assertNotEmptyString(message.invocationId, "Invalid payload for Completion message."); + }; + JsonHubProtocol.prototype.assertNotEmptyString = function (value, errorMessage) { + if (typeof value !== "string" || value === "") { + throw new Error(errorMessage); + } + }; + return JsonHubProtocol; + }()); + exports.JsonHubProtocol = JsonHubProtocol; + + }); + + unwrapExports(JsonHubProtocol_1); + var JsonHubProtocol_2 = JsonHubProtocol_1.JSON_HUB_PROTOCOL_NAME; + var JsonHubProtocol_3 = JsonHubProtocol_1.JsonHubProtocol; + + var Observable = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + var Subscription = /** @class */ (function () { + function Subscription(subject, observer) { + this.subject = subject; + this.observer = observer; + } + Subscription.prototype.dispose = function () { + var index = this.subject.observers.indexOf(this.observer); + if (index > -1) { + this.subject.observers.splice(index, 1); + } + if (this.subject.observers.length === 0) { + this.subject.cancelCallback().catch(function (_) { }); + } + }; + return Subscription; + }()); + exports.Subscription = Subscription; + var Subject = /** @class */ (function () { + function Subject(cancelCallback) { + this.observers = []; + this.cancelCallback = cancelCallback; + } + Subject.prototype.next = function (item) { + for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { + var observer = _a[_i]; + observer.next(item); + } + }; + Subject.prototype.error = function (err) { + for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { + var observer = _a[_i]; + if (observer.error) { + observer.error(err); + } + } + }; + Subject.prototype.complete = function () { + for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { + var observer = _a[_i]; + if (observer.complete) { + observer.complete(); + } + } + }; + Subject.prototype.subscribe = function (observer) { + this.observers.push(observer); + return new Subscription(this, observer); + }; + return Subject; + }()); + exports.Subject = Subject; + + }); + + unwrapExports(Observable); + var Observable_1 = Observable.Subscription; + var Observable_2 = Observable.Subject; + + var HubConnection_1 = createCommonjsModule(function (module, exports) { + var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + Object.defineProperty(exports, "__esModule", { value: true }); + + + + exports.JsonHubProtocol = JsonHubProtocol_1.JsonHubProtocol; + + + + var DEFAULT_TIMEOUT_IN_MS = 30 * 1000; + var HubConnection = /** @class */ (function () { + function HubConnection(urlOrConnection, options) { + if (options === void 0) { options = {}; } + var _this = this; + options = options || {}; + this.timeoutInMilliseconds = options.timeoutInMilliseconds || DEFAULT_TIMEOUT_IN_MS; + this.protocol = options.protocol || new JsonHubProtocol_1.JsonHubProtocol(); + if (typeof urlOrConnection === "string") { + this.connection = new HttpConnection_1.HttpConnection(urlOrConnection, options); + } + else { + this.connection = urlOrConnection; + } + this.logger = Loggers.LoggerFactory.createLogger(options.logger); + this.connection.onreceive = function (data) { return _this.processIncomingData(data); }; + this.connection.onclose = function (error) { return _this.connectionClosed(error); }; + this.callbacks = {}; + this.methods = {}; + this.closedCallbacks = []; + this.id = 0; + } + HubConnection.prototype.processIncomingData = function (data) { + this.cleanupTimeout(); + if (!this.receivedHandshakeResponse) { + data = this.processHandshakeResponse(data); + this.receivedHandshakeResponse = true; + } + // Data may have all been read when processing handshake response + if (data) { + // Parse the messages + var messages = this.protocol.parseMessages(data, this.logger); + for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) { + var message = messages_1[_i]; + switch (message.type) { + case 1 /* Invocation */: + this.invokeClientMethod(message); + break; + case 2 /* StreamItem */: + case 3 /* Completion */: + var callback = this.callbacks[message.invocationId]; + if (callback != null) { + if (message.type === 3 /* Completion */) { + delete this.callbacks[message.invocationId]; + } + callback(message); + } + break; + case 6 /* Ping */: + // Don't care about pings + break; + case 7 /* Close */: + this.logger.log(ILogger.LogLevel.Information, "Close message received from server."); + this.connection.stop(message.error ? new Error("Server returned an error on close: " + message.error) : null); + break; + default: + this.logger.log(ILogger.LogLevel.Warning, "Invalid message type: " + message.type); + break; + } + } + } + this.configureTimeout(); + }; + HubConnection.prototype.processHandshakeResponse = function (data) { + var responseMessage; + var messageData; + var remainingData; + try { + if (data instanceof ArrayBuffer) { + // Format is binary but still need to read JSON text from handshake response + var binaryData = new Uint8Array(data); + var separatorIndex = binaryData.indexOf(TextMessageFormat_1.TextMessageFormat.RecordSeparatorCode); + if (separatorIndex === -1) { + throw new Error("Message is incomplete."); + } + // content before separator is handshake response + // optional content after is additional messages + var responseLength = separatorIndex + 1; + messageData = String.fromCharCode.apply(null, binaryData.slice(0, responseLength)); + remainingData = (binaryData.byteLength > responseLength) ? binaryData.slice(responseLength).buffer : null; + } + else { + var textData = data; + var separatorIndex = textData.indexOf(TextMessageFormat_1.TextMessageFormat.RecordSeparator); + if (separatorIndex === -1) { + throw new Error("Message is incomplete."); + } + // content before separator is handshake response + // optional content after is additional messages + var responseLength = separatorIndex + 1; + messageData = textData.substring(0, responseLength); + remainingData = (textData.length > responseLength) ? textData.substring(responseLength) : null; + } + // At this point we should have just the single handshake message + var messages = TextMessageFormat_1.TextMessageFormat.parse(messageData); + responseMessage = JSON.parse(messages[0]); + } + catch (e) { + var message = "Error parsing handshake response: " + e; + this.logger.log(ILogger.LogLevel.Error, message); + var error = new Error(message); + this.connection.stop(error); + throw error; + } + if (responseMessage.error) { + var message = "Server returned handshake error: " + responseMessage.error; + this.logger.log(ILogger.LogLevel.Error, message); + this.connection.stop(new Error(message)); + } + else { + this.logger.log(ILogger.LogLevel.Trace, "Server handshake complete."); + } + // multiple messages could have arrived with handshake + // return additional data to be parsed as usual, or null if all parsed + return remainingData; + }; + HubConnection.prototype.configureTimeout = function () { + var _this = this; + if (!this.connection.features || !this.connection.features.inherentKeepAlive) { + // Set the timeout timer + this.timeoutHandle = setTimeout(function () { return _this.serverTimeout(); }, this.timeoutInMilliseconds); + } + }; + HubConnection.prototype.serverTimeout = function () { + // The server hasn't talked to us in a while. It doesn't like us anymore ... :( + // Terminate the connection + this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server.")); + }; + HubConnection.prototype.invokeClientMethod = function (invocationMessage) { + var _this = this; + var methods = this.methods[invocationMessage.target.toLowerCase()]; + if (methods) { + methods.forEach(function (m) { return m.apply(_this, invocationMessage.arguments); }); + if (invocationMessage.invocationId) { + // This is not supported in v1. So we return an error to avoid blocking the server waiting for the response. + var message = "Server requested a response, which is not supported in this version of the client."; + this.logger.log(ILogger.LogLevel.Error, message); + this.connection.stop(new Error(message)); + } + } + else { + this.logger.log(ILogger.LogLevel.Warning, "No client method with the name '" + invocationMessage.target + "' found."); + } + }; + HubConnection.prototype.connectionClosed = function (error) { + var _this = this; + var callbacks = this.callbacks; + this.callbacks = {}; + Object.keys(callbacks) + .forEach(function (key) { + var callback = callbacks[key]; + callback(undefined, error ? error : new Error("Invocation canceled due to connection being closed.")); + }); + this.cleanupTimeout(); + this.closedCallbacks.forEach(function (c) { return c.apply(_this, [error]); }); + }; + HubConnection.prototype.start = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.logger.log(ILogger.LogLevel.Trace, "Starting HubConnection."); + this.receivedHandshakeResponse = false; + return [4 /*yield*/, this.connection.start(this.protocol.transferFormat)]; + case 1: + _a.sent(); + this.logger.log(ILogger.LogLevel.Trace, "Sending handshake request."); + // Handshake request is always JSON + return [4 /*yield*/, this.connection.send(TextMessageFormat_1.TextMessageFormat.write(JSON.stringify({ protocol: this.protocol.name, version: this.protocol.version })))]; + case 2: + // Handshake request is always JSON + _a.sent(); + this.logger.log(ILogger.LogLevel.Information, "Using HubProtocol '" + this.protocol.name + "'."); + // defensively cleanup timeout in case we receive a message from the server before we finish start + this.cleanupTimeout(); + this.configureTimeout(); + return [2 /*return*/]; + } + }); + }); + }; + HubConnection.prototype.stop = function () { + this.logger.log(ILogger.LogLevel.Trace, "Stopping HubConnection."); + this.cleanupTimeout(); + return this.connection.stop(); + }; + HubConnection.prototype.stream = function (methodName) { + var _this = this; + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var invocationDescriptor = this.createStreamInvocation(methodName, args); + var subject = new Observable.Subject(function () { + var cancelInvocation = _this.createCancelInvocation(invocationDescriptor.invocationId); + var cancelMessage = _this.protocol.writeMessage(cancelInvocation); + delete _this.callbacks[invocationDescriptor.invocationId]; + return _this.connection.send(cancelMessage); + }); + this.callbacks[invocationDescriptor.invocationId] = function (invocationEvent, error) { + if (error) { + subject.error(error); + return; + } + if (invocationEvent.type === 3 /* Completion */) { + if (invocationEvent.error) { + subject.error(new Error(invocationEvent.error)); + } + else { + subject.complete(); + } + } + else { + subject.next((invocationEvent.item)); + } + }; + var message = this.protocol.writeMessage(invocationDescriptor); + this.connection.send(message) + .catch(function (e) { + subject.error(e); + delete _this.callbacks[invocationDescriptor.invocationId]; + }); + return subject; + }; + HubConnection.prototype.send = function (methodName) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var invocationDescriptor = this.createInvocation(methodName, args, true); + var message = this.protocol.writeMessage(invocationDescriptor); + return this.connection.send(message); + }; + HubConnection.prototype.invoke = function (methodName) { + var _this = this; + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var invocationDescriptor = this.createInvocation(methodName, args, false); + var p = new Promise(function (resolve, reject) { + _this.callbacks[invocationDescriptor.invocationId] = function (invocationEvent, error) { + if (error) { + reject(error); + return; + } + if (invocationEvent.type === 3 /* Completion */) { + var completionMessage = invocationEvent; + if (completionMessage.error) { + reject(new Error(completionMessage.error)); + } + else { + resolve(completionMessage.result); + } + } + else { + reject(new Error("Unexpected message type: " + invocationEvent.type)); + } + }; + var message = _this.protocol.writeMessage(invocationDescriptor); + _this.connection.send(message) + .catch(function (e) { + reject(e); + delete _this.callbacks[invocationDescriptor.invocationId]; + }); + }); + return p; + }; + HubConnection.prototype.on = function (methodName, newMethod) { + if (!methodName || !newMethod) { + return; + } + methodName = methodName.toLowerCase(); + if (!this.methods[methodName]) { + this.methods[methodName] = []; + } + // Preventing adding the same handler multiple times. + if (this.methods[methodName].indexOf(newMethod) !== -1) { + return; + } + this.methods[methodName].push(newMethod); + }; + HubConnection.prototype.off = function (methodName, method) { + if (!methodName) { + return; + } + methodName = methodName.toLowerCase(); + var handlers = this.methods[methodName]; + if (!handlers) { + return; + } + if (method) { + var removeIdx = handlers.indexOf(method); + if (removeIdx !== -1) { + handlers.splice(removeIdx, 1); + if (handlers.length === 0) { + delete this.methods[methodName]; + } + } + } + else { + delete this.methods[methodName]; + } + }; + HubConnection.prototype.onclose = function (callback) { + if (callback) { + this.closedCallbacks.push(callback); + } + }; + HubConnection.prototype.cleanupTimeout = function () { + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); + } + }; + HubConnection.prototype.createInvocation = function (methodName, args, nonblocking) { + if (nonblocking) { + return { + arguments: args, + target: methodName, + type: 1 /* Invocation */, + }; + } + else { + var id = this.id; + this.id++; + return { + arguments: args, + invocationId: id.toString(), + target: methodName, + type: 1 /* Invocation */, + }; + } + }; + HubConnection.prototype.createStreamInvocation = function (methodName, args) { + var id = this.id; + this.id++; + return { + arguments: args, + invocationId: id.toString(), + target: methodName, + type: 4 /* StreamInvocation */, + }; + }; + HubConnection.prototype.createCancelInvocation = function (id) { + return { + invocationId: id, + type: 5 /* CancelInvocation */, + }; + }; + return HubConnection; + }()); + exports.HubConnection = HubConnection; + + }); + + unwrapExports(HubConnection_1); + var HubConnection_2 = HubConnection_1.JsonHubProtocol; + var HubConnection_3 = HubConnection_1.HubConnection; + + var IHubProtocol = createCommonjsModule(function (module, exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + + }); + + unwrapExports(IHubProtocol); + + var cjs = createCommonjsModule(function (module, exports) { + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + Object.defineProperty(exports, "__esModule", { value: true }); + __export(Errors); + __export(HttpClient_1); + __export(HttpConnection_1); + __export(HubConnection_1); + __export(IHubProtocol); + __export(ILogger); + __export(Loggers); + __export(Transports); + __export(Observable); + + }); + + unwrapExports(cjs); + + var browserIndex = createCommonjsModule(function (module, exports) { + function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + Object.defineProperty(exports, "__esModule", { value: true }); + // This is where we add any polyfills we'll need for the browser. It is the entry module for browser-specific builds. + + __export(cjs); + + }); + + var browserIndex$1 = unwrapExports(browserIndex); + + return browserIndex$1; }))); //# sourceMappingURL=signalr.js.map diff --git a/src/Web/WebMVC/wwwroot/js/site.min.js b/src/Web/WebMVC/wwwroot/js/site.min.js index f49f27c16..1f86f60f3 100644 --- a/src/Web/WebMVC/wwwroot/js/site.min.js +++ b/src/Web/WebMVC/wwwroot/js/site.min.js @@ -4,10 +4,10 @@ */ (function(n,t){typeof exports=="object"&&typeof module!="undefined"?module.exports=t():typeof define=="function"&&define.amd?define(t):n.signalR=t()})(this,function(){"use strict";function w(){throw new Error("Dynamic requires are not currently supported by rollup-plugin-commonjs");}function f(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n["default"]:n}function u(n,t){return t={exports:{}},n(t,t.exports),t.exports}var i=typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},ut=u(function(n){ /*! - * @overview es6-promise - a tiny implementation of Promises/A+. - * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) - * @license Licensed under MIT license - * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE - * @version v4.2.2+97478eb6 - */ + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version v4.2.2+97478eb6 + */ (function(t,i){n.exports=i()})(i,function(){function bt(n){var t=typeof n;return n!==null&&(t==="object"||t==="function")}function ft(n){return typeof n=="function"}function kt(n){k=n}function dt(n){u=n}function ti(){return function(){return process.nextTick(o)}}function ii(){return typeof b!="undefined"?function(){b(o)}:d()}function ri(){var n=0,i=new ct(o),t=document.createTextNode("");return i.observe(t,{characterData:!0}),function(){t.data=n=++n%2}}function ui(){var n=new MessageChannel;return n.port1.onmessage=o,function(){return n.port2.postMessage(0)}}function d(){var n=setTimeout;return function(){return n(o,1)}}function o(){for(var t,i,n=0;n=200&&o.status<300?r(new u(o.status,o.statusText,o.response||o.responseText)):f(new e.HttpError(o.statusText,o.status))};o.onerror=function(){i.logger.log(n.LogLevel.Warning,"Error from HTTP request. "+o.status+": "+o.statusText);f(new e.HttpError(o.statusText,o.status))};o.ontimeout=function(){i.logger.log(n.LogLevel.Warning,"Timeout from HTTP request.");f(new e.TimeoutError)};o.send(t.content||"")})},i}(f);r.DefaultHttpClient=s});f(h);var ot=h.HttpResponse,st=h.HttpClient,ht=h.DefaultHttpClient,s=u(function(t,i){var u,r,f;Object.defineProperty(i,"__esModule",{value:!0});u=function(){function n(){}return n.prototype.log=function(){},n}();i.NullLogger=u;r=function(){function t(n){this.minimumLogLevel=n}return t.prototype.log=function(t,i){if(t>=this.minimumLogLevel)switch(t){case n.LogLevel.Error:console.error(n.LogLevel[t]+": "+i);break;case n.LogLevel.Warning:console.warn(n.LogLevel[t]+": "+i);break;case n.LogLevel.Information:console.info(n.LogLevel[t]+": "+i);break;default:console.log(n.LogLevel[t]+": "+i)}},t}();i.ConsoleLogger=r;f=function(){function t(){}return t.createLogger=function(t){return t===undefined?new r(n.LogLevel.Information):t===null?new u:t.log?t:new r(t)},t}();i.LoggerFactory=f});f(s);var ct=s.NullLogger,lt=s.ConsoleLogger,at=s.LoggerFactory,y=u(function(n,t){Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function n(){this.isAborted=!1}return n.prototype.abort=function(){this.isAborted||(this.isAborted=!0,this.onabort&&this.onabort())},Object.defineProperty(n.prototype,"signal",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(n.prototype,"aborted",{get:function(){return this.isAborted},enumerable:!0,configurable:!0}),n}();t.AbortController=i});f(y);nt=y.AbortController;r=u(function(n,t){Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function n(){}return n.isRequired=function(n,t){if(n===null||n===undefined)throw new Error("The '"+t+"' argument is required.");},n.isIn=function(n,t,i){if(!(n in t))throw new Error("Unknown "+i+" value: "+n+".");},n}();t.Arg=i});f(r);tt=r.Arg;t=u(function(t,u){function o(n){var t=null;return n instanceof ArrayBuffer?t="Binary data of length "+n.byteLength:typeof n=="string"&&(t="String data of length "+n.length),t}function v(t,i,r,u,f,e){return s(this,void 0,void 0,function(){var c,l,a,s;return h(this,function(h){switch(h.label){case 0:return l=f(),l&&(c=(s={},s.Authorization="Bearer "+f(),s)),t.log(n.LogLevel.Trace,"("+i+" transport) sending data. "+o(e)+"."),[4,r.post(u,{content:e,headers:c})];case 1:return a=h.sent(),t.log(n.LogLevel.Trace,"("+i+" transport) request complete. Response status: "+a.statusCode+"."),[2]}})})}var s=i&&i.__awaiter||function(n,t,i,r){return new(i||(i=Promise))(function(u,f){function o(n){try{e(r.next(n))}catch(t){f(t)}}function s(n){try{e(r["throw"](n))}catch(t){f(t)}}function e(n){n.done?u(n.value):new i(function(t){t(n.value)}).then(o,s)}e((r=r.apply(n,t||[])).next())})},h=i&&i.__generator||function(n,t){function o(n){return function(t){return s([n,t])}}function s(e){if(f)throw new TypeError("Generator is already executing.");while(r)try{if(f=1,u&&(i=u[e[0]&2?"return":e[0]?"throw":"next"])&&!(i=i.call(u,e[1])).done)return i;(u=0,i)&&(e=[0,i.value]);switch(e[0]){case 0:case 1:i=e;break;case 4:return r.label++,{value:e[1],done:!1};case 5:r.label++;u=e[1];e=[0];continue;case 7:e=r.ops.pop();r.trys.pop();continue;default:if(!(i=r.trys,i=i.length>0&&i[i.length-1])&&(e[0]===6||e[0]===2)){r=0;continue}if(e[0]===3&&(!i||e[1]>i[0]&&e[1]0&&i[i.length-1])&&(e[0]===6||e[0]===2)){r=0;continue}if(e[0]===3&&(!i||e[1]>i[0]&&e[1]=0)if(f===t.TransportType.WebSockets&&typeof WebSocket=="undefined"||f===t.TransportType.ServerSentEvents&&typeof EventSource=="undefined")this.logger.log(n.LogLevel.Trace,"Skipping transport '"+t.TransportType[f]+"' because it is not supported in your environment.'");else return this.logger.log(n.LogLevel.Trace,"Selecting transport '"+t.TransportType[f]+"'"),f;else this.logger.log(n.LogLevel.Trace,"Skipping transport '"+t.TransportType[f]+"' because it does not support the requested transfer format '"+t.TransferFormat[u]+"'.");return null},i.prototype.isITransport=function(n){return typeof n=="object"&&"connect"in n},i.prototype.changeState=function(n,t){return this.connectionState===n?(this.connectionState=t,!0):!1},i.prototype.send=function(n){if(this.connectionState!==1)throw new Error("Cannot send data if the connection is not in the 'Connected' State.");return this.transport.send(n)},i.prototype.stop=function(n){return e(this,void 0,void 0,function(){var t,i;return o(this,function(r){switch(r.label){case 0:t=this.connectionState;this.connectionState=2;r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this.startPromise];case 2:return r.sent(),[3,4];case 3:return i=r.sent(),[3,4];case 4:return this.stopConnection(t===1,n),[2]}})})},i.prototype.stopConnection=function(t,i){if(this.transport&&(this.transport.stop(),this.transport=null),i?this.logger.log(n.LogLevel.Error,"Connection disconnected with error '"+i+"'."):this.logger.log(n.LogLevel.Information,"Connection disconnected."),this.connectionState=2,t&&this.onclose)this.onclose(i)},i.prototype.resolveUrl=function(t){var i,u,r;if(t.lastIndexOf("https://",0)===0||t.lastIndexOf("http://",0)===0)return t;if(typeof window=="undefined"||!window||!window.document)throw new Error("Cannot resolve '"+t+"'.");return i=window.document.createElement("a"),i.href=t,u=!i.protocol||i.protocol===":"?window.document.location.protocol+"//"+(i.host||window.document.location.host):i.protocol+"//"+i.host,t&&t[0]==="/"||(t="/"+t),r=u+t,this.logger.log(n.LogLevel.Information,"Normalizing '"+t+"' to '"+r+"'."),r},i.prototype.resolveNegotiateUrl=function(n){var i=n.indexOf("?"),t=n.substring(0,i===-1?n.length:i);return t[t.length-1]!=="/"&&(t+="/"),t+="negotiate",t+(i===-1?"":n.substring(i))},i}();f.HttpConnection=c});f(a);it=a.HttpConnection;o=u(function(n,t){Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function n(){}return n.write=function(t){return""+t+n.RecordSeparator},n.parse=function(t){if(t[t.length-1]!==n.RecordSeparator)throw new Error("Message is incomplete.");var i=t.split(n.RecordSeparator);return i.pop(),i},n.RecordSeparatorCode=30,n.RecordSeparator=String.fromCharCode(n.RecordSeparatorCode),n}();t.TextMessageFormat=i});f(o);rt=o.TextMessageFormat;c=u(function(i,r){Object.defineProperty(r,"__esModule",{value:!0});r.JSON_HUB_PROTOCOL_NAME="json";var u=function(){function i(){this.name=r.JSON_HUB_PROTOCOL_NAME;this.version=1;this.transferFormat=t.TransferFormat.Text}return i.prototype.parseMessages=function(t,i){var h,f,u,e,c,r;if(!t)return[];for(i===null&&(i=new s.NullLogger),h=o.TextMessageFormat.parse(t),f=[],u=0,e=h;u-1&&this.subject.observers.splice(n,1);this.subject.observers.length===0&&this.subject.cancelCallback().catch(function(){})},n}();t.Subscription=i;r=function(){function n(n){this.observers=[];this.cancelCallback=n}return n.prototype.next=function(n){for(var r,t=0,i=this.observers;t0&&i[i.length-1])&&(e[0]===6||e[0]===2)){r=0;continue}if(e[0]===3&&(!i||e[1]>i[0]&&e[1]i?f.slice(i).buffer:null}else{if(e=t,r=e.indexOf(o.TextMessageFormat.RecordSeparator),r===-1)throw new Error("Message is incomplete.");i=r+1;h=e.substring(0,i);c=e.length>i?e.substring(i):null}a=o.TextMessageFormat.parse(h);s=JSON.parse(a[0])}catch(v){u="Error parsing handshake response: "+v;this.logger.log(n.LogLevel.Error,u);l=new Error(u);this.connection.stop(l);throw l;}return s.error?(u="Server returned handshake error: "+s.error,this.logger.log(n.LogLevel.Error,u),this.connection.stop(new Error(u))):this.logger.log(n.LogLevel.Trace,"Server handshake complete."),c},t.prototype.configureTimeout=function(){var n=this;this.connection.features&&this.connection.features.inherentKeepAlive||(this.timeoutHandle=setTimeout(function(){return n.serverTimeout()},this.timeoutInMilliseconds))},t.prototype.serverTimeout=function(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))},t.prototype.invokeClientMethod=function(t){var u=this,r=this.methods[t.target.toLowerCase()],i;r?(r.forEach(function(n){return n.apply(u,t.arguments)}),t.invocationId&&(i="Server requested a response, which is not supported in this version of the client.",this.logger.log(n.LogLevel.Error,i),this.connection.stop(new Error(i)))):this.logger.log(n.LogLevel.Warning,"No client method with the name '"+t.target+"' found.")},t.prototype.connectionClosed=function(n){var i=this,t=this.callbacks;this.callbacks={};Object.keys(t).forEach(function(i){var r=t[i];r(undefined,n?n:new Error("Invocation canceled due to connection being closed."))});this.cleanupTimeout();this.closedCallbacks.forEach(function(t){return t.apply(i,[n])})},t.prototype.start=function(){return e(this,void 0,void 0,function(){return h(this,function(t){switch(t.label){case 0:return this.logger.log(n.LogLevel.Trace,"Starting HubConnection."),this.receivedHandshakeResponse=!1,[4,this.connection.start(this.protocol.transferFormat)];case 1:return t.sent(),this.logger.log(n.LogLevel.Trace,"Sending handshake request."),[4,this.connection.send(o.TextMessageFormat.write(JSON.stringify({protocol:this.protocol.name,version:this.protocol.version})))];case 2:return t.sent(),this.logger.log(n.LogLevel.Information,"Using HubProtocol '"+this.protocol.name+"'."),this.cleanupTimeout(),this.configureTimeout(),[2]}})})},t.prototype.stop=function(){return this.logger.log(n.LogLevel.Trace,"Stopping HubConnection."),this.cleanupTimeout(),this.connection.stop()},t.prototype.stream=function(n){for(var i,t,e,r=this,f=[],u=1;u=0;r--)l(n(u[r]),i)}function l(t,i,r){var u=r&&r.force?r.force:!1;return t&&(u||n(":focus",t).length===0)?(t[i.hideMethod]({duration:i.hideDuration,easing:i.hideEasing,complete:function(){s(t)}}),!0):!1}function nt(i){return t=n("
").attr("id",i.containerId).addClass(i.positionClass),t.appendTo(n(i.target)),t}function tt(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:undefined,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:undefined,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'