From cdd39050469b8bb20020724104914998cb519015 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 2 Dec 2020 10:10:48 +0100 Subject: [PATCH 01/26] Add timeout to Create data type test --- .../cypress/integration/Settings/dataTypes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/dataTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/dataTypes.ts index 5803810f54..53fd55a3fc 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/dataTypes.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/dataTypes.ts @@ -23,7 +23,7 @@ context('Data Types', () => { cy.umbracoEditorHeaderName(name); - cy.get('select[name="selectedEditor"]').select('Label'); + cy.get('select[name="selectedEditor"]', {timeout: 5000}).select('Label'); cy.get('.umb-property-editor select').select('Time'); From b6b17e4c9a5600a802b6af8e8fa10f03f8111eff Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 2 Dec 2020 13:11:17 +0100 Subject: [PATCH 02/26] Update cypress to 6.0.1 --- .../cypress/integration/Settings/templates.ts | 2 +- src/Umbraco.Tests.AcceptanceTest/package.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts index da1adedaeb..c586384af7 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts @@ -41,7 +41,7 @@ context('Templates', () => { cy.umbracoSuccessNotification().should('be.visible'); // For some reason cy.umbracoErrorNotification tries to click the element which is not possible // if it doesn't actually exist, making should('not.be.visible') impossible. - cy.get('.umb-notifications__notifications > .alert-error').should('not.be.visible'); + cy.get('.umb-notifications__notifications > .alert-error').should('not.exist'); //Clean up cy.umbracoEnsureTemplateNameNotExists(name); diff --git a/src/Umbraco.Tests.AcceptanceTest/package.json b/src/Umbraco.Tests.AcceptanceTest/package.json index 996a0cd2f8..1b39ee0ad9 100644 --- a/src/Umbraco.Tests.AcceptanceTest/package.json +++ b/src/Umbraco.Tests.AcceptanceTest/package.json @@ -7,10 +7,10 @@ }, "devDependencies": { "cross-env": "^7.0.2", - "cypress": "^5.1.0", + "cypress": "^6.0.1", "ncp": "^2.0.0", - "umbraco-cypress-testhelpers": "^1.0.0-beta-51", - "prompt": "^1.0.0" + "prompt": "^1.0.0", + "umbraco-cypress-testhelpers": "^1.0.0-beta-51" }, "dependencies": { "typescript": "^3.9.2" From c2d38640ea50f9a224130a2b925d1e41083fc06c Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 2 Dec 2020 14:31:23 +0100 Subject: [PATCH 03/26] Remove duplicate square bracket --- .../cypress/integration/Content/content.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts index 68f31e80bb..22f1f883d0 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts @@ -321,7 +321,7 @@ context('Content', () => { cy.get('.umb-box-content > div > .input-block-level') .find('option[label*=' + new Date().getDate() + ']') .then(elements => { - const option = elements[[elements.length - 1]].getAttribute('value'); + const option = elements[elements.length - 1].getAttribute('value'); cy.get('.umb-box-content > div > .input-block-level') .select(option); }); @@ -521,7 +521,7 @@ context('Content', () => { .done() .done() .build(); - + cy.saveDocumentType(pickedDocType).then((generatedType) => { const pickedContentNode = new ContentBuilder() .withContentTypeAlias(generatedType["alias"]) @@ -563,7 +563,7 @@ context('Content', () => { @{ Layout = null; } - + @{ IPublishedContent typedContentPicker = Model.Value("picker"); if (typedContentPicker != null) From cba3f3c6a91b2916e82fb0981416ff4e1d254d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 15 Dec 2020 09:27:30 +0100 Subject: [PATCH 04/26] added missing Y --- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 2 +- src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 7fddae5bea..54e55dc217 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -2532,7 +2532,7 @@ To manage your website, simply open the Umbraco back office and start adding con Preview website Open website in preview mode Preview website? - ou have ended preview mode, do you want to enable it again to view the latest saved version of your website? + You have ended preview mode, do you want to enable it again to view the latest saved version of your website? Preview latest version View published version View published version? diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 549f2783f8..e3d5e42c42 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -2554,7 +2554,7 @@ To manage your website, simply open the Umbraco back office and start adding con Preview website Open website in preview mode Preview website? - ou have ended preview mode, do you want to enable it again to view the latest saved version of your website? + You have ended preview mode, do you want to enable it again to view the latest saved version of your website? Preview latest version View published version View published version? From cd1120e062dc95fba2f7d9b2a29c0193e6ba8919 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 23 Nov 2020 07:43:24 +0100 Subject: [PATCH 05/26] Merge pull request #9408 from umbraco/v8/bugfix/task-scheduler-maindom-logging Ensure that TaskScheduler.Default is used anywhere that ContinueWith is used, adds more debug logging to MainDom operations (cherry picked from commit 9a1b4569494d6bce3e04687868ba944d69dbb309) # Conflicts: # src/Umbraco.Core/Runtime/SqlMainDomLock.cs --- .../Logging/LoggingTaskExtension.cs | 13 +++++++++-- src/Umbraco.Core/Runtime/MainDom.cs | 12 +++++++++- src/Umbraco.Core/Runtime/SqlMainDomLock.cs | 17 ++++++++++++-- .../PublishedCache/NuCache/ContentStore.cs | 6 ++++- .../PublishedCache/NuCache/SnapDictionary.cs | 6 ++++- .../Scheduling/BackgroundTaskRunner.cs | 10 ++++++++- .../Scheduling/TaskAndFactoryExtensions.cs | 22 +++++++++++++++++-- .../WebApi/HttpActionContextExtensions.cs | 4 +++- 8 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Core/Logging/LoggingTaskExtension.cs b/src/Umbraco.Core/Logging/LoggingTaskExtension.cs index 1f742133c3..2e3aa0a883 100644 --- a/src/Umbraco.Core/Logging/LoggingTaskExtension.cs +++ b/src/Umbraco.Core/Logging/LoggingTaskExtension.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Umbraco.Core.Logging @@ -14,7 +15,12 @@ namespace Umbraco.Core.Logging /// public static Task LogErrors(this Task task, Action logMethod) { - return task.ContinueWith(t => LogErrorsInner(t, logMethod), TaskContinuationOptions.OnlyOnFaulted); + return task.ContinueWith( + t => LogErrorsInner(t, logMethod), + CancellationToken.None, + TaskContinuationOptions.OnlyOnFaulted, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); } /// @@ -26,7 +32,10 @@ namespace Umbraco.Core.Logging /// public static Task LogErrorsWaitable(this Task task, Action logMethod) { - return task.ContinueWith(t => LogErrorsInner(t, logMethod)); + return task.ContinueWith( + t => LogErrorsInner(t, logMethod), + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); } private static void LogErrorsInner(Task task, Action logAction) diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index 02f37f654e..71842905dd 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Threading; +using System.Threading.Tasks; using System.Web.Hosting; using Umbraco.Core; using Umbraco.Core.Logging; @@ -38,6 +39,9 @@ namespace Umbraco.Core.Runtime private const int LockTimeoutMilliseconds = 40000; // 40 seconds + private Task _listenTask; + private Task _listenCompleteTask; + #endregion #region Ctor @@ -172,7 +176,13 @@ namespace Umbraco.Core.Runtime try { // Listen for the signal from another AppDomain coming online to release the lock - _mainDomLock.ListenAsync().ContinueWith(_ => OnSignal("signal")); + _listenTask = _mainDomLock.ListenAsync(); + _listenCompleteTask = _listenTask.ContinueWith(t => + { + _logger.Debug("Listening task completed with {TaskStatus}", _listenTask.Status); + + OnSignal("signal"); + }, TaskScheduler.Default); // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html } catch (OperationCanceledException ex) { diff --git a/src/Umbraco.Core/Runtime/SqlMainDomLock.cs b/src/Umbraco.Core/Runtime/SqlMainDomLock.cs index 84d98775d9..48b5804305 100644 --- a/src/Umbraco.Core/Runtime/SqlMainDomLock.cs +++ b/src/Umbraco.Core/Runtime/SqlMainDomLock.cs @@ -124,7 +124,12 @@ namespace Umbraco.Core.Runtime // Create a long running task (dedicated thread) // to poll to check if we are still the MainDom registered in the DB - return Task.Factory.StartNew(ListeningLoop, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + return Task.Factory.StartNew( + ListeningLoop, + _cancellationTokenSource.Token, + TaskCreationOptions.LongRunning, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); } @@ -159,7 +164,11 @@ namespace Umbraco.Core.Runtime // the other MainDom is taking to startup. In this case the db row will just be deleted and the // new MainDom will just take over. if (_cancellationTokenSource.IsCancellationRequested) + { + _logger.Debug("Task canceled, exiting loop"); return; + } + IUmbracoDatabase db = null; try { @@ -183,8 +192,10 @@ namespace Umbraco.Core.Runtime // We need to keep on listening unless we've been notified by our own AppDomain to shutdown since // we don't want to shutdown resources controlled by MainDom inadvertently. We'll just keep listening otherwise. if (_cancellationTokenSource.IsCancellationRequested) + { + _logger.Debug("Task canceled, exiting loop"); return; - + } } finally { @@ -389,6 +400,8 @@ namespace Umbraco.Core.Runtime { lock (_locker) { + _logger.Debug($"{nameof(SqlMainDomLock)} Disposing..."); + // immediately cancel all sub-tasks, we don't want them to keep querying _cancellationTokenSource.Cancel(); _cancellationTokenSource.Dispose(); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs index 34d21497a2..07b10c9fbc 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs @@ -1335,7 +1335,11 @@ namespace Umbraco.Web.PublishedCache.NuCache { _collectTask = null; } - }, TaskContinuationOptions.ExecuteSynchronously); + }, + CancellationToken.None, + TaskContinuationOptions.ExecuteSynchronously, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); // ReSharper restore InconsistentlySynchronizedField return task; diff --git a/src/Umbraco.Web/PublishedCache/NuCache/SnapDictionary.cs b/src/Umbraco.Web/PublishedCache/NuCache/SnapDictionary.cs index c38940da25..589cd06d8a 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/SnapDictionary.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/SnapDictionary.cs @@ -380,7 +380,11 @@ namespace Umbraco.Web.PublishedCache.NuCache { _collectTask = null; } - }, TaskContinuationOptions.ExecuteSynchronously); + }, + CancellationToken.None, + TaskContinuationOptions.ExecuteSynchronously, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); // ReSharper restore InconsistentlySynchronizedField return task; diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs index c0475b1f79..81bb45e270 100644 --- a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs @@ -756,9 +756,17 @@ namespace Umbraco.Web.Scheduling lock (_locker) { if (_runningTask != null) - _runningTask.ContinueWith(_ => StopImmediate()); + { + _runningTask.ContinueWith( + _ => StopImmediate(), + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); + } else + { StopImmediate(); + } + } } diff --git a/src/Umbraco.Web/Scheduling/TaskAndFactoryExtensions.cs b/src/Umbraco.Web/Scheduling/TaskAndFactoryExtensions.cs index 7220e77e0c..557fe37709 100644 --- a/src/Umbraco.Web/Scheduling/TaskAndFactoryExtensions.cs +++ b/src/Umbraco.Web/Scheduling/TaskAndFactoryExtensions.cs @@ -8,6 +8,7 @@ namespace Umbraco.Web.Scheduling { #region Task Extensions + // TODO: Not used, is this used in Deploy or something? static void SetCompletionSource(TaskCompletionSource completionSource, Task task) { if (task.IsFaulted) @@ -16,6 +17,7 @@ namespace Umbraco.Web.Scheduling completionSource.SetResult(default(TResult)); } + // TODO: Not used, is this used in Deploy or something? static void SetCompletionSource(TaskCompletionSource completionSource, Task task) { if (task.IsFaulted) @@ -24,17 +26,33 @@ namespace Umbraco.Web.Scheduling completionSource.SetResult(task.Result); } + // TODO: Not used, is this used in Deploy or something? public static Task ContinueWithTask(this Task task, Func continuation) { var completionSource = new TaskCompletionSource(); - task.ContinueWith(atask => continuation(atask).ContinueWith(atask2 => SetCompletionSource(completionSource, atask2))); + task.ContinueWith(atask => continuation(atask).ContinueWith( + atask2 => SetCompletionSource(completionSource, atask2), + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default), + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); return completionSource.Task; } + // TODO: Not used, is this used in Deploy or something? public static Task ContinueWithTask(this Task task, Func continuation, CancellationToken token) { var completionSource = new TaskCompletionSource(); - task.ContinueWith(atask => continuation(atask).ContinueWith(atask2 => SetCompletionSource(completionSource, atask2), token), token); + task.ContinueWith(atask => continuation(atask).ContinueWith( + atask2 => SetCompletionSource(completionSource, atask2), + token, + TaskContinuationOptions.None, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default), + token, + TaskContinuationOptions.None, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); return completionSource.Task; } diff --git a/src/Umbraco.Web/WebApi/HttpActionContextExtensions.cs b/src/Umbraco.Web/WebApi/HttpActionContextExtensions.cs index c67ec2f6a7..08d0ac8254 100644 --- a/src/Umbraco.Web/WebApi/HttpActionContextExtensions.cs +++ b/src/Umbraco.Web/WebApi/HttpActionContextExtensions.cs @@ -89,7 +89,9 @@ namespace Umbraco.Web.WebApi throw x.Exception; } result = x.ConfigureAwait(false).GetAwaiter().GetResult(); - }); + }, + // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html + TaskScheduler.Default); task.Wait(); if (result == null) From 7b32aeb1271d89911f173b19e2383a675bc7e48c Mon Sep 17 00:00:00 2001 From: Matt Darby Date: Wed, 28 Oct 2020 20:07:35 +0000 Subject: [PATCH 06/26] Change defaultButton type to "button" (cherry picked from commit 7ddb52a34feffebe3e11c86066b59aae795248c2) --- .../src/views/documenttypes/edit.controller.js | 2 +- .../src/views/mediatypes/edit.controller.js | 2 +- .../src/views/membertypes/edit.controller.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index e39a36a439..dfe229cf72 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -176,7 +176,7 @@ hotKeyWhenHidden: true, labelKey: vm.submitButtonKey, letter: "S", - type: "submit", + type: "button", handler: function () { vm.save(); } }; vm.page.subButtons = [{ diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index fc2b83ea93..43db6e7bb8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -190,7 +190,7 @@ hotKeyWhenHidden: true, labelKey: vm.saveButtonKey, letter: "S", - type: "submit", + type: "button", handler: function () { vm.save(); } }; vm.page.subButtons = [{ diff --git a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js index c81de0ec4d..31c062e41b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js @@ -111,7 +111,7 @@ hotKeyWhenHidden: true, labelKey: vm.saveButtonKey, letter: "S", - type: "submit", + type: "button", handler: function () { vm.save(); } }; vm.page.subButtons = [{ From 015882daa2f7acdcc968f4ba0feb2159947ccfa6 Mon Sep 17 00:00:00 2001 From: Matt Darby Date: Wed, 28 Oct 2020 20:11:47 +0000 Subject: [PATCH 07/26] Remove type as it defaults to button (cherry picked from commit bc2faefb1881969ff25a0d381808fc41280358c6) --- .../src/views/documenttypes/edit.controller.js | 1 - .../src/views/mediatypes/edit.controller.js | 1 - .../src/views/membertypes/edit.controller.js | 1 - 3 files changed, 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index dfe229cf72..3946d09578 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -176,7 +176,6 @@ hotKeyWhenHidden: true, labelKey: vm.submitButtonKey, letter: "S", - type: "button", handler: function () { vm.save(); } }; vm.page.subButtons = [{ diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index 43db6e7bb8..ecf2aec30c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -190,7 +190,6 @@ hotKeyWhenHidden: true, labelKey: vm.saveButtonKey, letter: "S", - type: "button", handler: function () { vm.save(); } }; vm.page.subButtons = [{ diff --git a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js index 31c062e41b..53bb4adb9b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js @@ -111,7 +111,6 @@ hotKeyWhenHidden: true, labelKey: vm.saveButtonKey, letter: "S", - type: "button", handler: function () { vm.save(); } }; vm.page.subButtons = [{ From 3f0f5c14495eb7dd6194b15f5309e7d0cddc20ee Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 18 Dec 2020 12:23:44 +0100 Subject: [PATCH 08/26] Fixed tests and update testhelper --- .../integration/Settings/documentTypes.ts | 4 +- .../integration/Settings/mediaTypes.ts | 2 +- .../integration/Settings/memberTypes.ts | 2 +- src/Umbraco.Tests.AcceptanceTest/package.json | 2 +- src/Umbraco.Web.UI.Client/package-lock.json | 1911 ++++++++++------- 5 files changed, 1148 insertions(+), 773 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts index c40d65d541..1a86e90852 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts @@ -32,7 +32,7 @@ context('Document Types', () => { cy.get('[data-element="editor-add"]').click(); //Search for textstring - cy.get('.umb-search-field').type('Textstring'); + cy.get('#datatype-search').type('Textstring'); // Choose first item cy.get('ul.umb-card-grid li [title="Textstring"]').closest("li").click(); @@ -70,7 +70,7 @@ context('Document Types', () => { cy.umbracoContextMenuAction("action-delete").click(); cy.get('label.checkbox').click(); - cy.umbracoButtonByLabelKey("general_ok").click(); + cy.umbracoButtonByLabelKey("delete").click(); cy.contains(name).should('not.exist'); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/mediaTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/mediaTypes.ts index 646654bbab..4064c1f41e 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/mediaTypes.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/mediaTypes.ts @@ -31,7 +31,7 @@ context('Media Types', () => { cy.get('[data-element="editor-add"]').click(); //Search for textstring - cy.get('.umb-search-field').type('Textstring'); + cy.get('#datatype-search').type('Textstring'); // Choose first item cy.get('ul.umb-card-grid li [title="Textstring"]').closest("li").click(); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/memberTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/memberTypes.ts index fe2d88d64f..e84c29c0d8 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/memberTypes.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/memberTypes.ts @@ -29,7 +29,7 @@ context('Member Types', () => { cy.get('[data-element="editor-add"]').click(); //Search for textstring - cy.get('.umb-search-field').type('Textstring'); + cy.get('#datatype-search').type('Textstring'); // Choose first item cy.get('ul.umb-card-grid li [title="Textstring"]').closest("li").click(); diff --git a/src/Umbraco.Tests.AcceptanceTest/package.json b/src/Umbraco.Tests.AcceptanceTest/package.json index 1b39ee0ad9..378fe719fc 100644 --- a/src/Umbraco.Tests.AcceptanceTest/package.json +++ b/src/Umbraco.Tests.AcceptanceTest/package.json @@ -10,7 +10,7 @@ "cypress": "^6.0.1", "ncp": "^2.0.0", "prompt": "^1.0.0", - "umbraco-cypress-testhelpers": "^1.0.0-beta-51" + "umbraco-cypress-testhelpers": "^1.0.0-beta-52" }, "dependencies": { "typescript": "^3.9.2" diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index df2f3637f6..1b28cfb029 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -104,7 +104,7 @@ "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "integrity": "sha1-Mj053QtQ4Qx8Bsp9djjmhk2MXDI=", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -113,7 +113,7 @@ "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "integrity": "sha1-a2lijf5Ah3mODE7Zjj1Kay+9L18=", "dev": true, "requires": { "@babel/helper-explode-assignable-expression": "^7.1.0", @@ -145,7 +145,7 @@ "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "integrity": "sha1-U3+hP28WdN90WwwA7I/k6ZaByPY=", "dev": true, "requires": { "@babel/traverse": "^7.1.0", @@ -155,7 +155,7 @@ "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "integrity": "sha1-oM6wFoX3M1XUNgwSR/WCv6/I/1M=", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.0.0", @@ -166,7 +166,7 @@ "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "integrity": "sha1-g1ctQyDipGVyY3NBE8QoaLZOScM=", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -193,7 +193,7 @@ "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "integrity": "sha1-lggbcRHkhtpNLNlxrRpP4hbMLj0=", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -216,7 +216,7 @@ "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "integrity": "sha1-opIMVwKwc8Fd5REGIAqoytIEl9U=", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -225,7 +225,7 @@ "@babel/helper-plugin-utils": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "integrity": "sha1-u7P77phmHFaQNCN8wDlnupm08lA=", "dev": true }, "@babel/helper-regex": { @@ -240,7 +240,7 @@ "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "integrity": "sha1-Nh2AghtvONp1vT8HheziCojF/n8=", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -265,7 +265,7 @@ "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "integrity": "sha1-Ze65VMjCRb6qToWdphiPOdceWFw=", "dev": true, "requires": { "@babel/template": "^7.1.0", @@ -862,6 +862,43 @@ } } }, + "@gulp-sourcemaps/identity-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", @@ -935,6 +972,12 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -948,7 +991,7 @@ "accord": { "version": "0.29.0", "resolved": "https://registry.npmjs.org/accord/-/accord-0.29.0.tgz", - "integrity": "sha512-3OOR92FTc2p5/EcOzPcXp+Cbo+3C15nV9RXHlOUBCBpHhcB+0frbSNR9ehED/o7sTcyGVtqGJpguToEdlXhD0w==", + "integrity": "sha1-t0HBdtAENcWSnUZt/oz2vukzseQ=", "dev": true, "requires": { "convert-source-map": "^1.5.0", @@ -984,7 +1027,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -995,7 +1038,7 @@ "ace-builds": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.4.2.tgz", - "integrity": "sha512-M1JtZctO2Zg+1qeGUFZXtYKsyaRptqQtqpVzlj80I0NzGW9MF3um0DBuizIvQlrPYUlTdm+wcOPZpZoerkxQdA==" + "integrity": "sha1-avwuQ6e17/3ETYQHQ2EShSVo6A0=" }, "acorn": { "version": "7.1.0", @@ -1003,12 +1046,36 @@ "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -1062,19 +1129,19 @@ "dev": true }, "angular": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.7.5.tgz", - "integrity": "sha512-760183yxtGzni740IBTieNuWLtPNAoMqvmC0Z62UoU0I3nqk+VJuO3JbQAXOyvo3Oy/ZsdNQwrSTh/B0OQZjNw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.0.tgz", + "integrity": "sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg==" }, "angular-animate": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.7.5.tgz", - "integrity": "sha512-kU/fHIGf2a4a3bH7E1tzALTHk+QfoUSCK9fEcMFisd6ZWvNDwPzXWAilItqOC3EDiAXPmGHaNc9/aXiD9xrAxQ==" + "integrity": "sha1-H/xsKpze4ieiunnMbNj3HsRNtdw=" }, "angular-aria": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.7.5.tgz", - "integrity": "sha512-X2dGRw+PK7hrV7/X1Ns4e5P3KC/OBFi1l7z//D/v7zbZObsAx48qBoX7unsck+s4+mnO+ikNNkHG5N49VfAyRw==" + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.7.9.tgz", + "integrity": "sha512-luI3Jemd1AbOQW0krdzfEG3fM0IFtLY0bSSqIDEx3POE0XjKIC1MkrO8Csyq9PPgueLphyAPofzUwZ8YeZ88SA==" }, "angular-chart.js": { "version": "1.1.1", @@ -1099,12 +1166,12 @@ "angular-cookies": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.7.5.tgz", - "integrity": "sha512-/8xvvSl/Z9Vwu8ChRm+OQE3vmli8Icwl8uTYkHqD7j7cknJP9kNaf7SgsENlsLVtOqLE/I7TCFYrSx3bmSeNQA==" + "integrity": "sha1-HFqzwFzcQ/F3e+lQbmRYfLNUNjQ=" }, "angular-dynamic-locale": { "version": "0.1.37", "resolved": "https://registry.npmjs.org/angular-dynamic-locale/-/angular-dynamic-locale-0.1.37.tgz", - "integrity": "sha512-m5Kyk8W8/mOZSqRxuByOwHBjv8labLBAgvl0Z3iQx2xT/tWCqb94imKUPwumudszdPDjxeopwyucQvm8Sw7ogw==", + "integrity": "sha1-fon70uxFvdaryJ82zaiJODjkk1Q=", "requires": { "@types/angular": "^1.6.25" } @@ -1112,7 +1179,7 @@ "angular-i18n": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-i18n/-/angular-i18n-1.7.5.tgz", - "integrity": "sha512-52+Jpt8HRJV2bqSbSU6fWkwOvGzj/DxbNpKXxnTuCS9heuJrlm77BS/lhrF4BA8+Uudnh7npr5/yRELobP+8Yw==" + "integrity": "sha1-Lie2Thl3qMa2sFHFHQF1xtTcglI=" }, "angular-local-storage": { "version": "0.7.1", @@ -1122,32 +1189,32 @@ "angular-messages": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-messages/-/angular-messages-1.7.5.tgz", - "integrity": "sha512-YDpJpFLyrIgZjE/sIAjgww1y6r3QqXBJbNDI0QjftD37vHXLkwvAOo3A4bxPw8BikyGLcJrFrgf6hRAzntJIWA==" + "integrity": "sha1-fC/XgTFaQ6GYOLEX2gFCqYhFThQ=" }, "angular-mocks": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.7.5.tgz", - "integrity": "sha512-I+Ue2Bkx6R9W5178DYrNvzjIdGh4wKKoCWsgz8dc7ysH4mA70Q3M9v5xRF0RUu7r+2CZj+nDeUecvh2paxcYvg==" + "integrity": "sha1-yLq6WgbtYLk0aXAmtJIWliavOEs=" }, "angular-route": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.7.5.tgz", - "integrity": "sha512-7KfyEVVOWTI+jTY/j5rUNCIHGRyeCOx7YqZI/Ci3IbDK7GIsy6xH+hS5ai0Xi0sLjzDZ0PUDO4gBn+K0dVtlOg==" + "integrity": "sha1-NKNkjEB6FKAw0HXPSFMY4zuiPw4=" }, "angular-sanitize": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.7.5.tgz", - "integrity": "sha512-wjKCJOIwrkEvfD0keTnKGi6We13gtoCAQIHcdoqyoo3gwvcgNfYymVQIS3+iCGVcjfWz0jHuS3KgB4ysRWsTTA==" + "integrity": "sha1-ddSeFQccqccFgedtIJQPJjcuJNI=" }, "angular-touch": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-touch/-/angular-touch-1.7.5.tgz", - "integrity": "sha512-XNAZNG0RA1mtdwBJheViCF1H/7wOygp4MLIfs5y1K+rne6AeaYKZcV6EJs9fvgfLKLO6ecm1+3J8hoCkdhhxQw==" + "integrity": "sha1-7SYyKmhfApmyPLauqYNMEZQk2kY=" }, "angular-ui-sortable": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/angular-ui-sortable/-/angular-ui-sortable-0.19.0.tgz", - "integrity": "sha512-u/uc981Nzg4XN1bMU9qKleMTSt7F1XjMWnyGw6gxPLIeQeLZm8jWNy7tj8y2r2HmvzXFbQVq2z6rObznFKAekQ==", + "integrity": "sha1-SsQ5H8TU3lcRDbS10xp8GY0xT9A=", "requires": { "angular": ">=1.2.x", "jquery": ">=3.1.x", @@ -1162,7 +1229,7 @@ "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "integrity": "sha1-Y3S03V1HGP884npnGjscrQdxMqk=", "dev": true, "requires": { "ansi-wrap": "^0.1.0" @@ -1210,7 +1277,7 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -1242,7 +1309,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { "micromatch": "^2.1.5", @@ -1390,7 +1457,7 @@ "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "dev": true, "requires": { "sprintf-js": "~1.0.2" @@ -1414,7 +1481,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "arr-map": { @@ -1489,13 +1556,13 @@ "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", "dev": true }, "array-sort": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "integrity": "sha1-5MBTVkU/VvU1EqfR1hI/LFTAqIo=", "dev": true, "requires": { "default-compare": "^1.0.0", @@ -1506,7 +1573,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -1532,7 +1599,7 @@ "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", "dev": true }, "asap": { @@ -1545,7 +1612,7 @@ "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", "dev": true, "requires": { "safer-buffer": "~2.1.0" @@ -1566,7 +1633,7 @@ "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=", "dev": true }, "async": { @@ -1628,7 +1695,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", "dev": true }, "autoprefixer": { @@ -1663,7 +1730,7 @@ "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=", "dev": true }, "babel-plugin-dynamic-import-node": { @@ -1707,7 +1774,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -1731,7 +1798,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -1740,7 +1807,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -1749,7 +1816,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -2057,7 +2124,7 @@ "bl": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", "dev": true, "optional": true, "requires": { @@ -2075,7 +2142,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "optional": true, "requires": { @@ -2091,7 +2158,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "optional": true, "requires": { @@ -2103,7 +2170,7 @@ "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "integrity": "sha1-1oDu7yX4zZGtUz9bAe7UjmTK9oM=", "dev": true }, "bluebird": { @@ -2133,7 +2200,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -2176,7 +2243,7 @@ "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -2186,7 +2253,7 @@ "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -2212,6 +2279,12 @@ } } }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, "browserslist": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", @@ -2237,7 +2310,7 @@ "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", "dev": true, "requires": { "buffer-alloc-unsafe": "^1.1.0", @@ -2247,7 +2320,7 @@ "buffer-alloc-unsafe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", "dev": true }, "buffer-crc32": { @@ -2272,7 +2345,7 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", "dev": true }, "bufferstreams": { @@ -2293,7 +2366,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -2420,7 +2493,7 @@ "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "integrity": "sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA=", "dev": true, "requires": { "browserslist": "^4.0.0", @@ -2430,9 +2503,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001002", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001002.tgz", - "integrity": "sha512-pRuxPE8wdrWmVPKcDmJJiGBxr6lFJq4ivdSeo9FTmGj5Rb8NX3Mby2pARG57MXF15hYAhZ0nHV5XxT2ig4bz3g==", + "version": "1.0.30001168", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001168.tgz", + "integrity": "sha512-P2zmX7swIXKu+GMMR01TWa4csIKELTNnZKc+f1CjebmZJQtTAEXmpQSoKVJVVcvPGAA0TEYTOUp3VehavZSFPQ==", "dev": true }, "caseless": { @@ -2478,13 +2551,13 @@ "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=", "dev": true }, "chart.js": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.8.0.tgz", - "integrity": "sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", "requires": { "chartjs-color": "^2.1.0", "moment": "^2.10.2" @@ -2530,7 +2603,7 @@ "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { "micromatch": "^3.1.4", @@ -2568,7 +2641,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -2591,7 +2664,7 @@ "clean-css": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "integrity": "sha1-LUEe92uFabbQyEBo2r6FsKpeXBc=", "dev": true, "requires": { "source-map": "~0.6.0" @@ -2600,7 +2673,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -2608,7 +2681,7 @@ "cli-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "integrity": "sha1-fRBzj0hSaCT4/n2lGFfLD1cv4B8=", "dev": true, "requires": { "ansi-regex": "^2.1.1", @@ -2637,7 +2710,7 @@ "clipboard": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", - "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", + "integrity": "sha1-g22v1mzw/qXXHOXVsL9ulYAJES0=", "requires": { "good-listener": "^1.2.2", "select": "^1.1.2", @@ -2703,7 +2776,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -2718,7 +2791,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -2804,7 +2877,7 @@ "color-string": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", "dev": true, "requires": { "color-name": "^1.0.0", @@ -2814,7 +2887,7 @@ "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", "dev": true }, "colornames": { @@ -2842,7 +2915,7 @@ "color": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "integrity": "sha1-2SC0Mo1TSjrIKV1o971LpsQnvpo=", "dev": true, "requires": { "color-convert": "^1.9.1", @@ -2912,7 +2985,7 @@ "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -2928,9 +3001,9 @@ "dev": true }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -2945,7 +3018,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -2956,7 +3029,7 @@ "concat-with-sourcemaps": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "integrity": "sha1-1OqT8FriV5CVG5nns7CeOQikCC4=", "dev": true, "requires": { "source-map": "^0.6.1" @@ -2965,7 +3038,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -2996,7 +3069,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -3039,13 +3112,13 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -3066,7 +3139,7 @@ "copy-props": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "integrity": "sha1-k7scrfr9MdpbuKnUtB9HHsOnLf4=", "dev": true, "requires": { "each-props": "^1.3.0", @@ -3138,7 +3211,7 @@ "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", "dev": true, "requires": { "nice-try": "^1.0.4", @@ -3148,6 +3221,26 @@ "which": "^1.2.9" } }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -3157,7 +3250,7 @@ "css-declaration-sorter": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", - "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "integrity": "sha1-wZiUD2OnbX42wecQGLABchBUyyI=", "dev": true, "requires": { "postcss": "^7.0.1", @@ -3167,7 +3260,7 @@ "css-select": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", - "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", + "integrity": "sha1-q0OGzsnh9miFVWSxfDcztDsqXt4=", "dev": true, "requires": { "boolbase": "^1.0.0", @@ -3179,7 +3272,7 @@ "css-select-base-adapter": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "integrity": "sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc=", "dev": true }, "css-tree": { @@ -3207,7 +3300,7 @@ "cssesc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=", "dev": true }, "cssnano": { @@ -3275,7 +3368,7 @@ "cssnano-util-raw-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", - "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "integrity": "sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI=", "dev": true, "requires": { "postcss": "^7.0.0" @@ -3284,13 +3377,13 @@ "cssnano-util-same-parent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", - "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "integrity": "sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M=", "dev": true }, "csso": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", - "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==", + "integrity": "sha1-e564vmFiiXPBsmHhadLwJACOdYs=", "dev": true, "requires": { "css-tree": "1.0.0-alpha.29" @@ -3299,7 +3392,7 @@ "css-tree": { "version": "1.0.0-alpha.29", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", - "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", + "integrity": "sha1-P6nU7zFCy9HDAedmTB81K9gvWjk=", "dev": true, "requires": { "mdn-data": "~1.1.0", @@ -3314,6 +3407,29 @@ } } }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -3349,6 +3465,17 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, "date-format": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", @@ -3370,12 +3497,46 @@ "ms": "^2.1.1" } }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decimal.js": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", + "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==", + "dev": true + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -3544,7 +3705,7 @@ "default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "integrity": "sha1-y2ETGESthNhHiPto/QFoHKd4Gi8=", "dev": true, "requires": { "kind-of": "^5.0.2" @@ -3553,7 +3714,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -3567,7 +3728,7 @@ "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "dev": true, "requires": { "object-keys": "^1.0.12" @@ -3576,7 +3737,7 @@ "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -3586,7 +3747,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3595,7 +3756,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3604,7 +3765,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -3623,7 +3784,7 @@ "delegate": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + "integrity": "sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=" }, "depd": { "version": "1.1.2", @@ -3637,6 +3798,12 @@ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, "di": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", @@ -3646,7 +3813,7 @@ "diagnostics": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", - "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "integrity": "sha1-yrasM99wydmnJ0kK5DrJladpsio=", "dev": true, "requires": { "colorspace": "1.1.x", @@ -3657,7 +3824,7 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=" }, "dir-glob": { "version": "3.0.1", @@ -3721,10 +3888,27 @@ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=", "dev": true, "requires": { "domelementtype": "1" @@ -3733,7 +3917,7 @@ "domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=", "dev": true, "requires": { "dom-serializer": "0", @@ -3743,7 +3927,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", "dev": true, "requires": { "is-obj": "^1.0.0" @@ -3832,7 +4016,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -3847,7 +4031,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -3858,7 +4042,7 @@ "each-props": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "integrity": "sha1-6kWkFNFt1c+kGbGoFyDVygaJIzM=", "dev": true, "requires": { "is-plain-object": "^2.0.1", @@ -3937,7 +4121,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -3951,7 +4135,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -3968,7 +4152,7 @@ "engine.io-client": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "integrity": "sha1-b1TAR13khxWKGnx30QF4cItq3TY=", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -4010,7 +4194,7 @@ "engine.io-parser": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "integrity": "sha1-dXq5cPvy37Mse3SwMyFtVznveaY=", "dev": true, "requires": { "after": "0.8.2", @@ -4035,13 +4219,13 @@ "env-variable": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", - "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==", + "integrity": "sha1-kT3YML7xHpagOcA41BMGBOujf4g=", "dev": true }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", "dev": true, "optional": true, "requires": { @@ -4051,7 +4235,7 @@ "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", "dev": true, "requires": { "is-arrayish": "^0.2.1" @@ -4078,7 +4262,7 @@ "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -4170,7 +4354,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -4317,13 +4501,13 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", "dev": true }, "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -4332,7 +4516,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", "dev": true, "requires": { "estraverse": "^4.1.0" @@ -4387,7 +4571,7 @@ "exec-buffer": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", - "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", + "integrity": "sha1-sWhtvZBMfPmC5lLB9aebHlVzCCs=", "dev": true, "optional": true, "requires": { @@ -4465,7 +4649,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -4509,7 +4693,7 @@ "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", "dev": true, "requires": { "is-number": "^2.1.0", @@ -4587,7 +4771,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=", "dev": true }, "extend-shallow": { @@ -4603,7 +4787,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -4625,7 +4809,7 @@ "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -4659,7 +4843,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -4668,7 +4852,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -4677,7 +4861,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -4687,53 +4871,6 @@ } } }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "requires": { - "fd-slicer": "~1.0.1" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -4743,7 +4880,7 @@ "fancy-log": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "integrity": "sha1-28GRVPVYaQFQojlToK29A1vkX8c=", "dev": true, "requires": { "ansi-gray": "^0.1.1", @@ -4955,7 +5092,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -5000,15 +5137,26 @@ } }, "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", "dev": true, "requires": { "detect-file": "^1.0.0", - "is-glob": "^3.1.0", + "is-glob": "^4.0.0", "micromatch": "^3.0.4", "resolve-dir": "^1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + } } }, "fined": { @@ -5085,7 +5233,7 @@ "flatpickr": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz", - "integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA==" + "integrity": "sha1-R8itRyoJbl+350uAmwcDU1OD8g0=" }, "flatted": { "version": "2.0.1", @@ -5184,7 +5332,7 @@ "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -5256,29 +5404,10 @@ "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", "dev": true, "optional": true }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true - } - } - }, "fs-mkdirp-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", @@ -5855,7 +5984,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", "dev": true }, "functional-red-black-tree": { @@ -5867,7 +5996,7 @@ "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", "dev": true }, "get-proxy": { @@ -6100,7 +6229,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -6252,7 +6381,7 @@ "gulp-babel": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0.tgz", - "integrity": "sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ==", + "integrity": "sha1-4NqW9PLsSojdOjAw9HbjirISbYc=", "dev": true, "requires": { "plugin-error": "^1.0.1", @@ -6319,9 +6448,9 @@ } }, "gulp-cli": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", - "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -6332,7 +6461,7 @@ "copy-props": "^2.0.1", "fancy-log": "^1.3.2", "gulplog": "^1.0.0", - "interpret": "^1.1.0", + "interpret": "^1.4.0", "isobject": "^3.0.1", "liftoff": "^3.1.0", "matchdep": "^2.0.0", @@ -6340,56 +6469,8 @@ "pretty-hrtime": "^1.0.0", "replace-homedir": "^1.0.0", "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.0.1", + "v8flags": "^3.2.0", "yargs": "^7.1.0" - }, - "dependencies": { - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - } } }, "gulp-concat": { @@ -6424,7 +6505,7 @@ "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "integrity": "sha1-2FsH2pbkWNJbL/4Z/s6fLKoT7YY=", "dev": true, "requires": { "clone": "^2.1.1", @@ -6470,7 +6551,7 @@ "gulp-less": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-4.0.1.tgz", - "integrity": "sha512-hmM2k0FfQp7Ptm3ZaqO2CkMX3hqpiIOn4OHtuSsCeFym63F7oWlEua5v6u1cIjVUKYsVIs9zPg9vbqTEb/udpA==", + "integrity": "sha1-NIwzpd3nogfFdxsdgmHRrBAhzu0=", "dev": true, "requires": { "accord": "^0.29.0", @@ -6549,7 +6630,7 @@ "gulp-notify": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/gulp-notify/-/gulp-notify-3.2.0.tgz", - "integrity": "sha512-qEocs1UVoDKKUjfsxJNMNwkRla0PbsyJwsqNNXpzYWsLQ29LhxRMY3wnTGZcc4hMHtalnvah/Dwlwb4NijH/0A==", + "integrity": "sha1-KugiUAnfiB7vWb5d1aLxM3OHdk4=", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -6635,7 +6716,7 @@ "gulp-postcss": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-8.0.0.tgz", - "integrity": "sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg==", + "integrity": "sha1-jTdyzU0nvKVeyMtMjlduO95NxVA=", "dev": true, "requires": { "fancy-log": "^1.3.2", @@ -6648,7 +6729,7 @@ "gulp-rename": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "integrity": "sha1-3hxxjnxAla6GH3KW708ySGSCQL0=", "dev": true }, "gulp-sort": { @@ -6660,6 +6741,39 @@ "through2": "^2.0.1" } }, + "gulp-sourcemaps": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", + "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", @@ -6716,7 +6830,7 @@ "gulp-watch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", - "integrity": "sha512-HnTSBdzAOFIT4wmXYPDUn783TaYAq9bpaN05vuZNP5eni3z3aRx0NAKbjhhMYtcq76x4R1wf4oORDGdlrEjuog==", + "integrity": "sha1-g9N4dS9b+0baAj5zwX7R2nBmIV0=", "dev": true, "requires": { "ansi-colors": "1.1.0", @@ -6771,7 +6885,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -6792,7 +6906,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -6801,7 +6915,7 @@ "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "integrity": "sha1-2FsH2pbkWNJbL/4Z/s6fLKoT7YY=", "dev": true, "requires": { "clone": "^2.1.1", @@ -6927,7 +7041,7 @@ "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", "dev": true, "requires": { "ajv": "^6.5.5", @@ -6937,7 +7051,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -6955,7 +7069,7 @@ "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", "dev": true, "requires": { "isarray": "2.0.1" @@ -7045,20 +7159,10 @@ } } }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, "hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", - "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "integrity": "sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4=", "dev": true }, "homedir-polyfill": { @@ -7091,9 +7195,18 @@ "html-comment-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "integrity": "sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c=", "dev": true }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, "htmlparser2": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", @@ -7123,7 +7236,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -7138,7 +7251,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -7199,7 +7312,7 @@ "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -7215,7 +7328,7 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", "dev": true }, "image-size": { @@ -7382,7 +7495,7 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", "dev": true }, "inquirer": { @@ -7459,9 +7572,9 @@ } }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, "into-stream": { @@ -7478,7 +7591,7 @@ "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", "dev": true, "requires": { "loose-envify": "^1.0.0" @@ -7490,6 +7603,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, "irregular-plurals": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", @@ -7505,7 +7624,7 @@ "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { "is-relative": "^1.0.0", @@ -7556,13 +7675,13 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", "dev": true }, "is-color-stop": { @@ -7608,7 +7727,7 @@ "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -7619,7 +7738,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -7767,7 +7886,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { "isobject": "^3.0.1" @@ -7786,6 +7905,12 @@ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", "dev": true }, + "is-potential-custom-element-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz", + "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=", + "dev": true + }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", @@ -7810,7 +7935,7 @@ "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { "is-unc-path": "^1.0.0" @@ -7819,7 +7944,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", "dev": true }, "is-retry-allowed": { @@ -7833,12 +7958,13 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "dev": true, + "optional": true }, "is-svg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "integrity": "sha1-kyHb0pwhLlypnE+peUxxS8r6L3U=", "dev": true, "requires": { "html-comment-regex": "^1.1.0" @@ -7847,7 +7973,7 @@ "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", "dev": true, "requires": { "has-symbols": "^1.0.0" @@ -7862,7 +7988,7 @@ "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { "unc-path-regex": "^0.1.2" @@ -7883,7 +8009,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true }, "is-wsl": { @@ -7901,7 +8027,7 @@ "isbinaryfile": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "integrity": "sha1-XW3vPt6/boyoyunDAYOoBLX4voA=", "dev": true, "requires": { "buffer-alloc": "^1.2.0" @@ -7955,9 +8081,9 @@ } }, "jquery": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", - "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==" }, "jquery-ui-dist": { "version": "1.12.1", @@ -7978,7 +8104,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", "dev": true }, "js-yaml": { @@ -7997,10 +8123,129 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsdom": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz", + "integrity": "sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "acorn": "^7.1.1", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.2.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.0", + "domexception": "^2.0.1", + "escodegen": "^1.14.1", + "html-encoding-sniffer": "^2.0.1", + "is-potential-custom-element-name": "^1.0.0", + "nwsapi": "^2.2.0", + "parse5": "5.1.1", + "request": "^2.88.2", + "request-promise-native": "^1.0.8", + "saxes": "^5.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^3.0.1", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0", + "ws": "^7.2.3", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dev": true, + "requires": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "ws": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", + "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==", + "dev": true + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=", "dev": true }, "json-buffer": { @@ -8013,7 +8258,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", "dev": true }, "json-schema": { @@ -8025,7 +8270,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -8049,24 +8294,6 @@ "minimist": "^1.2.0" } }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true, - "optional": true - } - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -8239,7 +8466,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "to-regex-range": { @@ -8256,12 +8483,18 @@ "karma-jasmine": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz", - "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", + "integrity": "sha1-JuPjHy+vJy3YDrsOGJiRTMOhl2M=", "dev": true, "requires": { "jasmine-core": "^3.3" } }, + "karma-jsdom-launcher": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/karma-jsdom-launcher/-/karma-jsdom-launcher-8.0.2.tgz", + "integrity": "sha512-jxO+Nf9U/XNSnHXrNpxBbbMyeYuvJH1V++bRdZv20vJ9pvaLuQ6LFNIgn4hA1WAVmzMsvW9j0P2Q2hTLMWcSvw==", + "dev": true + }, "karma-junit-reporter": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-2.0.1.tgz", @@ -8272,16 +8505,6 @@ "xmlbuilder": "12.0.0" } }, - "karma-phantomjs-launcher": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz", - "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", - "dev": true, - "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" - } - }, "karma-spec-reporter": { "version": "0.0.32", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.32.tgz", @@ -8291,12 +8514,6 @@ "colors": "^1.1.2" } }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", - "dev": true - }, "keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", @@ -8310,31 +8527,13 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", "dev": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true, - "optional": true - } - } - }, "kuler": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", - "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "integrity": "sha1-73x4TzbJ+24W3TFQ0VJneysCKKY=", "dev": true, "requires": { "colornames": "^1.1.1" @@ -8379,7 +8578,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -8394,7 +8593,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -8446,7 +8645,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -8462,6 +8661,22 @@ "type-check": "~0.3.2" } }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -8502,9 +8717,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash._basecopy": { @@ -8641,6 +8856,12 @@ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", @@ -8727,7 +8948,7 @@ "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -8747,7 +8968,7 @@ "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", "dev": true, "optional": true }, @@ -8803,7 +9024,7 @@ "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -8847,6 +9068,20 @@ "micromatch": "^3.0.4", "resolve": "^1.4.0", "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + } } }, "math-random": { @@ -8870,7 +9105,7 @@ "memoizee": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "integrity": "sha1-B6APIEaZ+alcLZ53IYJxx81hDVc=", "dev": true, "requires": { "d": "1", @@ -8926,7 +9161,7 @@ "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -8969,7 +9204,7 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", "dev": true }, "mimic-response": { @@ -8997,7 +9232,7 @@ "minimize": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/minimize/-/minimize-2.2.0.tgz", - "integrity": "sha512-IxR2XMbw9pXCxApkdD9BTcH2U4XlXhbeySUrv71rmMS9XDA8BVXEsIuFu24LtwCfBgfbL7Fuh8/ZzkO5DaTLlQ==", + "integrity": "sha1-ixZ28wBR2FmNdDZGvRJpCwdNpMM=", "dev": true, "requires": { "argh": "^0.1.4", @@ -9022,7 +9257,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -9070,7 +9305,7 @@ "mute-stdout": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "integrity": "sha1-rLAwDrTeI6fd7sAU4+lgRLNHIzE=", "dev": true }, "mute-stream": { @@ -9089,7 +9324,7 @@ "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -9131,7 +9366,7 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", "dev": true }, "node-notifier": { @@ -9196,13 +9431,13 @@ "normalize-url": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=", "dev": true }, "nouislider": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-14.0.2.tgz", - "integrity": "sha512-N4AQStV4frh+XcLUwMI/hZpBP6tRboDE/4LZ7gzfxMVXFi/2J9URphnm40Ff4KEyrAVGSGaWApvljoMzTNWBlA==" + "version": "14.6.2", + "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-14.6.2.tgz", + "integrity": "sha512-/lJeqJBghNAZS3P2VYrHzm1RM6YJPvvC/1wNpGaHBRX+05wpzUDafrW/ohAYp4kjKhRH8+BJ0vkorCHiMmgTMQ==" }, "now-and-later": { "version": "2.0.1", @@ -9214,9 +9449,9 @@ } }, "npm": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.0.tgz", - "integrity": "sha512-zjSJ8zjk0cDBZXqTWbQ6+qOdm1m2k489YDFP60RQRUhOxT5LOBhl+cDtFlEXEIblcNjofmsZ/qQ/wzmn5frimQ==", + "version": "6.14.9", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.9.tgz", + "integrity": "sha512-yHi1+i9LyAZF1gAmgyYtVk+HdABlLy94PMIDoK1TRKWvmFQAt5z3bodqVwKvzY0s6dLqQPVsRLiwhJfNtiHeCg==", "requires": { "JSONStream": "^1.3.5", "abbrev": "~1.1.1", @@ -9224,12 +9459,12 @@ "ansistyles": "~0.1.3", "aproba": "^2.0.0", "archy": "~1.0.0", - "bin-links": "^1.1.3", + "bin-links": "^1.1.8", "bluebird": "^3.5.5", "byte-size": "^5.0.1", "cacache": "^12.0.3", "call-limit": "^1.1.1", - "chownr": "^1.1.3", + "chownr": "^1.1.4", "ci-info": "^2.0.0", "cli-columns": "^3.1.2", "cli-table3": "^0.5.1", @@ -9245,11 +9480,11 @@ "find-npm-prefix": "^1.0.2", "fs-vacuum": "~1.2.10", "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.2.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.3", + "gentle-fs": "^2.3.1", + "glob": "^7.1.6", + "graceful-fs": "^4.2.4", "has-unicode": "~2.0.1", - "hosted-git-info": "^2.8.5", + "hosted-git-info": "^2.8.8", "iferr": "^1.0.2", "imurmurhash": "*", "infer-owner": "^1.0.4", @@ -9260,14 +9495,14 @@ "is-cidr": "^3.0.0", "json-parse-better-errors": "^1.0.2", "lazy-property": "~1.0.0", - "libcipm": "^4.0.7", + "libcipm": "^4.0.8", "libnpm": "^3.0.1", "libnpmaccess": "^3.0.2", "libnpmhook": "^5.0.3", "libnpmorg": "^1.0.1", "libnpmsearch": "^2.0.2", "libnpmteam": "^1.0.2", - "libnpx": "^10.2.0", + "libnpx": "^10.2.4", "lock-verify": "^2.1.0", "lockfile": "^1.0.4", "lodash._baseindexof": "*", @@ -9282,28 +9517,28 @@ "lodash.uniq": "~4.5.0", "lodash.without": "~4.4.0", "lru-cache": "^5.1.1", - "meant": "~1.0.1", + "meant": "^1.0.2", "mississippi": "^3.0.0", - "mkdirp": "~0.5.1", + "mkdirp": "^0.5.5", "move-concurrently": "^1.0.1", - "node-gyp": "^5.0.5", - "nopt": "~4.0.1", + "node-gyp": "^5.1.0", + "nopt": "^4.0.3", "normalize-package-data": "^2.5.0", - "npm-audit-report": "^1.3.2", + "npm-audit-report": "^1.3.3", "npm-cache-filename": "~1.0.2", "npm-install-checks": "^3.0.2", - "npm-lifecycle": "^3.1.4", + "npm-lifecycle": "^3.1.5", "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.6", + "npm-packlist": "^1.4.8", "npm-pick-manifest": "^3.0.2", - "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.2", - "npm-user-validate": "~1.0.0", + "npm-profile": "^4.0.4", + "npm-registry-fetch": "^4.0.7", + "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "once": "~1.4.0", "opener": "^1.5.1", "osenv": "^0.1.5", - "pacote": "^9.5.9", + "pacote": "^9.5.12", "path-is-inside": "~1.0.2", "promise-inflight": "~1.0.1", "qrcode-terminal": "^0.12.0", @@ -9312,13 +9547,13 @@ "read": "~1.0.7", "read-cmd-shim": "^1.0.5", "read-installed": "~4.0.3", - "read-package-json": "^2.1.0", + "read-package-json": "^2.1.1", "read-package-tree": "^5.3.1", - "readable-stream": "^3.4.0", + "readable-stream": "^3.6.0", "readdir-scoped-modules": "^1.1.0", "request": "^2.88.0", "retry": "^0.12.0", - "rimraf": "^2.6.3", + "rimraf": "^2.7.1", "safe-buffer": "^5.1.2", "semver": "^5.7.1", "sha": "^3.0.0", @@ -9369,16 +9604,6 @@ "humanize-ms": "^1.2.1" } }, - "ajv": { - "version": "5.5.2", - "bundled": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, "ansi-align": { "version": "2.0.0", "bundled": true, @@ -9483,13 +9708,14 @@ } }, "bin-links": { - "version": "1.1.3", + "version": "1.1.8", "bundled": true, "requires": { "bluebird": "^3.5.3", "cmd-shim": "^3.0.0", - "gentle-fs": "^2.0.1", + "gentle-fs": "^2.3.0", "graceful-fs": "^4.1.15", + "npm-normalize-package-bin": "^1.0.0", "write-file-atomic": "^2.3.0" } }, @@ -9581,7 +9807,7 @@ } }, "chownr": { - "version": "1.1.3", + "version": "1.1.4", "bundled": true }, "ci-info": { @@ -9617,23 +9843,36 @@ } }, "cliui": { - "version": "4.1.0", + "version": "5.0.0", "bundled": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", + "version": "4.1.0", "bundled": true }, - "strip-ansi": { - "version": "4.0.0", + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "3.1.0", "bundled": true, "requires": { - "ansi-regex": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "bundled": true, + "requires": { + "ansi-regex": "^4.1.0" } } } @@ -9650,10 +9889,6 @@ "mkdirp": "~0.5.0" } }, - "co": { - "version": "4.6.0", - "bundled": true - }, "code-point-at": { "version": "1.1.0", "bundled": true @@ -9734,10 +9969,10 @@ } }, "configstore": { - "version": "3.1.2", + "version": "3.1.5", "bundled": true, "requires": { - "dot-prop": "^4.1.0", + "dot-prop": "^4.2.1", "graceful-fs": "^4.1.2", "make-dir": "^1.0.0", "unique-string": "^1.0.0", @@ -9846,7 +10081,7 @@ "bundled": true }, "deep-extend": { - "version": "0.5.1", + "version": "0.6.0", "bundled": true }, "defaults": { @@ -9888,7 +10123,7 @@ } }, "dot-prop": { - "version": "4.2.0", + "version": "4.2.1", "bundled": true, "requires": { "is-obj": "^1.0.0" @@ -9947,6 +10182,10 @@ "version": "1.0.0", "bundled": true }, + "emoji-regex": { + "version": "7.0.3", + "bundled": true + }, "encoding": { "version": "0.1.12", "bundled": true, @@ -9962,7 +10201,7 @@ } }, "env-paths": { - "version": "1.0.0", + "version": "2.2.0", "bundled": true }, "err-code": { @@ -10038,10 +10277,6 @@ "version": "1.3.0", "bundled": true }, - "fast-deep-equal": { - "version": "1.1.0", - "bundled": true - }, "fast-json-stable-stringify": { "version": "2.0.0", "bundled": true @@ -10054,13 +10289,6 @@ "version": "1.0.2", "bundled": true }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "flush-write-stream": { "version": "1.0.3", "bundled": true, @@ -10238,11 +10466,12 @@ "bundled": true }, "gentle-fs": { - "version": "2.2.1", + "version": "2.3.1", "bundled": true, "requires": { "aproba": "^1.1.2", "chownr": "^1.1.2", + "cmd-shim": "^3.0.3", "fs-vacuum": "^1.2.10", "graceful-fs": "^4.1.11", "iferr": "^0.1.5", @@ -10264,7 +10493,7 @@ } }, "get-caller-file": { - "version": "1.0.2", + "version": "2.0.5", "bundled": true }, "get-stream": { @@ -10282,7 +10511,7 @@ } }, "glob": { - "version": "7.1.4", + "version": "7.1.6", "bundled": true, "requires": { "fs.realpath": "^1.0.0", @@ -10324,7 +10553,7 @@ } }, "graceful-fs": { - "version": "4.2.3", + "version": "4.2.4", "bundled": true }, "har-schema": { @@ -10332,11 +10561,31 @@ "bundled": true }, "har-validator": { - "version": "5.1.0", + "version": "5.1.5", "bundled": true, "requires": { - "ajv": "^5.3.0", + "ajv": "^6.12.3", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "bundled": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "bundled": true + } } }, "has": { @@ -10359,7 +10608,7 @@ "bundled": true }, "hosted-git-info": { - "version": "2.8.5", + "version": "2.8.8", "bundled": true }, "http-cache-semantics": { @@ -10384,7 +10633,7 @@ } }, "https-proxy-agent": { - "version": "2.2.2", + "version": "2.2.4", "bundled": true, "requires": { "agent-base": "^4.3.0", @@ -10458,10 +10707,6 @@ "validate-npm-package-name": "^3.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "bundled": true - }, "ip": { "version": "1.1.5", "bundled": true @@ -10475,10 +10720,10 @@ "bundled": true }, "is-ci": { - "version": "1.1.0", + "version": "1.2.1", "bundled": true, "requires": { - "ci-info": "^1.0.0" + "ci-info": "^1.5.0" }, "dependencies": { "ci-info": { @@ -10540,7 +10785,7 @@ } }, "is-retry-allowed": { - "version": "1.1.0", + "version": "1.2.0", "bundled": true }, "is-stream": { @@ -10583,10 +10828,6 @@ "version": "0.2.3", "bundled": true }, - "json-schema-traverse": { - "version": "0.3.1", - "bundled": true - }, "json-stringify-safe": { "version": "5.0.1", "bundled": true @@ -10616,15 +10857,8 @@ "version": "1.0.0", "bundled": true }, - "lcid": { - "version": "1.0.0", - "bundled": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "libcipm": { - "version": "4.0.7", + "version": "4.0.8", "bundled": true, "requires": { "bin-links": "^1.1.2", @@ -10633,7 +10867,7 @@ "find-npm-prefix": "^1.0.2", "graceful-fs": "^4.1.11", "ini": "^1.3.5", - "lock-verify": "^2.0.2", + "lock-verify": "^2.1.0", "mkdirp": "^0.5.1", "npm-lifecycle": "^3.0.0", "npm-logical-tree": "^1.2.1", @@ -10779,7 +11013,7 @@ } }, "libnpx": { - "version": "10.2.0", + "version": "10.2.4", "bundled": true, "requires": { "dotenv": "^5.0.1", @@ -10789,15 +11023,7 @@ "update-notifier": "^2.3.0", "which": "^1.3.0", "y18n": "^4.0.0", - "yargs": "^11.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "yargs": "^14.2.3" } }, "lock-verify": { @@ -10893,14 +11119,14 @@ } }, "make-fetch-happen": { - "version": "5.0.0", + "version": "5.0.2", "bundled": true, "requires": { "agentkeepalive": "^3.4.1", "cacache": "^12.0.0", "http-cache-semantics": "^3.8.1", "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", + "https-proxy-agent": "^2.2.3", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "node-fetch-npm": "^2.0.2", @@ -10910,16 +11136,9 @@ } }, "meant": { - "version": "1.0.1", + "version": "1.0.2", "bundled": true }, - "mem": { - "version": "1.1.0", - "bundled": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, "mime-db": { "version": "1.35.0", "bundled": true @@ -10931,10 +11150,6 @@ "mime-db": "~1.35.0" } }, - "mimic-fn": { - "version": "1.2.0", - "bundled": true - }, "minimatch": { "version": "3.0.4", "bundled": true, @@ -10943,7 +11158,7 @@ } }, "minimist": { - "version": "0.0.8", + "version": "1.2.5", "bundled": true }, "minizlib": { @@ -10980,10 +11195,16 @@ } }, "mkdirp": { - "version": "0.5.1", + "version": "0.5.5", "bundled": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "bundled": true + } } }, "move-concurrently": { @@ -11022,37 +11243,24 @@ } }, "node-gyp": { - "version": "5.0.5", + "version": "5.1.0", "bundled": true, "requires": { - "env-paths": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.1.2", + "request": "^2.88.0", + "rimraf": "^2.6.3", + "semver": "^5.7.1", "tar": "^4.4.12", - "which": "1" - }, - "dependencies": { - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1" - } - }, - "semver": { - "version": "5.3.0", - "bundled": true - } + "which": "^1.3.1" } }, "nopt": { - "version": "4.0.1", + "version": "4.0.3", "bundled": true, "requires": { "abbrev": "1", @@ -11079,7 +11287,7 @@ } }, "npm-audit-report": { - "version": "1.3.2", + "version": "1.3.3", "bundled": true, "requires": { "cli-table3": "^0.5.0", @@ -11087,8 +11295,11 @@ } }, "npm-bundled": { - "version": "1.0.6", - "bundled": true + "version": "1.1.1", + "bundled": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } }, "npm-cache-filename": { "version": "1.0.2", @@ -11102,7 +11313,7 @@ } }, "npm-lifecycle": { - "version": "3.1.4", + "version": "3.1.5", "bundled": true, "requires": { "byline": "^5.0.0", @@ -11119,6 +11330,10 @@ "version": "1.2.1", "bundled": true }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true + }, "npm-package-arg": { "version": "6.1.1", "bundled": true, @@ -11130,11 +11345,12 @@ } }, "npm-packlist": { - "version": "1.4.6", + "version": "1.4.8", "bundled": true, "requires": { "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npm-pick-manifest": { @@ -11147,7 +11363,7 @@ } }, "npm-profile": { - "version": "4.0.2", + "version": "4.0.4", "bundled": true, "requires": { "aproba": "^1.1.2 || 2", @@ -11156,7 +11372,7 @@ } }, "npm-registry-fetch": { - "version": "4.0.2", + "version": "4.0.7", "bundled": true, "requires": { "JSONStream": "^1.3.4", @@ -11169,7 +11385,7 @@ }, "dependencies": { "safe-buffer": { - "version": "5.2.0", + "version": "5.2.1", "bundled": true } } @@ -11182,7 +11398,7 @@ } }, "npm-user-validate": { - "version": "1.0.0", + "version": "1.0.1", "bundled": true }, "npmlog": { @@ -11234,15 +11450,6 @@ "version": "1.0.2", "bundled": true }, - "os-locale": { - "version": "2.1.0", - "bundled": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, "os-tmpdir": { "version": "1.0.2", "bundled": true @@ -11259,24 +11466,6 @@ "version": "1.0.0", "bundled": true }, - "p-limit": { - "version": "1.2.0", - "bundled": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "bundled": true - }, "package-json": { "version": "4.0.1", "bundled": true, @@ -11288,7 +11477,7 @@ } }, "pacote": { - "version": "9.5.9", + "version": "9.5.12", "bundled": true, "requires": { "bluebird": "^3.5.3", @@ -11305,6 +11494,7 @@ "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.12", "npm-pick-manifest": "^3.0.0", @@ -11500,19 +11690,13 @@ "bundled": true }, "rc": { - "version": "1.2.7", + "version": "1.2.8", "bundled": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true - } } }, "read": { @@ -11543,14 +11727,14 @@ } }, "read-package-json": { - "version": "2.1.0", + "version": "2.1.1", "bundled": true, "requires": { "glob": "^7.1.1", "graceful-fs": "^4.1.2", "json-parse-better-errors": "^1.0.1", "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "npm-normalize-package-bin": "^1.0.0" } }, "read-package-tree": { @@ -11563,7 +11747,7 @@ } }, "readable-stream": { - "version": "3.4.0", + "version": "3.6.0", "bundled": true, "requires": { "inherits": "^2.0.3", @@ -11582,7 +11766,7 @@ } }, "registry-auth-token": { - "version": "3.3.2", + "version": "3.4.0", "bundled": true, "requires": { "rc": "^1.1.6", @@ -11627,7 +11811,7 @@ "bundled": true }, "require-main-filename": { - "version": "1.0.1", + "version": "2.0.0", "bundled": true }, "resolve-from": { @@ -11639,7 +11823,7 @@ "bundled": true }, "rimraf": { - "version": "2.6.3", + "version": "2.7.1", "bundled": true, "requires": { "glob": "^7.1.3" @@ -11703,24 +11887,20 @@ "version": "3.0.2", "bundled": true }, - "slash": { - "version": "1.0.0", - "bundled": true - }, "slide": { "version": "1.1.6", "bundled": true }, "smart-buffer": { - "version": "4.0.2", + "version": "4.1.0", "bundled": true }, "socks": { - "version": "2.3.2", + "version": "2.3.3", "bundled": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "4.0.2" + "ip": "1.1.5", + "smart-buffer": "^4.1.0" } }, "socks-proxy-agent": { @@ -11801,7 +11981,7 @@ } }, "spdx-license-ids": { - "version": "3.0.3", + "version": "3.0.5", "bundled": true }, "split-on-first": { @@ -11902,10 +12082,16 @@ } }, "string_decoder": { - "version": "1.2.0", + "version": "1.3.0", "bundled": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "bundled": true + } } }, "stringify-package": { @@ -12087,6 +12273,19 @@ "xdg-basedir": "^3.0.0" } }, + "uri-js": { + "version": "4.4.0", + "bundled": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "bundled": true + } + } + }, "url-parse-lax": { "version": "1.0.0", "bundled": true, @@ -12174,7 +12373,7 @@ } }, "widest-line": { - "version": "2.0.0", + "version": "2.0.1", "bundled": true, "requires": { "string-width": "^2.1.1" @@ -12188,20 +12387,36 @@ } }, "wrap-ansi": { - "version": "2.1.0", + "version": "5.1.0", "bundled": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, "string-width": { - "version": "1.0.2", + "version": "3.1.0", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "bundled": true, + "requires": { + "ansi-regex": "^4.1.0" } } } @@ -12236,34 +12451,93 @@ "bundled": true }, "yargs": { - "version": "11.0.0", + "version": "14.2.3", "bundled": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" }, "dependencies": { - "y18n": { - "version": "3.2.1", + "ansi-regex": { + "version": "4.1.0", "bundled": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "bundled": true + }, + "string-width": { + "version": "3.1.0", + "bundled": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "bundled": true, + "requires": { + "ansi-regex": "^4.1.0" + } } } }, "yargs-parser": { - "version": "9.0.2", + "version": "15.0.1", "bundled": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "bundled": true + } } } } @@ -12301,7 +12575,7 @@ "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=", "dev": true, "requires": { "boolbase": "~1.0.0" @@ -12319,10 +12593,16 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=", "dev": true }, "object-assign": { @@ -12771,6 +13051,12 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -12831,7 +13117,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", "dev": true }, "path-root": { @@ -12872,7 +13158,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true + "dev": true, + "optional": true }, "performance-now": { "version": "2.1.0", @@ -12880,37 +13167,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - } - } - }, "picomatch": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", @@ -12941,7 +13197,7 @@ "plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "integrity": "sha1-dwFr2JGdCsN3/c3QMiMolTyleBw=", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -12979,7 +13235,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "supports-color": { @@ -12996,7 +13252,7 @@ "postcss-calc": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", - "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "integrity": "sha1-Ntd7qwI7Dsu5eJ2E3LI8SUEUVDY=", "dev": true, "requires": { "css-unit-converter": "^1.1.1", @@ -13021,7 +13277,7 @@ "postcss-convert-values": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", - "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "integrity": "sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8=", "dev": true, "requires": { "postcss": "^7.0.0", @@ -13040,7 +13296,7 @@ "postcss-discard-duplicates": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", - "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "integrity": "sha1-P+EzzTyCKC5VD8myORdqkge3hOs=", "dev": true, "requires": { "postcss": "^7.0.0" @@ -13049,7 +13305,7 @@ "postcss-discard-empty": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", - "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "integrity": "sha1-yMlR6fc+2UKAGUWERKAq2Qu592U=", "dev": true, "requires": { "postcss": "^7.0.0" @@ -13058,7 +13314,7 @@ "postcss-discard-overridden": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", - "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "integrity": "sha1-ZSrvipZybwKfXj4AFG7npOdV/1c=", "dev": true, "requires": { "postcss": "^7.0.0" @@ -13116,7 +13372,7 @@ "postcss-minify-font-values": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", - "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "integrity": "sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY=", "dev": true, "requires": { "postcss": "^7.0.0", @@ -13177,7 +13433,7 @@ "postcss-normalize-charset": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", - "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "integrity": "sha1-izWt067oOhNrBHHg1ZvlilAoXdQ=", "dev": true, "requires": { "postcss": "^7.0.0" @@ -13243,7 +13499,7 @@ "postcss-normalize-unicode": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", - "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "integrity": "sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs=", "dev": true, "requires": { "browserslist": "^4.0.0", @@ -13254,7 +13510,7 @@ "postcss-normalize-url": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", - "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "integrity": "sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE=", "dev": true, "requires": { "is-absolute-url": "^2.0.0", @@ -13334,7 +13590,7 @@ "postcss-unique-selectors": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "integrity": "sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w=", "dev": true, "requires": { "alphanum-sort": "^1.0.0", @@ -13345,7 +13601,7 @@ "postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", "dev": true }, "prelude-ls": { @@ -13382,7 +13638,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", "dev": true }, "process-nextick-args": { @@ -13400,7 +13656,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", "dev": true, "optional": true, "requires": { @@ -13457,7 +13713,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=", "dev": true }, "q": { @@ -13469,7 +13725,7 @@ "qjobs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=", "dev": true }, "qs": { @@ -13502,7 +13758,7 @@ "randomatic": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "integrity": "sha1-t3bvxZN1mE42xTey9RofCv8Noe0=", "dev": true, "requires": { "is-number": "^4.0.0", @@ -13513,7 +13769,7 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", "dev": true } } @@ -13572,7 +13828,7 @@ "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -13595,7 +13851,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -13610,7 +13866,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -13641,7 +13897,7 @@ "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", "dev": true }, "regenerate-unicode-properties": { @@ -13665,7 +13921,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { "is-equal-shallow": "^0.1.3" @@ -13674,7 +13930,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -13684,7 +13940,7 @@ "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=", "dev": true }, "regexpu-core": { @@ -13754,7 +14010,7 @@ "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", "dev": true }, "repeat-string": { @@ -13793,8 +14049,9 @@ "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", "dev": true, + "optional": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -13823,19 +14080,31 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } } } }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "throttleit": "^1.0.0" + "lodash": "^4.17.19" + } + }, + "request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "dev": true, + "requires": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "require-directory": { @@ -13919,7 +14188,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", "dev": true }, "reusify": { @@ -13982,7 +14251,7 @@ "run-sequence": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.1.tgz", - "integrity": "sha512-qkzZnQWMZjcKbh3CNly2srtrkaO/2H/SI5f2eliMCapdRD3UhMrwjfOAZJAnZ2H8Ju4aBzFZkBGXUqFs9V0yxw==", + "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", "dev": true, "requires": { "chalk": "^1.1.3", @@ -14079,7 +14348,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", "dev": true }, "safe-regex": { @@ -14094,15 +14363,24 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", "dev": true }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", "dev": true }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, "seek-bzip": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", @@ -14203,7 +14481,7 @@ "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "integrity": "sha1-1rkYHBpI05cyTISHHvvPxz/AZUs=", "dev": true }, "signal-exit": { @@ -14215,7 +14493,7 @@ "signalr": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/signalr/-/signalr-2.4.0.tgz", - "integrity": "sha512-GPJHb3pcNk3IUui5/WG8lMuarEn+Vpc8wEvJ60w0KQ43W9FHnJcuNcF8dkZePr81eBslzicsRdyEunKNF7KjZQ==", + "integrity": "sha1-kq8AjmtSetSzbpT7s0DhNQh6YNI=", "requires": { "jquery": ">=1.6.4" } @@ -14232,7 +14510,7 @@ "is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=", "dev": true } } @@ -14265,7 +14543,7 @@ "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { "base": "^0.11.1", @@ -14281,7 +14559,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -14316,7 +14594,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "^1.0.0", @@ -14336,7 +14614,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -14345,7 +14623,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -14354,7 +14632,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -14367,7 +14645,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -14387,7 +14665,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -14401,7 +14679,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -14424,7 +14702,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -14452,7 +14730,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -14469,7 +14747,7 @@ "socket.io-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "integrity": "sha1-58Yii2qh+BTmFIrqMltRqpSZ4Hc=", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -14535,7 +14813,7 @@ "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", "dev": true, "requires": { "atob": "^2.1.1", @@ -14554,7 +14832,7 @@ "sparkles": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "integrity": "sha1-AI22XtzmxQ7sDF4ijhlFBh3QQ3w=", "dev": true }, "spdx-correct": { @@ -14570,13 +14848,13 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -14589,15 +14867,15 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "spectrum-colorpicker": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/spectrum-colorpicker/-/spectrum-colorpicker-1.8.0.tgz", - "integrity": "sha1-uSbPUALAp3hgtfg1HhwJPGUgAQc=" + "spectrum-colorpicker2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/spectrum-colorpicker2/-/spectrum-colorpicker2-2.0.3.tgz", + "integrity": "sha512-uEmzdiPqSHgJ1sJvEiwsuYAt7ep/GltjWZ7yloMDFMPcr4qQmmwX4UqlFz7C2HxmmqA51jx51FfgiF65s7R3Pg==" }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -14671,7 +14949,7 @@ "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", "dev": true }, "stack-trace": { @@ -14707,6 +14985,12 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -14735,7 +15019,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "dev": true, "requires": { "ms": "^2.1.1" @@ -14835,6 +15119,12 @@ "strip-bom": "^2.0.0" } }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -14871,7 +15161,7 @@ "strip-outer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "integrity": "sha1-sv0qv2YEudHmATBXGV34Nrip1jE=", "dev": true, "optional": true, "requires": { @@ -14905,7 +15195,7 @@ "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -14942,6 +15232,12 @@ "util.promisify": "~1.0.0" } }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -14991,7 +15287,7 @@ "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "integrity": "sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU=", "dev": true, "optional": true, "requires": { @@ -15014,7 +15310,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "optional": true, "requires": { @@ -15030,7 +15326,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "optional": true, "requires": { @@ -15060,7 +15356,7 @@ "text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "integrity": "sha1-adycGxdEbueakr9biEu0uRJ1BvU=", "dev": true }, "text-table": { @@ -15069,12 +15365,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -15084,7 +15374,7 @@ "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", "dev": true, "requires": { "readable-stream": "~2.3.6", @@ -15100,7 +15390,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -15115,7 +15405,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -15158,7 +15448,7 @@ "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "integrity": "sha1-b1ethXjgej+5+R2Th9ZWR1VeJcY=", "dev": true, "requires": { "es5-ext": "~0.10.46", @@ -15177,14 +15467,14 @@ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" }, "tinymce": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.9.2.tgz", - "integrity": "sha512-ZRoTGG4GAsOI73QPSNkabO7nkoYw9H6cglRB44W2mMkxSiqxYi8WJlgkUphk0fDqo6ZD6r3E+NSP4UHxF2lySg==" + "version": "4.9.11", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.9.11.tgz", + "integrity": "sha512-nkSLsax+VY5DBRjMFnHFqPwTnlLEGHCco82FwJF2JNH6W+5/ClvNC1P4uhD5lXPDNiDykSHR0XJdEh7w/ICHzA==" }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -15209,7 +15499,7 @@ "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=", "dev": true, "optional": true }, @@ -15242,7 +15532,7 @@ "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { "define-property": "^2.0.2", @@ -15279,7 +15569,7 @@ "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=", "dev": true, "requires": { "psl": "^1.1.24", @@ -15294,6 +15584,15 @@ } } }, + "tr46": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", + "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -15328,7 +15627,6 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -15436,7 +15734,7 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, "unbzip2-stream": { @@ -15459,7 +15757,7 @@ "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + "integrity": "sha1-BtzjSg5op7q8KbNluOdLiSUgOWE=" }, "undertaker": { "version": "1.2.1", @@ -15487,13 +15785,13 @@ "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", "dev": true }, "unicode-match-property-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", "dev": true, "requires": { "unicode-canonical-property-names-ecmascript": "^1.0.4", @@ -15619,7 +15917,7 @@ "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", "dev": true, "requires": { "punycode": "^2.1.0" @@ -15651,7 +15949,7 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", "dev": true }, "useragent": { @@ -15673,7 +15971,7 @@ "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", "dev": true, "requires": { "define-properties": "^1.1.2", @@ -15698,10 +15996,19 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -15931,6 +16238,56 @@ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz", + "integrity": "sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^2.0.2", + "webidl-conversions": "^6.1.0" + } + }, "when": { "version": "3.7.8", "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", @@ -15940,7 +16297,7 @@ "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", "dev": true, "requires": { "isexe": "^2.0.0" @@ -15952,6 +16309,11 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "wicg-inert": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/wicg-inert/-/wicg-inert-3.1.0.tgz", + "integrity": "sha512-P0ZiWaN9SxOkJbYtF/PIwmIRO8UTqTJtyl33QTQlHfAb6h15T0Dp5m7WTJ8N6UWIoj+KU5M0a8EtfRZLlHiP0Q==" + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -15992,7 +16354,7 @@ "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", "dev": true, "requires": { "async-limiter": "~1.0.0", @@ -16000,12 +16362,24 @@ "ultron": "~1.1.0" } }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, "xmlbuilder": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-12.0.0.tgz", "integrity": "sha512-lMo8DJ8u6JRWp0/Y4XLa/atVDr75H9litKlb2E5j3V3MesoL50EBgZDWoLT3F/LztVnG67GjPXLZpqcky/UMnQ==", "dev": true }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", @@ -16031,9 +16405,9 @@ "dev": true }, "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", "dev": true, "requires": { "camelcase": "^3.0.0", @@ -16048,16 +16422,17 @@ "string-width": "^1.0.2", "which-module": "^1.0.0", "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" + "yargs-parser": "5.0.0-security.0" } }, "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", "dev": true, "requires": { - "camelcase": "^3.0.0" + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" } }, "yauzl": { From b20ce5a92ea8adcc2b134679ca0c7aae8225495f Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 09:50:05 +1100 Subject: [PATCH 09/26] A bunch of cleanup for DI namespaces, ext methods and dist cache classes --- .../Cache/DistributedCacheBinderComponent.cs | 22 -- .../Composing/CollectionBuilderBase.cs | 3 +- .../Composing/CompositionExtensions.cs | 3 +- .../Composing/TypeCollectionBuilderBase.cs | 1 + .../ServiceCollectionExtensions.cs | 9 +- .../ServiceProviderExtensions.cs | 8 +- .../UmbracoBuilder.Collections.cs} | 20 +- .../DependencyInjection/UmbracoBuilder.cs | 29 +- src/Umbraco.Core/IO/FileSystems.cs | 1 + .../Sync/IBatchedDatabaseServerMessenger.cs | 6 +- .../Sync/IDatabaseServerMessenger.cs | 7 - src/Umbraco.Core/Sync/IServerMessenger.cs | 10 +- src/Umbraco.Core/Sync/IServerRegistrar.cs | 4 +- .../ExamineLuceneComposer.cs | 1 - .../BatchedDatabaseServerMessenger.cs | 28 +- ...abaseServerMessengerNotificationHandler.cs | 93 +++++ .../Cache/DistributedCacheBinderComposer.cs | 20 -- ...aseServerRegistrarAndMessengerComponent.cs | 121 ------- .../Compose/NotificationsComposer.cs | 3 +- .../CompositionExtensions/FileSystems.cs | 1 + .../CompositionExtensions/Installer.cs | 1 - .../CompositionExtensions.cs | 335 ------------------ .../UmbracoBuilder.Collections.cs | 96 +++++ .../UmbracoBuilder.CoreServices.cs} | 37 +- .../UmbracoBuilder.DistributedCache.cs | 138 ++++++++ .../UmbracoBuilder.Uniques.cs | 157 ++++++++ .../InstructionProcessTask.cs | 4 +- .../Logging/Serilog/SerilogComposer.cs | 1 - .../Logging/Viewer/LogViewerComposer.cs | 1 + .../Migrations/MigrationBuilder.cs | 1 + .../NoopPublishedSnapshotRebuilder.cs | 12 - .../Scoping/IScopeProvider.cs | 4 +- .../Search/ExamineComposer.cs | 3 +- .../Sync/DatabaseServerMessenger.cs | 157 ++++---- .../Sync/ServerMessengerBase.cs | 4 +- .../WebAssets/WebAssetsComposer.cs | 1 - .../Compose/ModelsBuilderComposer.cs | 1 - .../UmbracoBuilderExtensions.cs | 1 - src/Umbraco.Tests.Integration/RuntimeTests.cs | 47 +-- .../Testing/IntegrationTestComposer.cs | 10 +- .../Scoping/ScopedRepositoryTests.cs | 2 + .../Services/ContentEventsTests.cs | 2 + .../TestHelpers/BaseUsingSqlSyntax.cs | 1 - .../TestHelpers/TestHelper.cs | 1 + .../DistributedCache/DistributedCacheTests.cs | 14 +- .../InstructionProcessTaskTests.cs | 4 +- .../Cache/DistributedCacheBinderTests.cs | 1 - .../PublishedContentLanguageVariantTests.cs | 1 + .../PublishedContentSnapshotTestBase.cs | 2 +- .../PublishedContent/PublishedContentTests.cs | 1 + .../PublishedContent/PublishedMediaTests.cs | 1 + .../Routing/RenderRouteHandlerTests.cs | 1 + ...oviderWithHideTopLevelNodeFromPathTests.cs | 2 +- .../Routing/UrlRoutingTestBase.cs | 2 +- .../Routing/UrlsProviderWithDomainsTests.cs | 2 +- .../Routing/UrlsWithNestedDomains.cs | 2 +- .../Scoping/ScopeEventDispatcherTests.cs | 1 - .../Scoping/ScopedNuCacheTests.cs | 1 + src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 3 + src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 1 + .../TestHelpers/TestWithDatabaseBase.cs | 1 + src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 1 + .../UmbracoExamine/ExamineBaseTest.cs | 2 +- .../AuthenticationControllerTests.cs | 2 +- .../Runtime/BackOfficeComposer.cs | 1 - .../UmbracoBuilderExtensions.cs | 7 + .../Extensions/LinkGeneratorExtensions.cs | 3 +- .../UmbracoCoreServiceCollectionExtensions.cs | 2 +- .../Profiler/WebProfilerComposer.cs | 1 - .../Runtime/AspNetCoreBootFailedComposer.cs | 1 - .../RuntimeMinification/SmidgeComposer.cs | 3 +- .../Runtime/WebsiteComposer.cs | 1 - src/Umbraco.Web/UmbracoBuilderExtensions.cs | 1 - 74 files changed, 737 insertions(+), 737 deletions(-) delete mode 100644 src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs rename src/Umbraco.Core/{ => DependencyInjection}/ServiceCollectionExtensions.cs (92%) rename src/Umbraco.Core/{ => DependencyInjection}/ServiceProviderExtensions.cs (96%) rename src/Umbraco.Core/{CompositionExtensions.cs => DependencyInjection/UmbracoBuilder.Collections.cs} (93%) delete mode 100644 src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs create mode 100644 src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs delete mode 100644 src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs delete mode 100644 src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs delete mode 100644 src/Umbraco.Infrastructure/CompositionExtensions.cs create mode 100644 src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs rename src/Umbraco.Infrastructure/{Runtime/CoreInitialServices.cs => DependencyInjection/UmbracoBuilder.CoreServices.cs} (95%) create mode 100644 src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs create mode 100644 src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs delete mode 100644 src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs diff --git a/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs b/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs deleted file mode 100644 index 31e876892e..0000000000 --- a/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Cache -{ - public class DistributedCacheBinderComponent : IComponent - { - private readonly IDistributedCacheBinder _binder; - - public DistributedCacheBinderComponent(IDistributedCacheBinder distributedCacheBinder) - { - _binder = distributedCacheBinder; - } - - public void Initialize() - { - _binder.BindEvents(); - } - - public void Terminate() - { } - } -} diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 1c4de6cd8e..14089ba924 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Core.Composing { diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index e4e02443eb..d7b143df38 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -1,5 +1,4 @@ -using System; -using Umbraco.Core; +using System; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Web.PublishedCache; diff --git a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs index edbf554a2c..9229a95cc3 100644 --- a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Core.Composing { diff --git a/src/Umbraco.Core/ServiceCollectionExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs similarity index 92% rename from src/Umbraco.Core/ServiceCollectionExtensions.cs rename to src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs index d1c89ea17e..51ff6b705f 100644 --- a/src/Umbraco.Core/ServiceCollectionExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs @@ -1,9 +1,10 @@ -using System; +using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Umbraco.Core; using Umbraco.Core.Composing; -namespace Umbraco.Core +namespace Umbraco.Core.DependencyInjection { public static class ServiceCollectionExtensions { @@ -21,7 +22,7 @@ namespace Umbraco.Core where TImplementing : class, TService1, TService2 { services.AddUnique(); - services.AddUnique(factory => (TImplementing) factory.GetRequiredService()); + services.AddUnique(factory => (TImplementing)factory.GetRequiredService()); } public static void AddUnique(this IServiceCollection services) @@ -48,7 +49,7 @@ namespace Umbraco.Core /// public static void AddUnique(this IServiceCollection services, TService instance) where TService : class - => services.Replace(ServiceDescriptor.Singleton(instance)); + => services.Replace(ServiceDescriptor.Singleton(instance)); public static IServiceCollection AddLazySupport(this IServiceCollection services) { diff --git a/src/Umbraco.Core/ServiceProviderExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs similarity index 96% rename from src/Umbraco.Core/ServiceProviderExtensions.cs rename to src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs index e0d3da2c03..a1cc779500 100644 --- a/src/Umbraco.Core/ServiceProviderExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using System; using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.Composing; -namespace Umbraco.Core +namespace Umbraco.Core.DependencyInjection { /// /// Provides extension methods to the class. diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs similarity index 93% rename from src/Umbraco.Core/CompositionExtensions.cs rename to src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs index 58aac7b811..35d8ba1025 100644 --- a/src/Umbraco.Core/CompositionExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs @@ -1,4 +1,3 @@ -using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Core.HealthCheck; using Umbraco.Core.Manifest; @@ -11,18 +10,17 @@ using Umbraco.Web.Routing; using Umbraco.Web.Sections; using Umbraco.Web.Tour; -namespace Umbraco.Core +namespace Umbraco.Core.DependencyInjection { - public static partial class CompositionExtensions + /// + /// Extension methods for + /// + public static partial class UmbracoBuilderExtensions { - - #region Collection Builders - /// /// Gets the actions collection builder. /// /// The builder. - /// public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -30,7 +28,6 @@ namespace Umbraco.Core /// Gets the content apps collection builder. /// /// The builder. - /// public static ContentAppFactoryCollectionBuilder ContentApps(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -38,7 +35,6 @@ namespace Umbraco.Core /// Gets the content finders collection builder. /// /// The builder. - /// public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -46,7 +42,6 @@ namespace Umbraco.Core /// Gets the editor validators collection builder. /// /// The builder. - /// public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -90,7 +85,6 @@ namespace Umbraco.Core public static ComponentCollectionBuilder Components(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); - /// /// Gets the backoffice dashboards collection builder. /// @@ -109,15 +103,11 @@ namespace Umbraco.Core .Add() .Add(); - /// /// Gets the content finders collection builder. /// /// The builder. - /// public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); - - #endregion } } diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index d56712cdcf..1c05695429 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -14,17 +14,26 @@ namespace Umbraco.Core.DependencyInjection { public class UmbracoBuilder : IUmbracoBuilder { - public IServiceCollection Services { get; } - public IConfiguration Config { get; } - public TypeLoader TypeLoader { get; } - public ILoggerFactory BuilderLoggerFactory { get; } - private readonly Dictionary _builders = new Dictionary(); + public IServiceCollection Services { get; } + + public IConfiguration Config { get; } + + public TypeLoader TypeLoader { get; } + + public ILoggerFactory BuilderLoggerFactory { get; } + + /// + /// Initializes a new instance of the class. + /// public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader) : this(services, config, typeLoader, NullLoggerFactory.Instance) { } + /// + /// Initializes a new instance of the class. + /// public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader, ILoggerFactory loggerFactory) { Services = services; @@ -43,10 +52,12 @@ namespace Umbraco.Core.DependencyInjection public TBuilder WithCollectionBuilder() where TBuilder : ICollectionBuilder, new() { - var typeOfBuilder = typeof(TBuilder); + Type typeOfBuilder = typeof(TBuilder); - if (_builders.TryGetValue(typeOfBuilder, out var o)) + if (_builders.TryGetValue(typeOfBuilder, out ICollectionBuilder o)) + { return (TBuilder)o; + } var builder = new TBuilder(); _builders[typeOfBuilder] = builder; @@ -55,8 +66,10 @@ namespace Umbraco.Core.DependencyInjection public void Build() { - foreach (var builder in _builders.Values) + foreach (ICollectionBuilder builder in _builders.Values) + { builder.RegisterWith(Services); + } _builders.Clear(); } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index b078172213..62f46edce4 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.Hosting; using Umbraco.Core.Configuration.Models; using Microsoft.Extensions.Options; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Core.IO { diff --git a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs index 560b7fb235..02859ff6f0 100644 --- a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs @@ -3,10 +3,10 @@ namespace Umbraco.Core.Sync /// /// An implementation that works by storing messages in the database. /// - public interface IBatchedDatabaseServerMessenger : IDatabaseServerMessenger + public interface IBatchedDatabaseServerMessenger : IServerMessenger { + // TODO: We only ever use IBatchedDatabaseServerMessenger so just combine these interfaces + void FlushBatch(); - DatabaseServerMessengerCallbacks Callbacks { get; } - void Startup(); } } diff --git a/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs deleted file mode 100644 index a49cfdd023..0000000000 --- a/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Umbraco.Core.Sync -{ - public interface IDatabaseServerMessenger: IServerMessenger - { - void Sync(); - } -} diff --git a/src/Umbraco.Core/Sync/IServerMessenger.cs b/src/Umbraco.Core/Sync/IServerMessenger.cs index b8300b2d6d..a6c5b5d755 100644 --- a/src/Umbraco.Core/Sync/IServerMessenger.cs +++ b/src/Umbraco.Core/Sync/IServerMessenger.cs @@ -1,15 +1,19 @@ -using System; -using System.Collections.Generic; +using System; using Umbraco.Core.Cache; namespace Umbraco.Core.Sync { /// - /// Broadcasts distributed cache notifications to all servers of a load balanced environment. + /// Transmits distributed cache notifications for all servers of a load balanced environment. /// /// Also ensures that the notification is processed on the local environment. public interface IServerMessenger { + /// + /// Called to synchronize a server with queued notifications + /// + void Sync(); + /// /// Notifies the distributed cache, for a specified . /// diff --git a/src/Umbraco.Core/Sync/IServerRegistrar.cs b/src/Umbraco.Core/Sync/IServerRegistrar.cs index 780f865ad7..7e63b6b170 100644 --- a/src/Umbraco.Core/Sync/IServerRegistrar.cs +++ b/src/Umbraco.Core/Sync/IServerRegistrar.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Umbraco.Core.Sync { @@ -10,7 +10,7 @@ namespace Umbraco.Core.Sync /// /// Gets the server registrations. /// - IEnumerable Registrations { get; } + IEnumerable Registrations { get; } // TODO: This isn't even used anymore, this whole interface can probably go away /// /// Gets the role of the current server in the application environment. diff --git a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs index e2f2460d58..05315b05fe 100644 --- a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs +++ b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs @@ -1,5 +1,4 @@ using System.Runtime.InteropServices; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs index 187eced6e4..bafb537db6 100644 --- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Logging; @@ -25,13 +25,11 @@ namespace Umbraco.Web /// public class BatchedDatabaseServerMessenger : DatabaseServerMessenger, IBatchedDatabaseServerMessenger { - private readonly IUmbracoDatabaseFactory _databaseFactory; private readonly IRequestCache _requestCache; private readonly IRequestAccessor _requestAccessor; public BatchedDatabaseServerMessenger( IMainDom mainDom, - IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, IProfilingLogger proflog, ILogger logger, @@ -42,34 +40,12 @@ namespace Umbraco.Web IRequestCache requestCache, IRequestAccessor requestAccessor, IOptions globalSettings) - : base(mainDom, scopeProvider, databaseFactory, proflog, logger, serverRegistrar, true, callbacks, hostingEnvironment, cacheRefreshers, globalSettings) + : base(mainDom, scopeProvider, proflog, logger, serverRegistrar, true, callbacks, hostingEnvironment, cacheRefreshers, globalSettings) { - _databaseFactory = databaseFactory; _requestCache = requestCache; _requestAccessor = requestAccessor; } - // invoked by DatabaseServerRegistrarAndMessengerComponent - public void Startup() - { - _requestAccessor.EndRequest += UmbracoModule_EndRequest; - - if (_databaseFactory.CanConnect == false) - { - Logger.LogWarning("Cannot connect to the database, distributed calls will not be enabled for this server."); - } - else - { - Boot(); - } - } - - private void UmbracoModule_EndRequest(object sender, UmbracoRequestEventArgs e) - { - // will clear the batch - will remain in HttpContext though - that's ok - FlushBatch(); - } - protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) { var idsA = ids?.ToArray(); diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs new file mode 100644 index 0000000000..b0921f7698 --- /dev/null +++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs @@ -0,0 +1,93 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Umbraco.Core.Events; +using Umbraco.Core.Persistence; +using Umbraco.Core.Sync; +using Umbraco.Web; +using Umbraco.Web.Cache; +using Umbraco.Web.Routing; + +namespace Umbraco.Infrastructure.Cache +{ + /// + /// Ensures that distributed cache events are setup and the is initialized + /// + public sealed class DatabaseServerMessengerNotificationHandler : INotificationHandler + { + private readonly IBatchedDatabaseServerMessenger _messenger; + private readonly IRequestAccessor _requestAccessor; + private readonly IUmbracoDatabaseFactory _databaseFactory; + private readonly IDistributedCacheBinder _distributedCacheBinder; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public DatabaseServerMessengerNotificationHandler( + IServerMessenger serverMessenger, + IRequestAccessor requestAccessor, + IUmbracoDatabaseFactory databaseFactory, + IDistributedCacheBinder distributedCacheBinder, + ILogger logger) + { + _requestAccessor = requestAccessor; + _databaseFactory = databaseFactory; + _distributedCacheBinder = distributedCacheBinder; + _logger = logger; + _messenger = serverMessenger as IBatchedDatabaseServerMessenger; + } + + /// + public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken) + { + // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services. + // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL + // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured). + // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available + // for the hosted services to use when the HTTP request is not available. + _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce; + _requestAccessor.EndRequest += UmbracoModule_EndRequest; + + Startup(); + + return Task.CompletedTask; + } + + private void Startup() + { + if (_databaseFactory.CanConnect == false) + { + _logger.LogWarning("Cannot connect to the database, distributed calls will not be enabled for this server."); + } + else + { + _distributedCacheBinder.BindEvents(); + + // Sync on startup, this will run through the messenger's initialization sequence + _messenger?.Sync(); + } + } + + // TODO: I don't really know or think that the Application Url plays a role anymore with the DB dist cache, + // this might be really old stuff + private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e) + { + if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest) + { + _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce; + EnsureApplicationUrl(); + } + } + + // By retrieving the application URL within the context of a request (as we are here in responding + // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for + // future requests that may not be within an HTTP request (e.g. from hosted services). + private void EnsureApplicationUrl() => _requestAccessor.GetApplicationUrl(); + + /// + /// Clear the batch on end request + /// + private void UmbracoModule_EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.FlushBatch(); + } +} diff --git a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs deleted file mode 100644 index 7279eaf10c..0000000000 --- a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Cache -{ - /// - /// Installs listeners on service events in order to refresh our caches. - /// - [ComposeBefore(typeof(ICoreComposer))] // runs before every other IUmbracoCoreComponent! - public sealed class DistributedCacheBinderComposer : ComponentComposer, ICoreComposer - { - public override void Compose(IUmbracoBuilder builder) - { - base.Compose(builder); - - builder.Services.AddUnique(); - } - } -} diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs deleted file mode 100644 index 8d2a2e19cc..0000000000 --- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Composing; -using Umbraco.Core.Services.Changes; -using Umbraco.Core.Sync; -using Umbraco.Web.Cache; -using Umbraco.Web.PublishedCache; -using Umbraco.Web.Routing; -using Umbraco.Web.Search; - -namespace Umbraco.Web.Compose -{ - /// - /// Ensures that servers are automatically registered in the database, when using the database server registrar. - /// - /// - /// At the moment servers are automatically registered upon first request and then on every - /// request but not more than once per (configurable) period. This really is "for information & debug" purposes so - /// we can look at the table and see what servers are registered - but the info is not used anywhere. - /// Should we actually want to use this, we would need a better and more deterministic way of figuring - /// out the "server address" ie the address to which server-to-server requests should be sent - because it - /// probably is not the "current request address" - especially in multi-domains configurations. - /// - // during Initialize / Startup, we end up checking Examine, which needs to be initialized beforehand - // TODO: should not be a strong dependency on "examine" but on an "indexing component" - [ComposeAfter(typeof(ExamineComposer))] - - public sealed class DatabaseServerRegistrarAndMessengerComposer : ComponentComposer, ICoreComposer - { - public static DatabaseServerMessengerCallbacks GetCallbacks(IServiceProvider factory) - { - return new DatabaseServerMessengerCallbacks - { - //These callbacks will be executed if the server has not been synced - // (i.e. it is a new server or the lastsynced.txt file has been removed) - InitializingCallbacks = new Action[] - { - //rebuild the xml cache file if the server is not synced - () => - { - var publishedSnapshotService = factory.GetRequiredService(); - - // rebuild the published snapshot caches entirely, if the server is not synced - // this is equivalent to DistributedCache RefreshAll... but local only - // (we really should have a way to reuse RefreshAll... locally) - // note: refresh all content & media caches does refresh content types too - publishedSnapshotService.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) }); - publishedSnapshotService.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _, out _); - publishedSnapshotService.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _); - }, - - //rebuild indexes if the server is not synced - // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific - // indexes then they can adjust this logic themselves. - () => - { - var indexRebuilder = factory.GetRequiredService(); - indexRebuilder.RebuildIndexes(false, 5000); - } - } - }; - } - - public override void Compose(IUmbracoBuilder builder) - { - base.Compose(builder); - - builder.SetDatabaseServerMessengerCallbacks(GetCallbacks); - builder.SetServerMessenger(); - } - } - - public sealed class DatabaseServerRegistrarAndMessengerComponent : IComponent - { - private readonly IBatchedDatabaseServerMessenger _messenger; - private readonly IRequestAccessor _requestAccessor; - - public DatabaseServerRegistrarAndMessengerComponent( - IServerMessenger serverMessenger, - IRequestAccessor requestAccessor) - { - _requestAccessor = requestAccessor; - _messenger = serverMessenger as IBatchedDatabaseServerMessenger; - } - - public void Initialize() - { - // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services. - // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL - // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured). - // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available - // for the hosted services to use when the HTTP request is not available. - _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce; - - // Must come last, as it references some _variables - _messenger?.Startup(); - } - - public void Terminate() - { } - - private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e) - { - if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest) - { - _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce; - EnsureApplicationUrl(); - } - } - - private void EnsureApplicationUrl() - { - // By retrieving the application URL within the context of a request (as we are here in responding - // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for - // future requests that may not be within an HTTP request (e.g. from hosted services). - _requestAccessor.GetApplicationUrl(); - } - } -} diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs index 0fee815560..79066dedd7 100644 --- a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs +++ b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs @@ -1,5 +1,4 @@ -using Umbraco.Core; -using Umbraco.Core.DependencyInjection; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; namespace Umbraco.Web.Compose diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs index f098cfaf57..4c8caa89b8 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Strings; +using Umbraco.Infrastructure.DependencyInjection; namespace Umbraco.Core.Composing.CompositionExtensions { diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs index 31b3133e4d..dc3b1e2481 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Web.Install; diff --git a/src/Umbraco.Infrastructure/CompositionExtensions.cs b/src/Umbraco.Infrastructure/CompositionExtensions.cs deleted file mode 100644 index 703c35e06b..0000000000 --- a/src/Umbraco.Infrastructure/CompositionExtensions.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Dictionary; -using Umbraco.Core.IO; -using Umbraco.Core.Logging.Viewer; -using Umbraco.Core.Manifest; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PackageActions; -using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Strings; -using Umbraco.Core.Sync; -using Umbraco.Web.Media.EmbedProviders; -using Umbraco.Web.Search; - -namespace Umbraco.Core -{ - /// - /// Provides extension methods to the class. - /// - public static partial class CompositionExtensions - { - #region Collection Builders - - /// - /// Gets the cache refreshers collection builder. - /// - /// The builder. - public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the mappers collection builder. - /// - /// The builder. - public static MapperCollectionBuilder Mappers(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the package actions collection builder. - /// - /// The builder. - internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the data editor collection builder. - /// - /// The builder. - public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the data value reference factory collection builder. - /// - /// The builder. - public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the property value converters collection builder. - /// - /// The builder. - public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the url segment providers collection builder. - /// - /// The builder. - public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the validators collection builder. - /// - /// The builder. - internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the manifest filter collection builder. - /// - /// The builder. - public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the backoffice OEmbed Providers collection builder. - /// - /// The builder. - public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the back office searchable tree collection builder - /// - /// - /// - public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - #endregion - - #region Uniques - - /// - /// Sets the culture dictionary factory. - /// - /// The type of the factory. - /// The builder. - public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder) - where T : class, ICultureDictionaryFactory - { - builder.Services.AddUnique(); - } - - /// - /// Sets the culture dictionary factory. - /// - /// The builder. - /// A function creating a culture dictionary factory. - public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the culture dictionary factory. - /// - /// The builder. - /// A factory. - public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, ICultureDictionaryFactory factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the published content model factory. - /// - /// The type of the factory. - /// The builder. - public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder) - where T : class, IPublishedModelFactory - { - builder.Services.AddUnique(); - } - - /// - /// Sets the published content model factory. - /// - /// The builder. - /// A function creating a published content model factory. - public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the published content model factory. - /// - /// The builder. - /// A published content model factory. - public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, IPublishedModelFactory factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the server registrar. - /// - /// The type of the server registrar. - /// The builder. - public static void SetServerRegistrar(this IUmbracoBuilder builder) - where T : class, IServerRegistrar - { - builder.Services.AddUnique(); - } - - /// - /// Sets the server registrar. - /// - /// The builder. - /// A function creating a server registrar. - public static void SetServerRegistrar(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the server registrar. - /// - /// The builder. - /// A server registrar. - public static void SetServerRegistrar(this IUmbracoBuilder builder, IServerRegistrar registrar) - { - builder.Services.AddUnique(registrar); - } - - /// - /// Sets the server messenger. - /// - /// The type of the server registrar. - /// The builder. - public static void SetServerMessenger(this IUmbracoBuilder builder) - where T : class, IServerMessenger - { - builder.Services.AddUnique(); - } - - /// - /// Sets the server messenger. - /// - /// The builder. - /// A function creating a server messenger. - public static void SetServerMessenger(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the server messenger. - /// - /// The builder. - /// A server messenger. - public static void SetServerMessenger(this IUmbracoBuilder builder, IServerMessenger registrar) - { - builder.Services.AddUnique(registrar); - } - - /// - /// Sets the database server messenger options. - /// - /// The builder. - /// A function creating the options. - /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. - public static void SetDatabaseServerMessengerCallbacks(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the database server messenger options. - /// - /// The builder. - /// Options. - /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. - public static void SetDatabaseServerMessengerOptions(this IUmbracoBuilder builder, DatabaseServerMessengerCallbacks options) - { - builder.Services.AddUnique(options); - } - - /// - /// Sets the short string helper. - /// - /// The type of the short string helper. - /// The builder. - public static void SetShortStringHelper(this IUmbracoBuilder builder) - where T : class, IShortStringHelper - { - builder.Services.AddUnique(); - } - - /// - /// Sets the short string helper. - /// - /// The builder. - /// A function creating a short string helper. - public static void SetShortStringHelper(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the short string helper. - /// - /// A builder. - /// A short string helper. - public static void SetShortStringHelper(this IUmbracoBuilder builder, IShortStringHelper helper) - { - builder.Services.AddUnique(helper); - } - - /// - /// Sets the underlying media filesystem. - /// - /// A builder. - /// A filesystem factory. - /// - /// Using this helper will ensure that your IFileSystem implementation is wrapped by the ShadowWrapper - /// - public static void SetMediaFileSystem(this IUmbracoBuilder builder, Func filesystemFactory) - => builder.Services.AddUnique(factory => - { - var fileSystems = factory.GetRequiredService(); - return fileSystems.GetFileSystem(filesystemFactory(factory)); - }); - - /// - /// Sets the log viewer. - /// - /// The type of the log viewer. - /// The builder. - public static void SetLogViewer(this IUmbracoBuilder builder) - where T : class, ILogViewer - { - builder.Services.AddUnique(); - } - - /// - /// Sets the log viewer. - /// - /// The builder. - /// A function creating a log viewer. - public static void SetLogViewer(this IUmbracoBuilder builder, Func factory) - { - builder.Services.AddUnique(factory); - } - - /// - /// Sets the log viewer. - /// - /// A builder. - /// A log viewer. - public static void SetLogViewer(this IUmbracoBuilder builder, ILogViewer viewer) - { - builder.Services.AddUnique(viewer); - } - - #endregion - } -} diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs new file mode 100644 index 0000000000..28bed7b363 --- /dev/null +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs @@ -0,0 +1,96 @@ +using Umbraco.Core.Cache; +using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Manifest; +using Umbraco.Core.PackageActions; +using Umbraco.Core.Persistence.Mappers; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Strings; +using Umbraco.Web.Media.EmbedProviders; +using Umbraco.Web.Search; + +namespace Umbraco.Infrastructure.DependencyInjection +{ + /// + /// Provides extension methods to the class. + /// + public static partial class UmbracoBuilderExtensions + { + /// + /// Gets the cache refreshers collection builder. + /// + /// The builder. + public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the mappers collection builder. + /// + /// The builder. + public static MapperCollectionBuilder Mappers(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the package actions collection builder. + /// + /// The builder. + internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the data editor collection builder. + /// + /// The builder. + public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the data value reference factory collection builder. + /// + /// The builder. + public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the property value converters collection builder. + /// + /// The builder. + public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the url segment providers collection builder. + /// + /// The builder. + public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the validators collection builder. + /// + /// The builder. + internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the manifest filter collection builder. + /// + /// The builder. + public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the backoffice OEmbed Providers collection builder. + /// + /// The builder. + public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the back office searchable tree collection builder + /// + /// + /// + public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + } +} diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs similarity index 95% rename from src/Umbraco.Infrastructure/Runtime/CoreInitialServices.cs rename to src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index 32f5e6bf36..e150f0cdba 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -1,7 +1,6 @@ using System; using Examine; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; @@ -13,9 +12,7 @@ using Umbraco.Core.Dashboards; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; -using Umbraco.Core.Hosting; using Umbraco.Core.Install; -using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.Media; using Umbraco.Core.Migrations; @@ -23,7 +20,6 @@ using Umbraco.Core.Migrations.Install; using Umbraco.Core.Migrations.PostMigrations; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Packaging; -using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.PropertyEditors.ValueConverters; @@ -38,6 +34,7 @@ using Umbraco.Core.Templates; using Umbraco.Examine; using Umbraco.Infrastructure.Examine; using Umbraco.Infrastructure.Media; +using Umbraco.Infrastructure.Runtime; using Umbraco.Web; using Umbraco.Web.Actions; using Umbraco.Web.Cache; @@ -62,10 +59,30 @@ using Umbraco.Web.Templates; using Umbraco.Web.Trees; using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; -namespace Umbraco.Infrastructure.Runtime +namespace Umbraco.Infrastructure.DependencyInjection { - public static class CoreInitialServices + public static partial class UmbracoBuilderExtensions { + + /* + * TODO: Many of these things are not "Core" services and are probably not required to run + * + * This should be split up: + * - Distributed Cache + * - BackOffice + * - Manifest + * - Property Editors + * - Packages + * - Dashboards + * - OEmbed + * - Sections + * - Content Apps + * - Health Checks + * - ETC... + * - Installation + * - Front End + */ + public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder) { builder.AddNotificationHandler(); @@ -130,7 +147,7 @@ namespace Umbraco.Infrastructure.Runtime builder.DataValueReferenceFactories(); // register a server registrar, by default it's the db registrar - builder.Services.AddUnique(f => + builder.Services.AddUnique(f => { var globalSettings = f.GetRequiredService>().Value; @@ -138,7 +155,7 @@ namespace Umbraco.Infrastructure.Runtime // even on 1 single server we can have 2 concurrent app domains var singleServer = globalSettings.DisableElectionForSingleServer; return singleServer - ? (IServerRegistrar) new SingleServerRegistrar(f.GetRequiredService()) + ? (IServerRegistrar)new SingleServerRegistrar(f.GetRequiredService()) : new DatabaseServerRegistrar( new Lazy(f.GetRequiredService)); }); @@ -183,7 +200,6 @@ namespace Umbraco.Infrastructure.Runtime // by default, register a noop factory builder.Services.AddUnique(); - // by default builder.Services.AddUnique(); builder.SetCultureDictionaryFactory(); @@ -253,10 +269,8 @@ namespace Umbraco.Infrastructure.Runtime builder.EditorValidators() .Add(() => builder.TypeLoader.GetTypes()); - builder.TourFilters(); - // replace with web implementation builder.Services.AddUnique(); // register OEmbed providers - no type scanning - all explicit opt-in of adding types @@ -338,7 +352,6 @@ namespace Umbraco.Infrastructure.Runtime // register distributed cache builder.Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService())); - builder.Services.AddScoped(); builder.Services.AddUnique(); diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs new file mode 100644 index 0000000000..4970df2b87 --- /dev/null +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs @@ -0,0 +1,138 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core; +using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Events; +using Umbraco.Core.Services.Changes; +using Umbraco.Core.Sync; +using Umbraco.Infrastructure.Cache; +using Umbraco.Web; +using Umbraco.Web.Cache; +using Umbraco.Web.PublishedCache; +using Umbraco.Web.Search; + +namespace Umbraco.Infrastructure.DependencyInjection +{ + /// + /// Provides extension methods to the class. + /// + public static partial class UmbracoBuilderExtensions + { + /// + /// Adds distributed cache support + /// + public static IUmbracoBuilder AddDistributedCache(this IUmbracoBuilder builder) + { + // NOTE: the `DistributedCache` is registered in AddCoreInitialServices since it's a core service + + builder.SetDatabaseServerMessengerCallbacks(GetCallbacks); + builder.SetServerMessenger(); + builder.AddNotificationHandler(); + + builder.CacheRefreshers() + .Add(() => builder.TypeLoader.GetCacheRefreshers()); + + builder.Services.AddUnique(); + return builder; + } + + /// + /// Sets the server registrar. + /// + /// The type of the server registrar. + /// The builder. + public static void SetServerRegistrar(this IUmbracoBuilder builder) + where T : class, IServerRegistrar + => builder.Services.AddUnique(); + + /// + /// Sets the server registrar. + /// + /// The builder. + /// A function creating a server registrar. + public static void SetServerRegistrar(this IUmbracoBuilder builder, Func factory) + => builder.Services.AddUnique(factory); + + /// + /// Sets the server registrar. + /// + /// The builder. + /// A server registrar. + public static void SetServerRegistrar(this IUmbracoBuilder builder, IServerRegistrar registrar) + => builder.Services.AddUnique(registrar); + + /// + /// Sets the database server messenger options. + /// + /// The builder. + /// A function creating the options. + /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. + public static void SetDatabaseServerMessengerCallbacks(this IUmbracoBuilder builder, Func factory) + => builder.Services.AddUnique(factory); + + /// + /// Sets the database server messenger options. + /// + /// The builder. + /// Options. + /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. + public static void SetDatabaseServerMessengerOptions(this IUmbracoBuilder builder, DatabaseServerMessengerCallbacks options) + => builder.Services.AddUnique(options); + + /// + /// Sets the server messenger. + /// + /// The type of the server registrar. + /// The builder. + public static void SetServerMessenger(this IUmbracoBuilder builder) + where T : class, IServerMessenger + => builder.Services.AddUnique(); + + /// + /// Sets the server messenger. + /// + /// The builder. + /// A function creating a server messenger. + public static void SetServerMessenger(this IUmbracoBuilder builder, Func factory) + => builder.Services.AddUnique(factory); + + /// + /// Sets the server messenger. + /// + /// The builder. + /// A server messenger. + public static void SetServerMessenger(this IUmbracoBuilder builder, IServerMessenger registrar) + => builder.Services.AddUnique(registrar); + + private static DatabaseServerMessengerCallbacks GetCallbacks(IServiceProvider factory) => new DatabaseServerMessengerCallbacks + { + // These callbacks will be executed if the server has not been synced + // (i.e. it is a new server or the lastsynced.txt file has been removed) + InitializingCallbacks = new Action[] + { + // rebuild the xml cache file if the server is not synced + () => + { + IPublishedSnapshotService publishedSnapshotService = factory.GetRequiredService(); + + // rebuild the published snapshot caches entirely, if the server is not synced + // this is equivalent to DistributedCache RefreshAll... but local only + // (we really should have a way to reuse RefreshAll... locally) + // note: refresh all content & media caches does refresh content types too + publishedSnapshotService.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) }); + publishedSnapshotService.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _, out _); + publishedSnapshotService.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _); + }, + + // rebuild indexes if the server is not synced + // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific + // indexes then they can adjust this logic themselves. + () => + { + var indexRebuilder = factory.GetRequiredService(); + indexRebuilder.RebuildIndexes(false, 5000); + } + } + }; + } +} diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs new file mode 100644 index 0000000000..f26b4442f8 --- /dev/null +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs @@ -0,0 +1,157 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Dictionary; +using Umbraco.Core.IO; +using Umbraco.Core.Logging.Viewer; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Strings; +using Umbraco.Core.Sync; + +namespace Umbraco.Infrastructure.DependencyInjection +{ + /// + /// Provides extension methods to the class. + /// + public static partial class UmbracoBuilderExtensions + { + /// + /// Sets the culture dictionary factory. + /// + /// The type of the factory. + /// The builder. + public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder) + where T : class, ICultureDictionaryFactory + { + builder.Services.AddUnique(); + } + + /// + /// Sets the culture dictionary factory. + /// + /// The builder. + /// A function creating a culture dictionary factory. + public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, Func factory) + { + builder.Services.AddUnique(factory); + } + + /// + /// Sets the culture dictionary factory. + /// + /// The builder. + /// A factory. + public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, ICultureDictionaryFactory factory) + { + builder.Services.AddUnique(factory); + } + + /// + /// Sets the published content model factory. + /// + /// The type of the factory. + /// The builder. + public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder) + where T : class, IPublishedModelFactory + { + builder.Services.AddUnique(); + } + + /// + /// Sets the published content model factory. + /// + /// The builder. + /// A function creating a published content model factory. + public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, Func factory) + { + builder.Services.AddUnique(factory); + } + + /// + /// Sets the published content model factory. + /// + /// The builder. + /// A published content model factory. + public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, IPublishedModelFactory factory) + { + builder.Services.AddUnique(factory); + } + + /// + /// Sets the short string helper. + /// + /// The type of the short string helper. + /// The builder. + public static void SetShortStringHelper(this IUmbracoBuilder builder) + where T : class, IShortStringHelper + { + builder.Services.AddUnique(); + } + + /// + /// Sets the short string helper. + /// + /// The builder. + /// A function creating a short string helper. + public static void SetShortStringHelper(this IUmbracoBuilder builder, Func factory) + { + builder.Services.AddUnique(factory); + } + + /// + /// Sets the short string helper. + /// + /// A builder. + /// A short string helper. + public static void SetShortStringHelper(this IUmbracoBuilder builder, IShortStringHelper helper) + { + builder.Services.AddUnique(helper); + } + + /// + /// Sets the underlying media filesystem. + /// + /// A builder. + /// A filesystem factory. + /// + /// Using this helper will ensure that your IFileSystem implementation is wrapped by the ShadowWrapper + /// + public static void SetMediaFileSystem(this IUmbracoBuilder builder, Func filesystemFactory) + => builder.Services.AddUnique(factory => + { + var fileSystems = factory.GetRequiredService(); + return fileSystems.GetFileSystem(filesystemFactory(factory)); + }); + + /// + /// Sets the log viewer. + /// + /// The type of the log viewer. + /// The builder. + public static void SetLogViewer(this IUmbracoBuilder builder) + where T : class, ILogViewer + { + builder.Services.AddUnique(); + } + + /// + /// Sets the log viewer. + /// + /// The builder. + /// A function creating a log viewer. + public static void SetLogViewer(this IUmbracoBuilder builder, Func factory) + { + builder.Services.AddUnique(factory); + } + + /// + /// Sets the log viewer. + /// + /// A builder. + /// A log viewer. + public static void SetLogViewer(this IUmbracoBuilder builder, ILogViewer viewer) + { + builder.Services.AddUnique(viewer); + } + } +} diff --git a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs index 3c291f187b..f3d970d2b0 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs @@ -17,7 +17,7 @@ namespace Umbraco.Infrastructure.HostedServices.ServerRegistration public class InstructionProcessTask : RecurringHostedServiceBase { private readonly IRuntimeState _runtimeState; - private readonly IDatabaseServerMessenger _messenger; + private readonly IServerMessenger _messenger; private readonly ILogger _logger; /// @@ -31,7 +31,7 @@ namespace Umbraco.Infrastructure.HostedServices.ServerRegistration : base(globalSettings.Value.DatabaseServerMessenger.TimeBetweenSyncOperations, TimeSpan.FromMinutes(1)) { _runtimeState = runtimeState; - _messenger = messenger as IDatabaseServerMessenger ?? throw new ArgumentNullException(nameof(messenger)); + _messenger = messenger as IServerMessenger ?? throw new ArgumentNullException(nameof(messenger)); _logger = logger; } diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs index fc26f922eb..4d8046ee8c 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Core.Logging.Serilog.Enrichers; diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs b/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs index aa57383541..4c419a1648 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Serilog; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; +using Umbraco.Infrastructure.DependencyInjection; namespace Umbraco.Core.Logging.Viewer { diff --git a/src/Umbraco.Infrastructure/Migrations/MigrationBuilder.cs b/src/Umbraco.Infrastructure/Migrations/MigrationBuilder.cs index 9fc5b1b277..22961dea5a 100644 --- a/src/Umbraco.Infrastructure/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Infrastructure/Migrations/MigrationBuilder.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core.Composing; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Core.Migrations { diff --git a/src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs b/src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs deleted file mode 100644 index cf53f161a4..0000000000 --- a/src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Umbraco.Core.Migrations.PostMigrations -{ - /// - /// Implements in Umbraco.Core (doing nothing). - /// - public class NoopPublishedSnapshotRebuilder : IPublishedSnapshotRebuilder - { - /// - public void Rebuild() - { } - } -} diff --git a/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs b/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs index dce6658f16..712b90affa 100644 --- a/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs +++ b/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Data; using Umbraco.Core.Events; using Umbraco.Core.Persistence; @@ -13,7 +13,7 @@ namespace Umbraco.Core.Scoping /// Provides scopes. /// public interface IScopeProvider - { + { /// /// Creates an ambient scope. /// diff --git a/src/Umbraco.Infrastructure/Search/ExamineComposer.cs b/src/Umbraco.Infrastructure/Search/ExamineComposer.cs index 683ed48ecd..c961aa6e72 100644 --- a/src/Umbraco.Infrastructure/Search/ExamineComposer.cs +++ b/src/Umbraco.Infrastructure/Search/ExamineComposer.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Core.Models; diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index 856772148f..11e1596529 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -23,15 +23,20 @@ namespace Umbraco.Core.Sync /// /// An that works by storing messages in the database. /// - // - // this messenger writes ALL instructions to the database, - // but only processes instructions coming from remote servers, - // thus ensuring that instructions run only once - // - public class DatabaseServerMessenger : ServerMessengerBase, IDatabaseServerMessenger + public abstract class DatabaseServerMessenger : ServerMessengerBase { + // TODO: This class is never used directly, only BatchedDatabaseServerMessenger is used so + // this could/should be combined with that or made abstract and/or just cleaned up. + + // TODO: This class needs to be split into a service/repo for DB access + + /* + * this messenger writes ALL instructions to the database, + * but only processes instructions coming from remote servers, + * thus ensuring that instructions run only once + */ + private readonly IMainDom _mainDom; - private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory; private readonly ManualResetEvent _syncIdle; private readonly object _locko = new object(); private readonly IProfilingLogger _profilingLogger; @@ -43,22 +48,28 @@ namespace Umbraco.Core.Sync private int _lastId = -1; private DateTime _lastSync; private DateTime _lastPruned; - private bool _initialized; + private readonly Lazy _initialized; private bool _syncing; private bool _released; - public DatabaseServerMessengerCallbacks Callbacks { get; } - - public GlobalSettings GlobalSettings { get; } - + /// + /// Initializes a new instance of the class. + /// public DatabaseServerMessenger( - IMainDom mainDom, IScopeProvider scopeProvider, IUmbracoDatabaseFactory umbracoDatabaseFactory, IProfilingLogger proflog, ILogger logger, IServerRegistrar serverRegistrar, - bool distributedEnabled, DatabaseServerMessengerCallbacks callbacks, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers, IOptions globalSettings) + IMainDom mainDom, + IScopeProvider scopeProvider, + IProfilingLogger proflog, + ILogger logger, + IServerRegistrar serverRegistrar, + bool distributedEnabled, + DatabaseServerMessengerCallbacks callbacks, + IHostingEnvironment hostingEnvironment, + CacheRefresherCollection cacheRefreshers, + IOptions globalSettings) : base(distributedEnabled) { ScopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); _mainDom = mainDom; - _umbracoDatabaseFactory = umbracoDatabaseFactory; _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); _serverRegistrar = serverRegistrar; _hostingEnvironment = hostingEnvironment; @@ -76,24 +87,28 @@ namespace Umbraco.Core.Sync + " [P" + Process.GetCurrentProcess().Id // eg 1234 + "/D" + AppDomain.CurrentDomain.Id // eg 22 + "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique + + _initialized = new Lazy(EnsureInitialized); } + public DatabaseServerMessengerCallbacks Callbacks { get; } + + public GlobalSettings GlobalSettings { get; } + protected ILogger Logger { get; } protected IScopeProvider ScopeProvider { get; } - protected Sql Sql() => _umbracoDatabaseFactory.SqlContext.Sql(); + protected Sql Sql() => ScopeProvider.SqlContext.Sql(); private string DistCacheFilePath => _distCacheFilePath.Value; #region Messenger + // we don't care if there's servers listed or not, + // if distributed call is enabled we will make the call protected override bool RequiresDistributed(ICacheRefresher refresher, MessageType dispatchType) - { - // we don't care if there's servers listed or not, - // if distributed call is enabled we will make the call - return _initialized && DistributedEnabled; - } + => _initialized.Value && DistributedEnabled; protected override void DeliverRemote( ICacheRefresher refresher, @@ -104,7 +119,9 @@ namespace Umbraco.Core.Sync var idsA = ids?.ToArray(); if (GetArrayType(idsA, out var idType) == false) + { throw new ArgumentException("All items must be of the same type, either int or Guid.", nameof(ids)); + } var instructions = RefreshInstruction.GetInstructions(refresher, messageType, idsA, idType, json); @@ -130,17 +147,12 @@ namespace Umbraco.Core.Sync /// /// Boots the messenger. /// - /// - /// Thread safety: this is NOT thread safe. Because it is NOT meant to run multi-threaded. - /// Callers MUST ensure thread-safety. - /// - protected void Boot() + private bool EnsureInitialized() { // weight:10, must release *before* the published snapshot service, because once released // the service will *not* be able to properly handle our notifications anymore const int weight = 10; - var registered = _mainDom.Register( () => { @@ -154,7 +166,7 @@ namespace Umbraco.Core.Sync // properly releasing MainDom - a timeout here means that one refresher // is taking too much time processing, however when it's done we will // not update lastId and stop everything - var idle =_syncIdle.WaitOne(5000); + var idle = _syncIdle.WaitOne(5000); if (idle == false) { Logger.LogWarning("The wait lock timed out, application is shutting down. The current instruction batch will be re-processed."); @@ -163,15 +175,16 @@ namespace Umbraco.Core.Sync weight); if (registered == false) - return; + { + return false; + } ReadLastSynced(); // get _lastId - using (var scope = ScopeProvider.CreateScope()) + + using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { EnsureInstructions(scope.Database); // reset _lastId if instructions are missing - Initialize(scope.Database); // boot - - scope.Complete(); + return Initialize(scope.Database); // boot } } @@ -182,14 +195,19 @@ namespace Umbraco.Core.Sync /// Thread safety: this is NOT thread safe. Because it is NOT meant to run multi-threaded. /// Callers MUST ensure thread-safety. /// - private void Initialize(IUmbracoDatabase database) + private bool Initialize(IUmbracoDatabase database) { lock (_locko) { - if (_released) return; + if (_released) + { + return false; + } var coldboot = false; - if (_lastId < 0) // never synced before + + // never synced before + if (_lastId < 0) { // we haven't synced - in this case we aren't going to sync the whole thing, we will assume this is a new // server and it will need to rebuild it's own caches, eg Lucene or the xml cache file. @@ -201,12 +219,12 @@ namespace Umbraco.Core.Sync } else { - //check for how many instructions there are to process, each row contains a count of the number of instructions contained in each - //row so we will sum these numbers to get the actual count. - var count = database.ExecuteScalar("SELECT SUM(instructionCount) FROM umbracoCacheInstruction WHERE id > @lastId", new {lastId = _lastId}); + // check for how many instructions there are to process, each row contains a count of the number of instructions contained in each + // row so we will sum these numbers to get the actual count. + var count = database.ExecuteScalar("SELECT SUM(instructionCount) FROM umbracoCacheInstruction WHERE id > @lastId", new { lastId = _lastId }); if (count > GlobalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount) { - //too many instructions, proceed to cold boot + // too many instructions, proceed to cold boot Logger.LogWarning( "The instruction count ({InstructionCount}) exceeds the specified MaxProcessingInstructionCount ({MaxProcessingInstructionCount})." + " The server will skip existing instructions, rebuild its caches and indexes entirely, adjust its last synced Id" @@ -224,38 +242,55 @@ namespace Umbraco.Core.Sync // when doing it before, some instructions might run twice - not an issue var maxId = database.ExecuteScalar("SELECT MAX(id) FROM umbracoCacheInstruction"); - //if there is a max currently, or if we've never synced + // if there is a max currently, or if we've never synced if (maxId > 0 || _lastId < 0) + { SaveLastSynced(maxId); + } // execute initializing callbacks if (Callbacks.InitializingCallbacks != null) + { foreach (var callback in Callbacks.InitializingCallbacks) + { callback(); + } + } } - _initialized = true; + return true; } } /// /// Synchronize the server (throttled). /// - public void Sync() + public override void Sync() { + if (!_initialized.Value) + { + return; + } + lock (_locko) { if (_syncing) + { return; + } - //Don't continue if we are released + // Don't continue if we are released if (_released) + { return; + } if ((DateTime.UtcNow - _lastSync) <= GlobalSettings.DatabaseServerMessenger.TimeBetweenSyncOperations) + { return; + } - //Set our flag and the lock to be in it's original state (i.e. it can be awaited) + // Set our flag and the lock to be in it's original state (i.e. it can be awaited) _syncing = true; _syncIdle.Reset(); _lastSync = DateTime.UtcNow; @@ -268,7 +303,7 @@ namespace Umbraco.Core.Sync { ProcessDatabaseInstructions(scope.Database); - //Check for pruning throttling + // Check for pruning throttling if (_released || (DateTime.UtcNow - _lastPruned) <= GlobalSettings.DatabaseServerMessenger.TimeBetweenPruneOperations) { scope.Complete(); @@ -292,7 +327,7 @@ namespace Umbraco.Core.Sync { lock (_locko) { - //We must reset our flag and signal any waiting locks + // We must reset our flag and signal any waiting locks _syncing = false; } @@ -306,9 +341,6 @@ namespace Umbraco.Core.Sync /// /// Thread safety: this is NOT thread safe. Because it is NOT meant to run multi-threaded. /// - /// - /// Returns the number of processed instructions - /// private void ProcessDatabaseInstructions(IUmbracoDatabase database) { // NOTE @@ -324,7 +356,7 @@ namespace Umbraco.Core.Sync .Where(dto => dto.Id > _lastId) .OrderBy(dto => dto.Id); - //only retrieve the top 100 (just in case there's tons) + // only retrieve the top 100 (just in case there's tons) // even though MaxProcessingInstructionCount is by default 1000 we still don't want to process that many // rows in one request thread since each row can contain a ton of instructions (until 7.5.5 in which case // a row can only contain MaxProcessingInstructionCount) @@ -337,15 +369,15 @@ namespace Umbraco.Core.Sync var lastId = 0; - //tracks which ones have already been processed to avoid duplicates + // tracks which ones have already been processed to avoid duplicates var processed = new HashSet(); - //It would have been nice to do this in a Query instead of Fetch using a data reader to save + // It would have been nice to do this in a Query instead of Fetch using a data reader to save // some memory however we cannot do that because inside of this loop the cache refreshers are also // performing some lookups which cannot be done with an active reader open foreach (var dto in database.Fetch(topSql)) { - //If this flag gets set it means we're shutting down! In this case, we need to exit asap and cannot + // If this flag gets set it means we're shutting down! In this case, we need to exit asap and cannot // continue processing anything otherwise we'll hold up the app domain shutdown if (_released) { @@ -377,10 +409,10 @@ namespace Umbraco.Core.Sync var instructionBatch = GetAllInstructions(jsonA); - //process as per-normal + // process as per-normal var success = ProcessDatabaseInstructions(instructionBatch, dto, processed, ref lastId); - //if they couldn't be all processed (i.e. we're shutting down) then exit + // if they couldn't be all processed (i.e. we're shutting down) then exit if (success == false) { Logger.LogInformation("The current batch of instructions was not processed, app is shutting down"); @@ -425,11 +457,11 @@ namespace Umbraco.Core.Sync //} catch (Exception ex) { - Logger.LogError( - ex, - "DISTRIBUTED CACHE IS NOT UPDATED. Failed to execute instructions ({DtoId}: '{DtoInstructions}'). Instruction is being skipped/ignored", - dto.Id, - dto.Instructions); + Logger.LogError( + ex, + "DISTRIBUTED CACHE IS NOT UPDATED. Failed to execute instructions ({DtoId}: '{DtoInstructions}'). Instruction is being skipped/ignored", + dto.Id, + dto.Instructions); //we cannot throw here because this invalid instruction will just keep getting processed over and over and errors // will be thrown over and over. The only thing we can do is ignore and move on. @@ -509,7 +541,8 @@ namespace Umbraco.Core.Sync /// private void ReadLastSynced() { - if (File.Exists(DistCacheFilePath) == false) return; + if (File.Exists(DistCacheFilePath) == false) + return; var content = File.ReadAllText(DistCacheFilePath); if (int.TryParse(content, out var last)) diff --git a/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs b/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs index f2918ffe96..150f3428a7 100644 --- a/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs +++ b/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; @@ -346,6 +346,8 @@ namespace Umbraco.Core.Sync DeliverRemote(refresher, messageType, idsA); } + public abstract void Sync(); + //protected virtual void Deliver(ICacheRefresher refresher, object payload) //{ // if (servers == null) throw new ArgumentNullException("servers"); diff --git a/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs b/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs index af59c27ef2..5db66fdf78 100644 --- a/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs +++ b/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs @@ -1,4 +1,3 @@ -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs index ca597a607b..94237ccf3d 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs @@ -1,7 +1,6 @@ using System.Linq; using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.Configuration; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded.Building; diff --git a/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs index 719d014296..6f6e0d0c0e 100644 --- a/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Models; using Umbraco.Core.Scoping; diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 9b09f7c562..394884a0db 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -10,6 +11,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.DependencyInjection; using Umbraco.Extensions; +using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Tests.Integration.Extensions; using Umbraco.Tests.Integration.Implementations; using Umbraco.Web.Common.DependencyInjection; @@ -42,16 +44,15 @@ namespace Umbraco.Tests.Integration { var testHelper = new TestHelper(); - var hostBuilder = new HostBuilder() + IHostBuilder hostBuilder = new HostBuilder() .ConfigureServices((hostContext, services) => { - var webHostEnvironment = testHelper.GetWebHostEnvironment(); + IWebHostEnvironment webHostEnvironment = testHelper.GetWebHostEnvironment(); services.AddSingleton(testHelper.DbProviderFactoryCreator); services.AddRequiredNetCoreServices(testHelper, webHostEnvironment); // Add it! - - var typeLoader = services.AddTypeLoader( + TypeLoader typeLoader = services.AddTypeLoader( GetType().Assembly, webHostEnvironment, testHelper.GetHostingEnvironment(), @@ -60,9 +61,13 @@ namespace Umbraco.Tests.Integration hostContext.Configuration, testHelper.Profiler); - var builder = new UmbracoBuilder(services, hostContext.Configuration, typeLoader, + var builder = new UmbracoBuilder( + services, + hostContext.Configuration, + typeLoader, testHelper.ConsoleLoggerFactory); - builder.Services.AddUnique(AppCaches.NoCache); + + builder.Services.AddUnique(AppCaches.NoCache); builder.AddConfiguration() .AddUmbracoCore() .Build(); @@ -70,15 +75,14 @@ namespace Umbraco.Tests.Integration services.AddRouting(); // LinkGenerator }); - var host = await hostBuilder.StartAsync(); + IHost host = await hostBuilder.StartAsync(); var app = new ApplicationBuilder(host.Services); app.UseUmbracoCore(); - // assert results - var runtimeState = app.ApplicationServices.GetRequiredService(); - var mainDom = app.ApplicationServices.GetRequiredService(); + IRuntimeState runtimeState = app.ApplicationServices.GetRequiredService(); + IMainDom mainDom = app.ApplicationServices.GetRequiredService(); Assert.IsTrue(mainDom.IsMainDom); Assert.IsNull(runtimeState.BootFailedException); @@ -97,10 +101,7 @@ namespace Umbraco.Tests.Integration IsComposed = true; } - public static void Reset() - { - IsComposed = false; - } + public static void Reset() => IsComposed = false; public static bool IsComposed { get; private set; } } @@ -108,24 +109,16 @@ namespace Umbraco.Tests.Integration public class MyComponent : IComponent { public static bool IsInit { get; private set; } + public static bool IsTerminated { get; private set; } private readonly ILogger _logger; - public MyComponent(ILogger logger) - { - _logger = logger; - } + public MyComponent(ILogger logger) => _logger = logger; - public void Initialize() - { - IsInit = true; - } + public void Initialize() => IsInit = true; - public void Terminate() - { - IsTerminated = true; - } + public void Terminate() => IsTerminated = true; public static void Reset() { @@ -134,6 +127,4 @@ namespace Umbraco.Tests.Integration } } } - - } diff --git a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs index 39d74f8869..1aeaec1bca 100644 --- a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs +++ b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs @@ -1,4 +1,4 @@ -using Moq; +using Moq; using NUnit.Framework; using System; using System.Collections.Generic; @@ -22,10 +22,10 @@ using Umbraco.Core.Sync; using Umbraco.Core.WebAssets; using Umbraco.Examine; using Umbraco.Tests.TestHelpers.Stubs; -using Umbraco.Web.Compose; using Umbraco.Web.PublishedCache.NuCache; using Umbraco.Web.Scheduling; using Umbraco.Web.Search; +using Umbraco.Infrastructure.Cache; namespace Umbraco.Tests.Integration.Testing { @@ -38,11 +38,12 @@ namespace Umbraco.Tests.Integration.Testing /// public class IntegrationTestComposer : ComponentComposer { + // TODO: Kill this and only enable using ext methods what we need (first we need to kill composers) + public override void Compose(IUmbracoBuilder builder) { base.Compose(builder); - builder.Components().Remove(); builder.Services.AddUnique(); builder.Services.AddUnique(factory => Mock.Of()); @@ -65,7 +66,6 @@ namespace Umbraco.Tests.Integration.Testing /// Used to register a replacement for where the file sources are the ones within the netcore project so /// we don't need to copy files /// - /// private ILocalizedTextService GetLocalizedTextService(IServiceProvider factory) { var globalSettings = factory.GetRequiredService>(); @@ -153,6 +153,8 @@ namespace Umbraco.Tests.Integration.Testing { } + + public void Sync() { } } } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs index 11f4095f53..556dedee14 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs @@ -335,6 +335,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Scoping : base(false) { } + public override void Sync() { } + protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) { throw new NotImplementedException(); diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs index 80bf464c31..6b5af1e1e2 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs @@ -2171,6 +2171,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services public LocalServerMessenger() : base(false) { } + public override void Sync() { } + protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) { } diff --git a/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs b/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs index 76f96ead05..d6db3c09f6 100644 --- a/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs +++ b/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.DependencyInjection; using Moq; using NPoco; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Persistence; diff --git a/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs index 0b0f3120d0..40e70d9b5d 100644 --- a/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs @@ -18,6 +18,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.IO; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs index 1023e47dfa..6211711202 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs @@ -127,12 +127,12 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache.DistributedCache internal class TestServerMessenger : IServerMessenger { // Used for tests - public List IntIdsRefreshed = new List(); - public List GuidIdsRefreshed = new List(); - public List IntIdsRemoved = new List(); - public List PayloadsRemoved = new List(); - public List PayloadsRefreshed = new List(); - public int CountOfFullRefreshes = 0; + public List IntIdsRefreshed { get; } = new List(); + public List GuidIdsRefreshed { get; } = new List(); + public List IntIdsRemoved { get; } = new List(); + public List PayloadsRemoved { get; } = new List(); + public List PayloadsRefreshed { get; } = new List(); + public int CountOfFullRefreshes { get; private set; } = 0; public void PerformRefresh(ICacheRefresher refresher, TPayload[] payload) { @@ -156,6 +156,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache.DistributedCache public void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds) => GuidIdsRefreshed.AddRange(guidIds); public void PerformRefreshAll(ICacheRefresher refresher) => CountOfFullRefreshes++; + + public void Sync() { } } internal class TestServerRegistrar : IServerRegistrar diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTaskTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTaskTests.cs index 6ea56792e2..5187f83375 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTaskTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTaskTests.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRe [TestFixture] public class InstructionProcessTaskTests { - private Mock _mockDatabaseServerMessenger; + private Mock _mockDatabaseServerMessenger; [TestCase(RuntimeLevel.Boot)] [TestCase(RuntimeLevel.Install)] @@ -45,7 +45,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRe var mockLogger = new Mock>(); - _mockDatabaseServerMessenger = new Mock(); + _mockDatabaseServerMessenger = new Mock(); var settings = new GlobalSettings(); diff --git a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs index 1800abc8a8..f18aacf18b 100644 --- a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using System; using System.Linq; using System.Threading; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.Models; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index edcd199463..7392537e39 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -6,6 +6,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index e4b3721892..3387f424dd 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -6,9 +6,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 797b1c2be9..af0dab8e14 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 9262c72dfa..912d1e4995 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -25,6 +25,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.Common; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.PublishedContent { diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 9332dc894a..a8d017e3cb 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -26,6 +26,7 @@ using Umbraco.Web.Mvc; using Umbraco.Web.Runtime; using Umbraco.Web.WebApi; using Current = Umbraco.Web.Composing.Current; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs index 50b1597cca..de8ddfd201 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs @@ -1,10 +1,10 @@ using NUnit.Framework; using Microsoft.Extensions.Logging; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Tests.Common; using Umbraco.Tests.Testing; using Umbraco.Web.Routing; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 4c658379cd..649f63f09e 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -2,8 +2,8 @@ using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index aaf3b0de96..a18d12351f 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -5,8 +5,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index af2ffad6e5..46d67eb9bd 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; using Microsoft.Extensions.Logging; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; @@ -13,6 +12,7 @@ using Umbraco.Tests.Common; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Web; using Umbraco.Web.Routing; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index e663996d60..b1851694bc 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.IO; diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 76a947f63a..4f424f4bb0 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 6814210cc4..51c306a864 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -299,6 +300,8 @@ namespace Umbraco.Tests.Scoping : base(false) { } + public override void Sync() { } + protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) { throw new NotImplementedException(); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index cab74e22e4..103d361fc5 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -6,8 +6,8 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index e91c2fdf4d..bea5deb10c 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -38,6 +38,7 @@ using Umbraco.Tests.Common.Builders; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.TestHelpers { diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 8c7b9a00e2..302e1198a8 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -32,6 +32,7 @@ using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Web.WebApi; using Umbraco.Tests.Common; using Umbraco.Core.Security; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.TestHelpers { diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 288a309374..4da5ba7189 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -43,6 +43,7 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; +using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 59b453cc5b..61b5141856 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -2,9 +2,9 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Strings; diff --git a/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs index cdc2bfed00..52e1c3a5a3 100644 --- a/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs @@ -12,7 +12,6 @@ using System.Web.Http; using Moq; using Newtonsoft.Json; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Web.Composing; using Umbraco.Core.Configuration; @@ -37,6 +36,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Persistance.SqlCe; using Umbraco.Web.Routing; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Tests.Web.Controllers { diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs index e9bf69f2c0..d933d00d68 100644 --- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs +++ b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs @@ -1,7 +1,6 @@ using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Hosting; diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 39a3eb3dce..1d11f32916 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -31,9 +31,11 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Runtime; using Umbraco.Extensions; +using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.HostedServices; using Umbraco.Infrastructure.HostedServices.ServerRegistration; using Umbraco.Infrastructure.Runtime; +using Umbraco.Web.Cache; using Umbraco.Web.Common.ApplicationModels; using Umbraco.Web.Common.AspNetCore; using Umbraco.Web.Common.DependencyInjection; @@ -50,6 +52,9 @@ namespace Umbraco.Web.Common.DependencyInjection /// public static class UmbracoBuilderExtensions { + /// + /// Creates an and registers basic Umbraco services + /// public static IUmbracoBuilder AddUmbraco( this IServiceCollection services, IWebHostEnvironment webHostEnvironment, @@ -65,6 +70,8 @@ namespace Umbraco.Web.Common.DependencyInjection throw new ArgumentNullException(nameof(config)); } + // TODO: Should some/all of these registrations be moved directly into UmbracoBuilder? + IHostingEnvironment tempHostingEnvironment = GetTemporaryHostingEnvironment(webHostEnvironment, config); var loggingDir = tempHostingEnvironment.MapPathContentRoot(Core.Constants.SystemDirectories.LogFiles); diff --git a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs index f2babdb07c..6bfa402154 100644 --- a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; @@ -9,7 +9,6 @@ using Umbraco.Web.Common.Install; using Umbraco.Core.Hosting; using System.Linq.Expressions; using Umbraco.Web.Common.Controllers; -using System.Linq; namespace Umbraco.Extensions { diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index f42fc274f0..4161cafd91 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -7,10 +7,10 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Serilog; using Serilog.Extensions.Hosting; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Runtime; diff --git a/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs b/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs index 3c00b0d3bc..eac3e058c2 100644 --- a/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs +++ b/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs @@ -1,4 +1,3 @@ -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs index a23f880e7e..758125b425 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs @@ -1,4 +1,3 @@ -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Web.Common.Middleware; diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs index 1058192034..9a097f688b 100644 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs +++ b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs @@ -1,6 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Smidge.FileProcessors; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Core.Runtime; diff --git a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs index a40b29aea2..2a4b85a0df 100644 --- a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs +++ b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs @@ -1,4 +1,3 @@ -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; using Umbraco.Extensions; diff --git a/src/Umbraco.Web/UmbracoBuilderExtensions.cs b/src/Umbraco.Web/UmbracoBuilderExtensions.cs index bb6fe29c93..d9eea6b5ea 100644 --- a/src/Umbraco.Web/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web/UmbracoBuilderExtensions.cs @@ -1,6 +1,5 @@ using System; using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core; using Umbraco.Core.DependencyInjection; using Umbraco.Web.Routing; From 1f6297ad6bb75b0b2dd74d2808885e234465592c Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 11:46:17 +1100 Subject: [PATCH 10/26] Moves some services 'up' to Core, moves core DI registrations 'up' to UmbracoBuilder, moves Composing ext to DependencyInjection namespaces as UmbracoBuilder ext --- .../ServiceCollectionExtensions.cs | 2 +- .../DependencyInjection/UmbracoBuilder.cs | 111 ++++++++++++ .../EmailNotificationMethod.cs | 1 + src/Umbraco.Core/{ => Mail}/IEmailSender.cs | 4 +- src/Umbraco.Core/{ => Mail}/ISmsSender.cs | 4 +- .../Mail/NotImplementedEmailSender.cs | 12 ++ .../Mail}/NotImplementedSmsSender.cs | 4 +- .../{ => PublishedCache}/ITagQuery.cs | 0 ...uginsManifestWatcherNotificationHandler.cs | 3 +- .../Runtime/EssentialDirectoryCreator.cs | 3 +- .../Runtime/MainDomSemaphoreLock.cs | 6 +- .../{Implement => }/DashboardService.cs | 0 .../Services}/InstallationService.cs | 4 +- src/Umbraco.Core/Services/UpgradeService.cs | 5 +- .../CompositionExtensions/Installer.cs | 36 ---- .../UmbracoBuilder.CoreServices.cs | 166 +++++------------- .../UmbracoBuilder.DistributedCache.cs | 18 ++ .../UmbracoBuilder.FileSystems.cs} | 16 +- .../UmbracoBuilder.Installer.cs | 36 ++++ .../UmbracoBuilder.MappingProfiles.cs} | 12 +- .../UmbracoBuilder.Repositories.cs} | 11 +- .../UmbracoBuilder.Services.cs} | 27 ++- src/Umbraco.Infrastructure/EmailSender.cs | 1 + .../Manifest/ManifestParser.cs | 2 +- .../Media/ImageDimensionExtractor.cs | 11 +- .../Packaging/PackageInstallation.cs | 13 +- .../Services/Implement/NotificationService.cs | 1 + src/Umbraco.Tests.Integration/RuntimeTests.cs | 1 - .../Umbraco.Core/IO/FileSystemsTests.cs | 14 +- .../TestHelpers/TestHelper.cs | 1 + src/Umbraco.Tests/TestHelpers/TestHelper.cs | 1 + src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 8 +- .../Controllers/AuthenticationController.cs | 1 + .../Controllers/UsersController.cs | 1 + .../Trees/PartialViewsTreeController.cs | 5 +- .../UmbracoBuilderExtensions.cs | 54 +----- .../Runtime/AspNetCoreComposer.cs | 4 +- 37 files changed, 301 insertions(+), 298 deletions(-) rename src/Umbraco.Core/{ => Mail}/IEmailSender.cs (78%) rename src/Umbraco.Core/{ => Mail}/ISmsSender.cs (84%) create mode 100644 src/Umbraco.Core/Mail/NotImplementedEmailSender.cs rename src/{Umbraco.Infrastructure => Umbraco.Core/Mail}/NotImplementedSmsSender.cs (90%) rename src/Umbraco.Core/{ => PublishedCache}/ITagQuery.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Runtime/AppPluginsManifestWatcherNotificationHandler.cs (96%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Runtime/EssentialDirectoryCreator.cs (96%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Runtime/MainDomSemaphoreLock.cs (92%) rename src/Umbraco.Core/Services/{Implement => }/DashboardService.cs (100%) rename src/{Umbraco.Infrastructure/Services/Implement/Implement => Umbraco.Core/Services}/InstallationService.cs (87%) delete mode 100644 src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs rename src/Umbraco.Infrastructure/{Composing/CompositionExtensions/FileSystems.cs => DependencyInjection/UmbracoBuilder.FileSystems.cs} (87%) create mode 100644 src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs rename src/Umbraco.Infrastructure/{Composing/CompositionExtensions/CoreMappingProfiles.cs => DependencyInjection/UmbracoBuilder.MappingProfiles.cs} (79%) rename src/Umbraco.Infrastructure/{Composing/CompositionExtensions/Repositories.cs => DependencyInjection/UmbracoBuilder.Repositories.cs} (91%) rename src/Umbraco.Infrastructure/{Composing/CompositionExtensions/Services.cs => DependencyInjection/UmbracoBuilder.Services.cs} (89%) diff --git a/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs index 51ff6b705f..97e70da9be 100644 --- a/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs @@ -51,7 +51,7 @@ namespace Umbraco.Core.DependencyInjection where TService : class => services.Replace(ServiceDescriptor.Singleton(instance)); - public static IServiceCollection AddLazySupport(this IServiceCollection services) + internal static IServiceCollection AddLazySupport(this IServiceCollection services) { services.Replace(ServiceDescriptor.Transient(typeof(Lazy<>), typeof(LazyResolve<>))); return services; diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index 1c05695429..11b035bb73 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -3,12 +3,36 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Grid; +using Umbraco.Core.Dictionary; using Umbraco.Core.Events; +using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Mail; +using Umbraco.Core.Manifest; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Runtime; +using Umbraco.Core.Security; +using Umbraco.Core.Services; +using Umbraco.Core.Sync; +using Umbraco.Web; +using Umbraco.Web.Cache; +using Umbraco.Web.Editors; +using Umbraco.Web.Features; +using Umbraco.Web.Install; +using Umbraco.Web.Models.PublishedContent; +using Umbraco.Web.Routing; +using Umbraco.Web.Services; +using Umbraco.Web.Templates; namespace Umbraco.Core.DependencyInjection { @@ -79,6 +103,93 @@ namespace Umbraco.Core.DependencyInjection // Register as singleton to allow injection everywhere. Services.AddSingleton(p => p.GetService); Services.AddSingleton(); + + Services.AddLazySupport(); + + Services.AddUnique(); + + Services.AddUnique(factory => + { + IHostingEnvironment hostingEnvironment = factory.GetRequiredService(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return new IOHelperLinux(hostingEnvironment); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return new IOHelperOSX(hostingEnvironment); + } + + return new IOHelperWindows(hostingEnvironment); + }); + + Services.AddUnique(factory => factory.GetRequiredService().RuntimeCache); + Services.AddUnique(factory => factory.GetRequiredService().RequestCache); + Services.AddUnique(); + Services.AddUnique(); + + this.AddNotificationHandler(); + + Services.AddSingleton(); + this.AddNotificationHandler(); + + Services.AddUnique(); + + // by default, register a noop factory + Services.AddUnique(); + + Services.AddUnique(); + Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); + + Services.AddUnique(); + + Services.AddUnique(); + + // will be injected in controllers when needed to invoke rest endpoints on Our + Services.AddUnique(); + Services.AddUnique(); + + // Grid config is not a real config file as we know them + Services.AddUnique(); + + Services.AddUnique(); + Services.AddUnique(); + + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); + + // register properties fallback + Services.AddUnique(); + + Services.AddUnique(); + + // register published router + Services.AddUnique(); + + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); + + Services.AddUnique(); + Services.AddUnique(); + + // register distributed cache + Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService())); + + // register the http context and umbraco context accessors + // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when + // we have no http context, eg when booting Umbraco or in background threads, so instead + // let's use an hybrid accessor that can fall back to a ThreadStatic context. + Services.AddUnique(); + + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); } } } diff --git a/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs index d29f3ccb0b..ad92886ecd 100644 --- a/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.HealthCheck; +using Umbraco.Core.Mail; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Infrastructure.HealthCheck; diff --git a/src/Umbraco.Core/IEmailSender.cs b/src/Umbraco.Core/Mail/IEmailSender.cs similarity index 78% rename from src/Umbraco.Core/IEmailSender.cs rename to src/Umbraco.Core/Mail/IEmailSender.cs index aab944e04d..3862d0e717 100644 --- a/src/Umbraco.Core/IEmailSender.cs +++ b/src/Umbraco.Core/Mail/IEmailSender.cs @@ -1,7 +1,7 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Umbraco.Core.Models; -namespace Umbraco.Core +namespace Umbraco.Core.Mail { /// /// Simple abstraction to send an email message diff --git a/src/Umbraco.Core/ISmsSender.cs b/src/Umbraco.Core/Mail/ISmsSender.cs similarity index 84% rename from src/Umbraco.Core/ISmsSender.cs rename to src/Umbraco.Core/Mail/ISmsSender.cs index f296a2ea9b..a2ff054c48 100644 --- a/src/Umbraco.Core/ISmsSender.cs +++ b/src/Umbraco.Core/Mail/ISmsSender.cs @@ -1,6 +1,6 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; -namespace Umbraco.Core +namespace Umbraco.Core.Mail { /// /// Service to send an SMS diff --git a/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs new file mode 100644 index 0000000000..bb8d787cbf --- /dev/null +++ b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs @@ -0,0 +1,12 @@ +using System; +using System.Threading.Tasks; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Mail +{ + internal class NotImplementedEmailSender : IEmailSender + { + public Task SendAsync(EmailMessage message) + => throw new NotImplementedException("To send an Email ensure IEmailSender is implemented with a custom implementation"); + } +} diff --git a/src/Umbraco.Infrastructure/NotImplementedSmsSender.cs b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs similarity index 90% rename from src/Umbraco.Infrastructure/NotImplementedSmsSender.cs rename to src/Umbraco.Core/Mail/NotImplementedSmsSender.cs index ffc33373d0..16c3d04711 100644 --- a/src/Umbraco.Infrastructure/NotImplementedSmsSender.cs +++ b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs @@ -1,7 +1,7 @@ -using System; +using System; using System.Threading.Tasks; -namespace Umbraco.Core +namespace Umbraco.Core.Mail { /// /// An that throws diff --git a/src/Umbraco.Core/ITagQuery.cs b/src/Umbraco.Core/PublishedCache/ITagQuery.cs similarity index 100% rename from src/Umbraco.Core/ITagQuery.cs rename to src/Umbraco.Core/PublishedCache/ITagQuery.cs diff --git a/src/Umbraco.Infrastructure/Runtime/AppPluginsManifestWatcherNotificationHandler.cs b/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs similarity index 96% rename from src/Umbraco.Infrastructure/Runtime/AppPluginsManifestWatcherNotificationHandler.cs rename to src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs index b67f41136a..5f219ac51f 100644 --- a/src/Umbraco.Infrastructure/Runtime/AppPluginsManifestWatcherNotificationHandler.cs +++ b/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs @@ -2,12 +2,11 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; -using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Core.Hosting; using Umbraco.Core.Manifest; -namespace Umbraco.Infrastructure.Runtime +namespace Umbraco.Core.Runtime { /// /// Starts monitoring AppPlugins directory during debug runs, to restart site when a plugin manifest changes. diff --git a/src/Umbraco.Infrastructure/Runtime/EssentialDirectoryCreator.cs b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs similarity index 96% rename from src/Umbraco.Infrastructure/Runtime/EssentialDirectoryCreator.cs rename to src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs index 5543662464..92ad5808b3 100644 --- a/src/Umbraco.Infrastructure/Runtime/EssentialDirectoryCreator.cs +++ b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs @@ -1,13 +1,12 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Options; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Hosting; using Umbraco.Core.IO; -namespace Umbraco.Infrastructure.Runtime +namespace Umbraco.Core.Runtime { public class EssentialDirectoryCreator : INotificationHandler { diff --git a/src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs similarity index 92% rename from src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs rename to src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs index eed13f5060..74dea6742c 100644 --- a/src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs +++ b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -29,7 +29,7 @@ namespace Umbraco.Core.Runtime _logger = logger; } - //WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread + // WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread public Task ListenAsync() => _signal.WaitOneAsync(); public Task AcquireLockAsync(int millisecondsTimeout) @@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime // if more than 1 instance reach that point, one will get the lock // and the other one will timeout, which is accepted - //This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset. + // This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset. try { _lockRelease = _systemLock.Lock(millisecondsTimeout); diff --git a/src/Umbraco.Core/Services/Implement/DashboardService.cs b/src/Umbraco.Core/Services/DashboardService.cs similarity index 100% rename from src/Umbraco.Core/Services/Implement/DashboardService.cs rename to src/Umbraco.Core/Services/DashboardService.cs diff --git a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs b/src/Umbraco.Core/Services/InstallationService.cs similarity index 87% rename from src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs rename to src/Umbraco.Core/Services/InstallationService.cs index a1f74e0862..6e283a61d7 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs +++ b/src/Umbraco.Core/Services/InstallationService.cs @@ -1,8 +1,8 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; -namespace Umbraco.Core.Services.Implement +namespace Umbraco.Core.Services { public class InstallationService : IInstallationService { diff --git a/src/Umbraco.Core/Services/UpgradeService.cs b/src/Umbraco.Core/Services/UpgradeService.cs index ead5270b41..b36eac7789 100644 --- a/src/Umbraco.Core/Services/UpgradeService.cs +++ b/src/Umbraco.Core/Services/UpgradeService.cs @@ -1,10 +1,9 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Semver; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Services; -namespace Umbraco.Core +namespace Umbraco.Core.Services { public class UpgradeService : IUpgradeService { diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs deleted file mode 100644 index dc3b1e2481..0000000000 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Composing; -using Umbraco.Web.Install; -using Umbraco.Web.Install.InstallSteps; -using Umbraco.Web.Install.Models; - -namespace Umbraco.Web.Composing.CompositionExtensions -{ - public static class Installer - { - public static IUmbracoBuilder ComposeInstaller(this IUmbracoBuilder builder) - { - // register the installer steps - - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - - // TODO: Add these back once we have a compatible Starter kit - // composition.Services.AddScoped(); - // composition.Services.AddScoped(); - // composition.Services.AddScoped(); - - builder.Services.AddScoped(); - - builder.Services.AddTransient(); - builder.Services.AddUnique(); - - return builder; - } - } -} diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index e150f0cdba..b4fd03350a 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -1,18 +1,16 @@ -using System; +using System.Runtime.InteropServices; using Examine; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing.CompositionExtensions; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Grid; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Dashboards; using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Dictionary; -using Umbraco.Core.Events; +using Umbraco.Core.Hosting; using Umbraco.Core.Install; +using Umbraco.Core.Mail; using Umbraco.Core.Manifest; using Umbraco.Core.Media; using Umbraco.Core.Migrations; @@ -20,16 +18,14 @@ using Umbraco.Core.Migrations.Install; using Umbraco.Core.Migrations.PostMigrations; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Packaging; +using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.PropertyEditors.ValueConverters; +using Umbraco.Core.Runtime; using Umbraco.Core.Scoping; -using Umbraco.Core.Security; using Umbraco.Core.Serialization; -using Umbraco.Core.Services; -using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; -using Umbraco.Core.Sync; using Umbraco.Core.Templates; using Umbraco.Examine; using Umbraco.Infrastructure.Examine; @@ -37,10 +33,8 @@ using Umbraco.Infrastructure.Media; using Umbraco.Infrastructure.Runtime; using Umbraco.Web; using Umbraco.Web.Actions; -using Umbraco.Web.Cache; using Umbraco.Web.ContentApps; using Umbraco.Web.Editors; -using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.HealthCheck.NotificationMethods; using Umbraco.Web.Install; @@ -54,8 +48,6 @@ using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Search; using Umbraco.Web.Sections; -using Umbraco.Web.Services; -using Umbraco.Web.Templates; using Umbraco.Web.Trees; using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; @@ -66,7 +58,7 @@ namespace Umbraco.Infrastructure.DependencyInjection /* * TODO: Many of these things are not "Core" services and are probably not required to run - * + * * This should be split up: * - Distributed Cache * - BackOffice @@ -83,19 +75,25 @@ namespace Umbraco.Infrastructure.DependencyInjection * - Front End */ + /// + /// Adds all core Umbraco services required to run which may be replaced later in the pipeline + /// public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder) { - builder.AddNotificationHandler(); + builder.AddMainDom(); - builder.Services.AddSingleton(); - builder.AddNotificationHandler(); + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => factory.GetRequiredService().CreateDatabase()); + builder.Services.AddUnique(factory => factory.GetRequiredService().SqlContext); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // composers builder - .ComposeRepositories() - .ComposeServices() - .ComposeCoreMappingProfiles() - .ComposeFileSystems(); + .AddRepositories() + .AddServices() + .AddCoreMappingProfiles() + .AddFileSystems(); // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it @@ -110,7 +108,6 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); - builder.Services.AddUnique(); // register database builder // *not* a singleton, don't want to keep it around @@ -146,41 +143,6 @@ namespace Umbraco.Infrastructure.DependencyInjection // references to media item/s builder.DataValueReferenceFactories(); - // register a server registrar, by default it's the db registrar - builder.Services.AddUnique(f => - { - var globalSettings = f.GetRequiredService>().Value; - - // TODO: we still register the full IServerMessenger because - // even on 1 single server we can have 2 concurrent app domains - var singleServer = globalSettings.DisableElectionForSingleServer; - return singleServer - ? (IServerRegistrar)new SingleServerRegistrar(f.GetRequiredService()) - : new DatabaseServerRegistrar( - new Lazy(f.GetRequiredService)); - }); - - // by default we'll use the database server messenger with default options (no callbacks), - // this will be overridden by the db thing in the corresponding components in the web - // project - builder.Services.AddUnique(factory - => new DatabaseServerMessenger( - factory.GetRequiredService(), - factory.GetRequiredService(), - factory.GetRequiredService(), - factory.GetRequiredService(), - factory.GetRequiredService>(), - factory.GetRequiredService(), - true, - new DatabaseServerMessengerCallbacks(), - factory.GetRequiredService(), - factory.GetRequiredService(), - factory.GetRequiredService>() - )); - - builder.CacheRefreshers() - .Add(() => builder.TypeLoader.GetCacheRefreshers()); - builder.PackageActions() .Add(() => builder.TypeLoader.GetPackageActions()); @@ -197,43 +159,20 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(factory => new MigrationBuilder(factory)); - // by default, register a noop factory - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.SetCultureDictionaryFactory(); - builder.Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); - builder.Services.AddUnique(); - // register the published snapshot accessor - the "current" published snapshot is in the umbraco context builder.Services.AddUnique(); builder.Services.AddUnique(); - builder.Services.AddUnique(); - // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards builder.Dashboards() .Add(builder.TypeLoader.GetTypes()); - // will be injected in controllers when needed to invoke rest endpoints on Our - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - // Grid config is not a real config file as we know them - builder.Services.AddUnique(); - // Config manipulator builder.Services.AddUnique(); - // register the umbraco context factory - // composition.Services.AddUnique(); - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); @@ -254,15 +193,8 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.MediaUrlProviders() .Append(); - builder.Services.AddUnique(); - - // register properties fallback - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Actions() .Add(() => builder.TypeLoader.GetTypes()); @@ -311,9 +243,6 @@ namespace Umbraco.Infrastructure.DependencyInjection .Append() .Append(); - // register published router - builder.Services.AddUnique(); - // register *all* checks, except those marked [HideFromTypeFinder] of course builder.Services.AddUnique(); builder.HealthChecks() @@ -325,12 +254,14 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(); builder.ContentFinders() + // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() .Append() .Append() - //.Append() // disabled, this is an odd finder + + // .Append() // disabled, this is an odd finder .Append() .Append(); @@ -339,26 +270,13 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.SearchableTrees() .Add(() => builder.TypeLoader.GetTypes()); - // replace some services - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); + // replace builder.Services.AddUnique(); - builder.Services.AddUnique(); builder.Services.AddUnique(); - // register distributed cache - builder.Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService())); - builder.Services.AddScoped(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); builder.Services.AddScoped(factory => { @@ -366,14 +284,6 @@ namespace Umbraco.Infrastructure.DependencyInjection return new PublishedContentQuery(umbCtx.UmbracoContext.PublishedSnapshot, factory.GetRequiredService(), factory.GetRequiredService()); }); - builder.Services.AddUnique(); - - // register the http context and umbraco context accessors - // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when - // we have no http context, eg when booting Umbraco or in background threads, so instead - // let's use an hybrid accessor that can fall back to a ThreadStatic context. - builder.Services.AddUnique(); - // register accessors for cultures builder.Services.AddUnique(); @@ -389,17 +299,33 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(); - builder.Services.AddUnique(factory => new LegacyPasswordSecurity()); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - builder.Services.AddUnique(); builder.Services.AddUnique(); - builder.Services.AddUnique(); return builder; } + + private static IUmbracoBuilder AddMainDom(this IUmbracoBuilder builder) + { + builder.Services.AddUnique(); + + builder.Services.AddUnique(factory => + { + var globalSettings = factory.GetRequiredService>().Value; + var connectionStrings = factory.GetRequiredService>().Value; + var hostingEnvironment = factory.GetRequiredService(); + + var dbCreator = factory.GetRequiredService(); + var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + var loggerFactory = factory.GetRequiredService(); + + return globalSettings.MainDomLock.Equals("SqlMainDomLock") || isWindows == false + ? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger(), loggerFactory, globalSettings, connectionStrings, dbCreator, hostingEnvironment) + : new MainDomSemaphoreLock(loggerFactory.CreateLogger(), hostingEnvironment); + }); + + return builder; + } } } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs index 4970df2b87..23e927df97 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs @@ -1,8 +1,11 @@ using System; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; +using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Sync; using Umbraco.Infrastructure.Cache; @@ -29,6 +32,21 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.SetServerMessenger(); builder.AddNotificationHandler(); + // TODO: We don't need server registrar anymore + // register a server registrar, by default it's the db registrar + builder.Services.AddUnique(f => + { + var globalSettings = f.GetRequiredService>().Value; + + // TODO: we still register the full IServerMessenger because + // even on 1 single server we can have 2 concurrent app domains + var singleServer = globalSettings.DisableElectionForSingleServer; + return singleServer + ? (IServerRegistrar)new SingleServerRegistrar(f.GetRequiredService()) + : new DatabaseServerRegistrar( + new Lazy(f.GetRequiredService)); + }); + builder.CacheRefreshers() .Add(() => builder.TypeLoader.GetCacheRefreshers()); diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs similarity index 87% rename from src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs rename to src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs index 4c8caa89b8..5c61fd2c60 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs @@ -1,17 +1,15 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Umbraco.Core.DependencyInjection; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; -using Umbraco.Core.Strings; -using Umbraco.Infrastructure.DependencyInjection; -namespace Umbraco.Core.Composing.CompositionExtensions +namespace Umbraco.Infrastructure.DependencyInjection { - internal static class FileSystems + public static partial class UmbracoBuilderExtensions { /* * HOW TO REPLACE THE MEDIA UNDERLYING FILESYSTEM @@ -35,16 +33,16 @@ namespace Umbraco.Core.Composing.CompositionExtensions * */ - public static IUmbracoBuilder ComposeFileSystems(this IUmbracoBuilder builder) + internal static IUmbracoBuilder AddFileSystems(this IUmbracoBuilder builder) { // register FileSystems, which manages all filesystems // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the // interface is really for end-users to get access to filesystems. - builder.Services.AddUnique(factory => factory.CreateInstance(factory)); + builder.Services.AddUnique(factory => factory.CreateInstance(factory)); // register IFileSystems, which gives access too all filesystems - builder.Services.AddUnique(factory => factory.GetRequiredService()); + builder.Services.AddUnique(factory => factory.GetRequiredService()); // register the scheme for media paths builder.Services.AddUnique(); diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs new file mode 100644 index 0000000000..bcdead6fd0 --- /dev/null +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.DependencyInjection; +using Umbraco.Web.Install; +using Umbraco.Web.Install.InstallSteps; +using Umbraco.Web.Install.Models; + +namespace Umbraco.Infrastructure.DependencyInjection +{ + public static partial class UmbracoBuilderExtensions + { + /// + /// Adds the services for the Umbraco installer + /// + public static IUmbracoBuilder AddInstaller(this IUmbracoBuilder builder) + { + // register the installer steps + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + + // TODO: Add these back once we have a compatible Starter kit + // composition.Services.AddScoped(); + // composition.Services.AddScoped(); + // composition.Services.AddScoped(); + builder.Services.AddScoped(); + + builder.Services.AddTransient(); + builder.Services.AddUnique(); + + return builder; + } + } +} diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs similarity index 79% rename from src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs rename to src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs index c700938534..4974a043b1 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs @@ -4,17 +4,14 @@ using Umbraco.Core.Mapping; using Umbraco.Core.Security; using Umbraco.Web.Models.Mapping; -namespace Umbraco.Core.Composing.CompositionExtensions - +namespace Umbraco.Infrastructure.DependencyInjection { - public static class CoreMappingProfiles + public static partial class UmbracoBuilderExtensions { /// /// Registers the core Umbraco mapper definitions /// - /// - /// - public static IUmbracoBuilder ComposeCoreMappingProfiles(this IUmbracoBuilder builder) + public static IUmbracoBuilder AddCoreMappingProfiles(this IUmbracoBuilder builder) { builder.Services.AddUnique(); @@ -34,8 +31,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions .Add() .Add() .Add() - .Add() - ; + .Add(); builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs similarity index 91% rename from src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs rename to src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs index 05b7371d15..1e32eddb5c 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs @@ -1,15 +1,18 @@ -using Umbraco.Core.DependencyInjection; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; -namespace Umbraco.Core.Composing.CompositionExtensions +namespace Umbraco.Infrastructure.DependencyInjection { /// /// Composes repositories. /// - internal static class Repositories + public static partial class UmbracoBuilderExtensions { - public static IUmbracoBuilder ComposeRepositories(this IUmbracoBuilder builder) + /// + /// Adds the Umbraco repositories + /// + internal static IUmbracoBuilder AddRepositories(this IUmbracoBuilder builder) { // repositories builder.Services.AddUnique(); diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs similarity index 89% rename from src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs rename to src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs index b027a99c67..918bdcb941 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs @@ -1,9 +1,10 @@ -using System; +using System; using System.IO; using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; @@ -15,16 +16,15 @@ using Umbraco.Core.Routing; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; -namespace Umbraco.Core.Composing.CompositionExtensions +namespace Umbraco.Infrastructure.DependencyInjection { - internal static class Services + public static partial class UmbracoBuilderExtensions { - public static IUmbracoBuilder ComposeServices(this IUmbracoBuilder builder) + /// + /// Adds Umbraco services + /// + internal static IUmbracoBuilder AddServices(this IUmbracoBuilder builder) { - // register a transient messages factory, which will be replaced by the web - // boot manager when running in a web context - builder.Services.AddUnique(); - // register the service context builder.Services.AddUnique(); @@ -59,7 +59,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); - builder.Services.AddTransient(SourcesFactory); + builder.Services.AddTransient(SourcesFactory); builder.Services.AddUnique(factory => new LocalizedTextService( factory.GetRequiredService>(), factory.GetRequiredService>())); @@ -82,9 +82,6 @@ namespace Umbraco.Core.Composing.CompositionExtensions /// /// Creates an instance of PackagesRepository for either the ICreatedPackagesRepository or the IInstalledPackagesRepository /// - /// - /// - /// private static PackagesRepository CreatePackageRepository(IServiceProvider factory, string packageRepoFileName) => new PackagesRepository( factory.GetRequiredService(), @@ -106,9 +103,9 @@ namespace Umbraco.Core.Composing.CompositionExtensions { var hostingEnvironment = container.GetRequiredService(); var globalSettings = container.GetRequiredService>().Value; - var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath , "config","lang"))); + var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath, "config", "lang"))); var appPlugins = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins)); - var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config ,"lang"))); + var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config, "lang"))); var pluginLangFolders = appPlugins.Exists == false ? Enumerable.Empty() @@ -117,7 +114,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); - //user defined langs that overwrite the default, these should not be used by plugin creators + // user defined langs that overwrite the default, these should not be used by plugin creators var userLangFolders = configLangFolder.Exists == false ? Enumerable.Empty() : configLangFolder diff --git a/src/Umbraco.Infrastructure/EmailSender.cs b/src/Umbraco.Infrastructure/EmailSender.cs index 539adcb971..4c377f1ff1 100644 --- a/src/Umbraco.Infrastructure/EmailSender.cs +++ b/src/Umbraco.Infrastructure/EmailSender.cs @@ -7,6 +7,7 @@ using MimeKit; using MimeKit.Text; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; +using Umbraco.Core.Mail; using Umbraco.Core.Models; using SmtpClient = MailKit.Net.Smtp.SmtpClient; diff --git a/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs b/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs index 15ddcebb7e..d134010104 100644 --- a/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs +++ b/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs b/src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs index 538c559cf6..ad5155e6d2 100644 --- a/src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs +++ b/src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Drawing; using System.IO; using Umbraco.Core; @@ -18,7 +18,7 @@ namespace Umbraco.Web.Media /// use potentially large amounts of memory. public ImageSize GetDimensions(Stream stream) { - //Try to load with exif + // Try to load with exif try { if (ExifImageDimensionExtractor.TryGetDimensions(stream, out var width, out var height)) @@ -28,12 +28,13 @@ namespace Umbraco.Web.Media } catch { - //We will just swallow, just means we can't read exif data, we don't want to log an error either + // We will just swallow, just means we can't read exif data, we don't want to log an error either } - //we have no choice but to try to read in via GDI + // we have no choice but to try to read in via GDI try { + // TODO: We should be using ImageSharp for this using (var image = Image.FromStream(stream)) { var fileWidth = image.Width; @@ -43,7 +44,7 @@ namespace Umbraco.Web.Media } catch (Exception) { - //We will just swallow, just means we can't read via GDI, we don't want to log an error either + // We will just swallow, just means we can't read via GDI, we don't want to log an error either } return new ImageSize(Constants.Conventions.Media.DefaultSize, Constants.Conventions.Media.DefaultSize); diff --git a/src/Umbraco.Infrastructure/Packaging/PackageInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageInstallation.cs index 4970fc302e..df8a58fc8d 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageInstallation.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -17,16 +17,11 @@ namespace Umbraco.Core.Packaging private readonly IPackageActionRunner _packageActionRunner; private readonly DirectoryInfo _applicationRootFolder; + /// - /// Constructor + /// Initializes a new instance of the class. /// - /// - /// - /// - /// - /// - public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner, - IHostingEnvironment hostingEnvironment) + public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner, IHostingEnvironment hostingEnvironment) { _packageExtraction = new PackageExtraction(); _packageFileInstallation = packageFileInstallation ?? throw new ArgumentNullException(nameof(packageFileInstallation)); diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index 3e99ca9b4b..653a878ab9 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -14,6 +14,7 @@ using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Scoping; +using Umbraco.Core.Mail; namespace Umbraco.Core.Services.Implement { diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index fc2844db24..394884a0db 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -70,7 +70,6 @@ namespace Umbraco.Tests.Integration builder.Services.AddUnique(AppCaches.NoCache); builder.AddConfiguration() .AddUmbracoCore() - .AddNuCache() .Build(); services.AddRouting(); // LinkGenerator diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/IO/FileSystemsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/IO/FileSystemsTests.cs index 4474b95584..314a50ce75 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Core/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Core/IO/FileSystemsTests.cs @@ -1,27 +1,17 @@ -using System; +using System; using System.IO; using System.Text; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing.CompositionExtensions; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; -using Umbraco.Core.Services; using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -using FileSystems = Umbraco.Core.IO.FileSystems; namespace Umbraco.Tests.IO { [TestFixture] - [UmbracoTest()] + [UmbracoTest] public class FileSystemsTests : UmbracoIntegrationTest { [Test] diff --git a/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs index 40e70d9b5d..b23ccc9080 100644 --- a/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests.UnitTests/TestHelpers/TestHelper.cs @@ -23,6 +23,7 @@ using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Mail; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index bea5deb10c..8c89905c97 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -39,6 +39,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Umbraco.Core.Configuration.Models; using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Mail; namespace Umbraco.Tests.TestHelpers { diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 4da5ba7189..433ef1de02 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -18,7 +18,6 @@ using Serilog; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.CompositionExtensions; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.DependencyInjection; @@ -28,6 +27,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; +using Umbraco.Core.Mail; using Umbraco.Core.Manifest; using Umbraco.Core.Mapping; using Umbraco.Core.Media; @@ -383,7 +383,7 @@ namespace Umbraco.Tests.Testing if (configure == false) return; Builder - .ComposeCoreMappingProfiles(); + .AddCoreMappingProfiles(); } protected virtual TypeLoader GetTypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, IHostingEnvironment hostingEnvironment, ILogger logger, IProfilingLogger profilingLogger, UmbracoTestOptions.TypeLoader option) @@ -452,7 +452,7 @@ namespace Umbraco.Tests.Testing if (withApplication == false) return; // default Datalayer/Repositories/SQL/Database/etc... - Builder.ComposeRepositories(); + Builder.AddRepositories(); Builder.Services.AddUnique(); @@ -497,7 +497,7 @@ namespace Umbraco.Tests.Testing => TestObjects.GetScopeProvider(_loggerFactory, factory.GetService(), factory.GetService())); Builder.Services.AddUnique(factory => (IScopeAccessor)factory.GetRequiredService()); - Builder.ComposeServices(); + Builder.AddServices(); // composition root is doing weird things, fix Builder.Services.AddUnique(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index 36e5c2b6fe..502ffbcba2 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Mail; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index 9d7999b9f7..fca8c49004 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -18,6 +18,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; +using Umbraco.Core.Mail; using Umbraco.Core.Mapping; using Umbraco.Core.Media; using Umbraco.Core.Models; diff --git a/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs index b648bd797f..a5707968ee 100644 --- a/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs @@ -1,11 +1,8 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Umbraco.Core.IO; using Umbraco.Core.Services; -using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Authorization; -using Umbraco.Web.Composing; -using Umbraco.Web.Mvc; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 1d11f32916..f3109ac2da 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -105,12 +105,16 @@ namespace Umbraco.Web.Common.DependencyInjection throw new ArgumentNullException(nameof(builder)); } - builder.Services.AddLazySupport(); + // Add ASP.NET specific services + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddHostedService(factory => factory.GetRequiredService()); // Add supported databases builder.AddUmbracoSqlCeSupport(); builder.AddUmbracoSqlServerSupport(); + // Must be added here because DbProviderFactories is netstandard 2.1 so cannot exist in Infra for now builder.Services.AddSingleton(factory => new DbProviderFactoryCreator( DbProviderFactories.GetFactory, factory.GetServices(), @@ -118,54 +122,6 @@ namespace Umbraco.Web.Common.DependencyInjection factory.GetServices() )); - builder.Services.AddUnique(factory => - { - var globalSettings = factory.GetRequiredService>().Value; - var connectionStrings = factory.GetRequiredService>().Value; - var hostingEnvironment = factory.GetRequiredService(); - - var dbCreator = factory.GetRequiredService(); - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var loggerFactory = factory.GetRequiredService(); - - return globalSettings.MainDomLock.Equals("SqlMainDomLock") || isWindows == false - ? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger(), loggerFactory, globalSettings, connectionStrings, dbCreator, hostingEnvironment) - : new MainDomSemaphoreLock(loggerFactory.CreateLogger(), hostingEnvironment); - }); - - builder.Services.AddUnique(factory => - { - var hostingEnvironment = factory.GetRequiredService(); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return new IOHelperLinux(hostingEnvironment); - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return new IOHelperOSX(hostingEnvironment); - } - - return new IOHelperWindows(hostingEnvironment); - } - - ); - builder.Services.AddUnique(factory => factory.GetRequiredService().RuntimeCache); - builder.Services.AddUnique(factory => factory.GetRequiredService().RequestCache); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(factory => factory.GetRequiredService().CreateDatabase()); - builder.Services.AddUnique(factory => factory.GetRequiredService().SqlContext); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - builder.Services.AddHostedService(factory => factory.GetRequiredService()); - builder.AddCoreInitialServices(); builder.AddComposers(); diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index 49dcf5a6db..42352d19f2 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -20,11 +20,11 @@ using Umbraco.Web.Common.Profiler; using Umbraco.Web.Common.Routing; using Umbraco.Web.Common.Security; using Umbraco.Web.Common.Templates; -using Umbraco.Web.Composing.CompositionExtensions; using Umbraco.Web.Macros; using Umbraco.Web.Security; using Umbraco.Web.Templates; using Umbraco.Web.Common.ModelBinders; +using Umbraco.Infrastructure.DependencyInjection; namespace Umbraco.Web.Common.Runtime { @@ -75,7 +75,7 @@ namespace Umbraco.Web.Common.Runtime builder.Services.AddUnique(); //register the install components - builder.ComposeInstaller(); + builder.AddInstaller(); var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); builder.WithCollectionBuilder() From e785ac28a342cdc48b7c01c84385385037be6a58 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 14:29:26 +1100 Subject: [PATCH 11/26] Moves more services and registrations "up", removes AspNetCoreComposer logic and moves to AddWebComponents --- src/Umbraco.Core/Cache/DistributedCache.cs | 10 +- .../UmbracoBuilder.Collections.cs | 186 ++++++++++++++++-- .../UmbracoBuilder.Composers.cs | 26 +++ .../UmbracoBuilder.Configuration.cs | 59 ++++++ .../UmbracoBuilder.Events.cs | 4 +- .../DependencyInjection/UmbracoBuilder.cs | 5 + .../Media/IImageDimensionExtractor.cs | 0 .../Media/ImageSize.cs | 0 .../Media/UploadAutoFillProperties.cs | 0 .../PropertyEditorCollection.cs | 4 +- .../TextStringValueConverter.cs | 0 ...rter.cs => SimpleTinyMceValueConverter.cs} | 4 +- .../TextStringValueConverter.cs | 45 ----- src/Umbraco.Core/Trees/ISearchableTree.cs | 4 +- .../Trees}/SearchableApplicationTree.cs | 4 +- .../Trees}/SearchableTreeCollection.cs | 4 +- .../Trees}/SearchableTreeCollectionBuilder.cs | 5 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../BatchedDatabaseServerMessenger.cs | 5 +- ...abaseServerMessengerNotificationHandler.cs | 4 +- .../UmbracoBuilder.Collections.cs | 73 +------ .../UmbracoBuilder.CoreServices.cs | 122 +----------- .../UmbracoBuilder.DistributedCache.cs | 7 +- .../UmbracoBuilder.Installer.cs | 2 +- .../RteMacroRenderingValueConverter.cs | 4 +- .../Search/UmbracoTreeSearcher.cs | 2 +- .../UmbracoTestServerTestBase.cs | 1 - .../Scoping/ScopedRepositoryTests.cs | 17 +- .../Services/ContentEventsTests.cs | 5 - .../ContentTypeServiceVariantsTests.cs | 2 - .../Services/TrackRelationsTests.cs | 2 - .../PublishedContentTestBase.cs | 2 +- .../Controllers/EntityController.cs | 1 + .../UmbracoBuilderExtensions.cs | 4 +- .../Trees/ContentTreeController.cs | 1 + .../Trees/ContentTypeTreeController.cs | 1 + .../Trees/DataTypeTreeController.cs | 1 + .../Trees/MediaTreeController.cs | 1 + .../Trees/MediaTypeTreeController.cs | 1 + .../Trees/MemberTreeController.cs | 1 + .../Trees/MemberTypeTreeController.cs | 1 + .../Trees/TemplatesTreeController.cs | 1 + .../Trees/TreeControllerBase.cs | 1 + .../UmbracoBuilderExtensions.cs | 130 +++++++----- .../Runtime/AspNetCoreBootFailedComposer.cs | 17 -- .../Runtime/AspNetCoreComposer.cs | 58 ------ .../UmbracoBuilderExtensions.cs | 3 +- 47 files changed, 402 insertions(+), 429 deletions(-) create mode 100644 src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs create mode 100644 src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/IImageDimensionExtractor.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/ImageSize.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/UploadAutoFillProperties.cs (100%) rename src/{Umbraco.Infrastructure/PropertyEditors/ValueConverters => Umbraco.Core/PropertyEditors}/TextStringValueConverter.cs (100%) rename src/Umbraco.Core/PropertyEditors/ValueConverters/{TinyMceValueConverter.cs => SimpleTinyMceValueConverter.cs} (95%) delete mode 100644 src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs rename src/{Umbraco.Infrastructure/Search => Umbraco.Core/Trees}/SearchableApplicationTree.cs (92%) rename src/{Umbraco.Infrastructure/Search => Umbraco.Core/Trees}/SearchableTreeCollection.cs (97%) rename src/{Umbraco.Infrastructure/Search => Umbraco.Core/Trees}/SearchableTreeCollectionBuilder.cs (81%) delete mode 100644 src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs diff --git a/src/Umbraco.Core/Cache/DistributedCache.cs b/src/Umbraco.Core/Cache/DistributedCache.cs index 698e97c610..569ff47724 100644 --- a/src/Umbraco.Core/Cache/DistributedCache.cs +++ b/src/Umbraco.Core/Cache/DistributedCache.cs @@ -164,9 +164,15 @@ namespace Umbraco.Web.Cache #endregion // helper method to get an ICacheRefresher by its unique identifier - private ICacheRefresher GetRefresherById(Guid refresherGuid) + private ICacheRefresher GetRefresherById(Guid refresherGuid) { - return _cacheRefreshers[refresherGuid]; + ICacheRefresher refresher = _cacheRefreshers[refresherGuid]; + if (refresher == null) + { + throw new InvalidOperationException($"No cache refresher found with id {refresherGuid}"); + } + + return refresher; } } } diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs index 35d8ba1025..f6dc6fd6ff 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs @@ -1,11 +1,21 @@ +using System.Security.Cryptography; +using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; using Umbraco.Core.HealthCheck; using Umbraco.Core.Manifest; +using Umbraco.Core.PackageActions; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Strings; +using Umbraco.Core.Trees; using Umbraco.Web.Actions; using Umbraco.Web.ContentApps; using Umbraco.Web.Dashboards; using Umbraco.Web.Editors; +using Umbraco.Web.HealthCheck; +using Umbraco.Web.HealthCheck.NotificationMethods; +using Umbraco.Web.Media.EmbedProviders; using Umbraco.Web.Routing; using Umbraco.Web.Sections; using Umbraco.Web.Tour; @@ -17,6 +27,97 @@ namespace Umbraco.Core.DependencyInjection /// public static partial class UmbracoBuilderExtensions { + /// + /// Adds all core collection builders + /// + internal static void AddAllCoreCollectionBuilders(this IUmbracoBuilder builder) + { + builder.CacheRefreshers().Add(() => builder.TypeLoader.GetCacheRefreshers()); + builder.DataEditors().Add(() => builder.TypeLoader.GetDataEditors()); + builder.Actions().Add(() => builder.TypeLoader.GetTypes()); + // register known content apps + builder.ContentApps() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); + // all built-in finders in the correct order, + // devs can then modify this list on application startup + builder.ContentFinders() + .Append() + .Append() + .Append() + /*.Append() // disabled, this is an odd finder */ + .Append() + .Append(); + builder.EditorValidators().Add(() => builder.TypeLoader.GetTypes()); + builder.HealthChecks().Add(() => builder.TypeLoader.GetTypes()); + builder.HealthCheckNotificationMethods().Add(() => builder.TypeLoader.GetTypes()); + builder.TourFilters(); + builder.UrlProviders() + .Append() + .Append(); + builder.MediaUrlProviders() + .Append(); + // register back office sections in the order we want them rendered + builder.Sections() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); + builder.Components(); + // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards + builder.Dashboards() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add(builder.TypeLoader.GetTypes()); + builder.PackageActions().Add(() => builder.TypeLoader.GetPackageActions()); + builder.DataValueReferenceFactories(); + builder.PropertyValueConverters().Append(builder.TypeLoader.GetTypes()); + builder.UrlSegmentProviders().Append(); + builder.ManifestValueValidators() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add(); + builder.ManifestFilters(); + builder.MediaUrlGenerators(); + // register OEmbed providers - no type scanning - all explicit opt-in of adding types, IEmbedProvider is not IDiscoverable + builder.OEmbedProviders() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); + builder.SearchableTrees().Add(() => builder.TypeLoader.GetTypes()); + } + /// /// Gets the actions collection builder. /// @@ -52,6 +153,9 @@ namespace Umbraco.Core.DependencyInjection public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + public static HealthCheckNotificationMethodCollectionBuilder HealthCheckNotificationMethods(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + /// /// Gets the TourFilters collection builder. /// @@ -90,18 +194,63 @@ namespace Umbraco.Core.DependencyInjection /// /// The builder. public static DashboardCollectionBuilder Dashboards(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add(); + => builder.WithCollectionBuilder(); + + /// + /// Gets the cache refreshers collection builder. + /// + /// The builder. + public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the package actions collection builder. + /// + /// The builder. + internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the data editor collection builder. + /// + /// The builder. + public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the data value reference factory collection builder. + /// + /// The builder. + public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the property value converters collection builder. + /// + /// The builder. + public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the url segment providers collection builder. + /// + /// The builder. + public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the validators collection builder. + /// + /// The builder. + internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the manifest filter collection builder. + /// + /// The builder. + public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the content finders collection builder. @@ -109,5 +258,18 @@ namespace Umbraco.Core.DependencyInjection /// The builder. public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + + /// + /// Gets the backoffice OEmbed Providers collection builder. + /// + /// The builder. + public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + + /// + /// Gets the back office searchable tree collection builder + /// + public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); } } diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs new file mode 100644 index 0000000000..3479bd74d6 --- /dev/null +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Composing; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Umbraco.Core.DependencyInjection +{ + /// + /// Extension methods for + /// + public static partial class UmbracoBuilderExtensions + { + /// + /// Adds Umbraco composers for plugins + /// + public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder) + { + IEnumerable composerTypes = builder.TypeLoader.GetTypes(); + IEnumerable enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); + new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger()).Compose(); + + return builder; + } + } +} diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs new file mode 100644 index 0000000000..1733536908 --- /dev/null +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration.Models.Validation; + +namespace Umbraco.Core.DependencyInjection +{ + /// + /// Extension methods for + /// + public static partial class UmbracoBuilderExtensions + { + /// + /// Add Umbraco configuration services and options + /// + public static IUmbracoBuilder AddConfiguration(this IUmbracoBuilder builder) + { + // Register configuration validators. + builder.Services.AddSingleton, ContentSettingsValidator>(); + builder.Services.AddSingleton, GlobalSettingsValidator>(); + builder.Services.AddSingleton, HealthChecksSettingsValidator>(); + builder.Services.AddSingleton, RequestHandlerSettingsValidator>(); + + // Register configuration sections. + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigActiveDirectory)); + builder.Services.Configure(builder.Config.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigContent)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigCoreDebug)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExceptionFilter)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigGlobal)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHealthChecks)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHosting)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigImaging)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExamine)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigKeepAlive)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigLogging)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigMemberPassword)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigModelsBuilder), o => o.BindNonPublicProperties = true); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigNuCache)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRequestHandler)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRuntime)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigSecurity)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTours)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigPlugins)); + + return builder; + } + } +} diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs index a21ae74976..d5090de01b 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs @@ -2,6 +2,7 @@ // See LICENSE for more details. using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Umbraco.Core.Events; namespace Umbraco.Core.DependencyInjection @@ -23,7 +24,8 @@ namespace Umbraco.Core.DependencyInjection where TNotification : INotification { // Register the handler as transient. This ensures that anything can be injected into it. - builder.Services.AddTransient(typeof(INotificationHandler), typeof(TNotificationHandler)); + // TODO: Waiting on feedback here https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 + builder.Services.TryAddTransient(typeof(INotificationHandler), typeof(TNotificationHandler)); return builder; } } diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index 11b035bb73..32eed6d78d 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mail; using Umbraco.Core.Manifest; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.PropertyEditors; using Umbraco.Core.Runtime; using Umbraco.Core.Security; using Umbraco.Core.Services; @@ -130,6 +131,7 @@ namespace Umbraco.Core.DependencyInjection Services.AddUnique(); Services.AddUnique(); + this.AddAllCoreCollectionBuilders(); this.AddNotificationHandler(); Services.AddSingleton(); @@ -190,6 +192,9 @@ namespace Umbraco.Core.DependencyInjection Services.AddUnique(); Services.AddUnique(); Services.AddUnique(); + + Services.AddUnique(); + Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs b/src/Umbraco.Core/Media/IImageDimensionExtractor.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs rename to src/Umbraco.Core/Media/IImageDimensionExtractor.cs diff --git a/src/Umbraco.Infrastructure/Media/ImageSize.cs b/src/Umbraco.Core/Media/ImageSize.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/ImageSize.cs rename to src/Umbraco.Core/Media/ImageSize.cs diff --git a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs b/src/Umbraco.Core/Media/UploadAutoFillProperties.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs rename to src/Umbraco.Core/Media/UploadAutoFillProperties.cs diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs index 2149ece02a..a3c02aeb0d 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs @@ -1,11 +1,9 @@ -using System.Linq; +using System.Linq; using Umbraco.Core.Composing; using Umbraco.Core.Manifest; namespace Umbraco.Core.PropertyEditors { - - public class PropertyEditorCollection : BuilderCollectionBase { public PropertyEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs similarity index 100% rename from src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs rename to src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs similarity index 95% rename from src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs rename to src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs index 51471f6da7..64ecba5c7c 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Strings; @@ -8,7 +8,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters /// Value converter for the RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used. /// [DefaultPropertyValueConverter] - public class TinyMceValueConverter : PropertyValueConverterBase + public class SimpleTinyMceValueConverter : PropertyValueConverterBase { public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias == Constants.PropertyEditors.Aliases.TinyMce; diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs deleted file mode 100644 index 7caa9a90cc..0000000000 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Linq; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Core.PropertyEditors.ValueConverters -{ - [DefaultPropertyValueConverter] - public class TextStringValueConverter : PropertyValueConverterBase - { - private static readonly string[] PropertyTypeAliases = - { - Constants.PropertyEditors.Aliases.TextBox, - Constants.PropertyEditors.Aliases.TextArea - }; - - public override bool IsConverter(IPublishedPropertyType propertyType) - => PropertyTypeAliases.Contains(propertyType.EditorAlias); - - public override Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof (string); - - public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) - => PropertyCacheLevel.Element; - - public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) - { - // in xml a string is: string - // in the database a string is: string - // default value is: null - return source; - } - - public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) - { - // source should come from ConvertSource and be a string (or null) already - return inter ?? string.Empty; - } - - public override object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) - { - // source should come from ConvertSource and be a string (or null) already - return inter; - } - } -} diff --git a/src/Umbraco.Core/Trees/ISearchableTree.cs b/src/Umbraco.Core/Trees/ISearchableTree.cs index 3d82d548c8..8f31c2c6ab 100644 --- a/src/Umbraco.Core/Trees/ISearchableTree.cs +++ b/src/Umbraco.Core/Trees/ISearchableTree.cs @@ -1,8 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Umbraco.Core.Composing; using Umbraco.Web.Models.ContentEditing; -namespace Umbraco.Web.Trees +namespace Umbraco.Core.Trees { public interface ISearchableTree : IDiscoverable { diff --git a/src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs b/src/Umbraco.Core/Trees/SearchableApplicationTree.cs similarity index 92% rename from src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs rename to src/Umbraco.Core/Trees/SearchableApplicationTree.cs index 346f106b84..ad6fb7f43f 100644 --- a/src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs +++ b/src/Umbraco.Core/Trees/SearchableApplicationTree.cs @@ -1,6 +1,4 @@ -using Umbraco.Web.Trees; - -namespace Umbraco.Web.Search +namespace Umbraco.Core.Trees { public class SearchableApplicationTree { diff --git a/src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs b/src/Umbraco.Core/Trees/SearchableTreeCollection.cs similarity index 97% rename from src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs rename to src/Umbraco.Core/Trees/SearchableTreeCollection.cs index 5c251a857d..e562b763d4 100644 --- a/src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs +++ b/src/Umbraco.Core/Trees/SearchableTreeCollection.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core; @@ -6,7 +6,7 @@ using Umbraco.Core.Composing; using Umbraco.Web.Services; using Umbraco.Web.Trees; -namespace Umbraco.Web.Search +namespace Umbraco.Core.Trees { public class SearchableTreeCollection : BuilderCollectionBase { diff --git a/src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs similarity index 81% rename from src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs rename to src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs index a5e940b4a6..7922cf36ad 100644 --- a/src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs +++ b/src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs @@ -1,8 +1,7 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.Composing; -using Umbraco.Web.Trees; -namespace Umbraco.Web.Search +namespace Umbraco.Core.Trees { public class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase { diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 24b2fae683..263621aed7 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs index bafb537db6..131aac23f7 100644 --- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs @@ -9,11 +9,9 @@ using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Scoping; using Umbraco.Core.Sync; -using Umbraco.Web.Routing; namespace Umbraco.Web { @@ -28,6 +26,9 @@ namespace Umbraco.Web private readonly IRequestCache _requestCache; private readonly IRequestAccessor _requestAccessor; + /// + /// Initializes a new instance of the class. + /// public BatchedDatabaseServerMessenger( IMainDom mainDom, IScopeProvider scopeProvider, diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs index b0921f7698..43527b5486 100644 --- a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs +++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs @@ -47,7 +47,7 @@ namespace Umbraco.Infrastructure.Cache // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available // for the hosted services to use when the HTTP request is not available. _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce; - _requestAccessor.EndRequest += UmbracoModule_EndRequest; + _requestAccessor.EndRequest += EndRequest; Startup(); @@ -88,6 +88,6 @@ namespace Umbraco.Infrastructure.Cache /// /// Clear the batch on end request /// - private void UmbracoModule_EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.FlushBatch(); + private void EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.FlushBatch(); } } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs index 28bed7b363..4da9c93fb3 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Collections.cs @@ -5,8 +5,8 @@ using Umbraco.Core.PackageActions; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Strings; +using Umbraco.Core.Trees; using Umbraco.Web.Media.EmbedProviders; -using Umbraco.Web.Search; namespace Umbraco.Infrastructure.DependencyInjection { @@ -15,82 +15,11 @@ namespace Umbraco.Infrastructure.DependencyInjection /// public static partial class UmbracoBuilderExtensions { - /// - /// Gets the cache refreshers collection builder. - /// - /// The builder. - public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - /// /// Gets the mappers collection builder. /// /// The builder. public static MapperCollectionBuilder Mappers(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); - - /// - /// Gets the package actions collection builder. - /// - /// The builder. - internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the data editor collection builder. - /// - /// The builder. - public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the data value reference factory collection builder. - /// - /// The builder. - public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the property value converters collection builder. - /// - /// The builder. - public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the url segment providers collection builder. - /// - /// The builder. - public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the validators collection builder. - /// - /// The builder. - internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the manifest filter collection builder. - /// - /// The builder. - public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the backoffice OEmbed Providers collection builder. - /// - /// The builder. - public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - - /// - /// Gets the back office searchable tree collection builder - /// - /// - /// - public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); } } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index b4fd03350a..b5c76aad83 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -27,6 +27,7 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Serialization; using Umbraco.Core.Strings; using Umbraco.Core.Templates; +using Umbraco.Core.Trees; using Umbraco.Examine; using Umbraco.Infrastructure.Examine; using Umbraco.Infrastructure.Media; @@ -49,7 +50,6 @@ using Umbraco.Web.Routing; using Umbraco.Web.Search; using Umbraco.Web.Sections; using Umbraco.Web.Trees; -using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; namespace Umbraco.Infrastructure.DependencyInjection { @@ -116,47 +116,18 @@ namespace Umbraco.Infrastructure.DependencyInjection // register manifest parser, will be injected in collection builders where needed builder.Services.AddUnique(); - // register our predefined validators - builder.ManifestValueValidators() - .Add() - .Add() - .Add() - .Add() - .Add() - .Add(); - // register the manifest filter collection builder (collection is empty by default) builder.ManifestFilters(); - // properties and parameters derive from data editors - builder.DataEditors() - .Add(() => builder.TypeLoader.GetDataEditors()); - builder.MediaUrlGenerators() .Add() .Add(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - // Used to determine if a datatype/editor should be storing/tracking - // references to media item/s - builder.DataValueReferenceFactories(); - - builder.PackageActions() - .Add(() => builder.TypeLoader.GetPackageActions()); - - builder.PropertyValueConverters() - .Append(builder.TypeLoader.GetTypes()); - builder.Services.AddUnique(); builder.Services.AddUnique(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService>().Value))); - builder.UrlSegmentProviders() - .Append(); - builder.Services.AddUnique(factory => new MigrationBuilder(factory)); builder.Services.AddUnique(); @@ -166,10 +137,6 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(); - // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards - builder.Dashboards() - .Add(builder.TypeLoader.GetTypes()); - // Config manipulator builder.Services.AddUnique(); @@ -177,99 +144,22 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be - // discovered when CoreBootManager configures the converters. We HAVE to remove one of them - // here because there cannot be two converters for one property editor - and we want the full - // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. - // (the limited one, defined in Core, is there for tests) - same for others + // discovered when CoreBootManager configures the converters. We will remove the basic one defined + // in core so that the more enhanced version is active. builder.PropertyValueConverters() - .Remove() - .Remove() - .Remove(); - - builder.UrlProviders() - .Append() - .Append(); - - builder.MediaUrlProviders() - .Append(); + .Remove(); builder.Services.AddUnique(); - builder.Actions() - .Add(() => builder.TypeLoader.GetTypes()); - - builder.EditorValidators() - .Add(() => builder.TypeLoader.GetTypes()); - - builder.TourFilters(); - builder.Services.AddUnique(); - // register OEmbed providers - no type scanning - all explicit opt-in of adding types - // note: IEmbedProvider is not IDiscoverable - think about it if going for type scanning - builder.OEmbedProviders() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append(); - - // register back office sections in the order we want them rendered - builder.Sections() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append(); - - // register known content apps - builder.ContentApps() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append() - .Append(); - // register *all* checks, except those marked [HideFromTypeFinder] of course builder.Services.AddUnique(); - builder.HealthChecks() - .Add(() => builder.TypeLoader.GetTypes()); - - builder.WithCollectionBuilder() - .Add(() => builder.TypeLoader.GetTypes()); - + builder.Services.AddUnique(); - builder.ContentFinders() - - // all built-in finders in the correct order, - // devs can then modify this list on application startup - .Append() - .Append() - .Append() - - // .Append() // disabled, this is an odd finder - .Append() - .Append(); - builder.Services.AddScoped(); - builder.SearchableTrees() - .Add(() => builder.TypeLoader.GetTypes()); - // replace builder.Services.AddUnique(); @@ -303,6 +193,8 @@ namespace Umbraco.Infrastructure.DependencyInjection builder.Services.AddUnique(); + builder.AddInstaller(); + return builder; } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs index 23e927df97..8be46d38fb 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs @@ -26,7 +26,7 @@ namespace Umbraco.Infrastructure.DependencyInjection /// public static IUmbracoBuilder AddDistributedCache(this IUmbracoBuilder builder) { - // NOTE: the `DistributedCache` is registered in AddCoreInitialServices since it's a core service + // NOTE: the `DistributedCache` is registered in UmbracoBuilder since it's a core service builder.SetDatabaseServerMessengerCallbacks(GetCallbacks); builder.SetServerMessenger(); @@ -34,7 +34,7 @@ namespace Umbraco.Infrastructure.DependencyInjection // TODO: We don't need server registrar anymore // register a server registrar, by default it's the db registrar - builder.Services.AddUnique(f => + builder.Services.AddUnique(f => { var globalSettings = f.GetRequiredService>().Value; @@ -47,9 +47,6 @@ namespace Umbraco.Infrastructure.DependencyInjection new Lazy(f.GetRequiredService)); }); - builder.CacheRefreshers() - .Add(() => builder.TypeLoader.GetCacheRefreshers()); - builder.Services.AddUnique(); return builder; } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs index bcdead6fd0..e5bdd844d8 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs @@ -11,7 +11,7 @@ namespace Umbraco.Infrastructure.DependencyInjection /// /// Adds the services for the Umbraco installer /// - public static IUmbracoBuilder AddInstaller(this IUmbracoBuilder builder) + internal static IUmbracoBuilder AddInstaller(this IUmbracoBuilder builder) { // register the installer steps builder.Services.AddScoped(); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index 7fe202ed4c..d0713b46ff 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Text; using HtmlAgilityPack; using Umbraco.Core; @@ -16,7 +16,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters /// used dynamically. /// [DefaultPropertyValueConverter] - public class RteMacroRenderingValueConverter : TinyMceValueConverter + public class RteMacroRenderingValueConverter : SimpleTinyMceValueConverter { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IMacroRenderer _macroRenderer; diff --git a/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs index ecaf7354ca..a2955dfef5 100644 --- a/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs @@ -8,11 +8,11 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Core.Trees; using Umbraco.Examine; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; using Umbraco.Web.Routing; -using Umbraco.Web.Trees; namespace Umbraco.Web.Search { diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index ef3735032e..017b0ddb45 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -154,7 +154,6 @@ namespace Umbraco.Tests.Integration.TestServerTest mvcBuilder.AddApplicationPart(typeof(SurfaceController).Assembly); }) .AddWebServer() - .AddNuCache() .Build(); } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs index 556dedee14..e42fd7dbf1 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs @@ -1,12 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using NUnit.Framework; using Umbraco.Core.Cache; -using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; @@ -14,7 +11,6 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Sync; -using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -29,15 +25,12 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Scoping private DistributedCacheBinder _distributedCacheBinder; private IUserService UserService => GetRequiredService(); - private ILocalizationService LocalizationService => GetRequiredService(); - private IServerMessenger ServerMessenger => GetRequiredService(); - private CacheRefresherCollection CacheRefresherCollection => GetRequiredService(); - protected override void CustomTestSetup(IUmbracoBuilder builder) - { - builder.AddNuCache(); - builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IServerMessenger), typeof(LocalServerMessenger))); - } + private ILocalizationService LocalizationService => GetRequiredService(); + + private IServerMessenger ServerMessenger { get; } = new LocalServerMessenger(); + + private CacheRefresherCollection CacheRefresherCollection => GetRequiredService(); protected override AppCaches GetAppCaches() { diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs index 6b5af1e1e2..44459550d2 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs @@ -5,16 +5,13 @@ using Microsoft.Extensions.Logging; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.DependencyInjection; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Sync; -using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; using Umbraco.Web; -using Umbraco.Web.BackOffice.DependencyInjection; using Umbraco.Web.Cache; namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services @@ -54,8 +51,6 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services ContentTypeService.Save(_contentType); } - protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddNuCache(); - [TearDown] public void TearDownTest() { diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs index 010f680ad1..b52609ce89 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs @@ -38,8 +38,6 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services private ILocalizationService LocalizationService => GetRequiredService(); - protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddNuCache(); - protected override void BeforeHostStart(IHost host) { base.BeforeHostStart(host); diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs index e4095c1d33..e6a8104355 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs @@ -19,8 +19,6 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services Boot = true)] public class TrackRelationsTests : UmbracoIntegrationTestWithContent { - protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddNuCache(); - private IMediaTypeService MediaTypeService => GetRequiredService(); private IMediaService MediaService => GetRequiredService(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index aa8fc26bd8..ec8e55e2bf 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.PublishedContent Builder.WithCollectionBuilder() .Clear() .Append() - .Append() + .Append() .Append(); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index b2a6300cc9..219ca694e8 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -31,6 +31,7 @@ using Umbraco.Web.Common.ModelBinders; using Umbraco.Web.Models.Mapping; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Umbraco.Core.Trees; namespace Umbraco.Web.BackOffice.Controllers { diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index e8c6171f01..30e6bdcbc7 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -2,6 +2,7 @@ using System; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.DependencyInjection; +using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Web.BackOffice.Authorization; using Umbraco.Web.BackOffice.Security; @@ -32,8 +33,7 @@ namespace Umbraco.Web.BackOffice.DependencyInjection .AddWebServer() .AddPreviewSupport() .AddHostedServices() - .AddHttpClients() - .AddNuCache(); + .AddDistributedCache(); /// /// Adds Umbraco back office authentication requirements diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs index 16dd446d49..404ebfdb3a 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs @@ -22,6 +22,7 @@ using Microsoft.Extensions.Options; using Umbraco.Web.Trees; using Microsoft.AspNetCore.Authorization; using Umbraco.Web.Common.Authorization; +using Umbraco.Core.Trees; namespace Umbraco.Web.BackOffice.Trees { diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs index 8b5286bdd2..25c48b94bd 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; +using Umbraco.Core.Trees; using Umbraco.Web.Actions; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; diff --git a/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs index ab2bfdb8d4..30389fb1be 100644 --- a/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs @@ -16,6 +16,7 @@ using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Microsoft.AspNetCore.Authorization; using Umbraco.Web.Common.Authorization; +using Umbraco.Core.Trees; namespace Umbraco.Web.BackOffice.Trees { diff --git a/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs index ece4013d0b..d284624999 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs @@ -22,6 +22,7 @@ using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Microsoft.AspNetCore.Authorization; using Umbraco.Web.Common.Authorization; +using Umbraco.Core.Trees; namespace Umbraco.Web.BackOffice.Trees { diff --git a/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs index cd64e23067..424a0b2451 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs @@ -15,6 +15,7 @@ using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Microsoft.AspNetCore.Authorization; using Umbraco.Web.Common.Authorization; +using Umbraco.Core.Trees; namespace Umbraco.Web.BackOffice.Trees { diff --git a/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs index 4ebd8f7cc5..378a90da83 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs @@ -22,6 +22,7 @@ using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Microsoft.AspNetCore.Authorization; using Umbraco.Web.Common.Authorization; +using Umbraco.Core.Trees; namespace Umbraco.Web.BackOffice.Trees { diff --git a/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs index be400bef39..8a8fe7b11e 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; +using Umbraco.Core.Trees; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.BackOffice.Trees; using Umbraco.Web.Common.Attributes; diff --git a/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs index 361875a41b..eb08dbe629 100644 --- a/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Services; +using Umbraco.Core.Trees; using Umbraco.Extensions; using Umbraco.Web.Actions; using Umbraco.Web.BackOffice.Filters; diff --git a/src/Umbraco.Web.BackOffice/Trees/TreeControllerBase.cs b/src/Umbraco.Web.BackOffice/Trees/TreeControllerBase.cs index e469cd4a25..ad4266e5e5 100644 --- a/src/Umbraco.Web.BackOffice/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Trees/TreeControllerBase.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Persistence; +using Umbraco.Core.Trees; using Umbraco.Extensions; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Common.Filters; diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index f3109ac2da..29e3820637 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Data.SqlClient; using System.IO; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using Microsoft.AspNetCore.Builder; @@ -25,22 +26,39 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.Models.Validation; using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Diagnostics; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Runtime; +using Umbraco.Core.Security; using Umbraco.Extensions; using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.HostedServices; using Umbraco.Infrastructure.HostedServices.ServerRegistration; +using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Infrastructure.Runtime; +using Umbraco.Net; using Umbraco.Web.Cache; using Umbraco.Web.Common.ApplicationModels; using Umbraco.Web.Common.AspNetCore; +using Umbraco.Web.Common.Controllers; using Umbraco.Web.Common.DependencyInjection; +using Umbraco.Web.Common.Install; +using Umbraco.Web.Common.Lifetime; +using Umbraco.Web.Common.Macros; +using Umbraco.Web.Common.Middleware; +using Umbraco.Web.Common.ModelBinders; using Umbraco.Web.Common.Profiler; +using Umbraco.Web.Common.Routing; +using Umbraco.Web.Common.Security; +using Umbraco.Web.Common.Templates; +using Umbraco.Web.Macros; +using Umbraco.Web.Security; using Umbraco.Web.Telemetry; +using Umbraco.Web.Templates; using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; namespace Umbraco.Web.Common.DependencyInjection @@ -123,62 +141,13 @@ namespace Umbraco.Web.Common.DependencyInjection )); builder.AddCoreInitialServices(); + + // TODO: This should be a separate call to opt-in to plugins builder.AddComposers(); return builder; } - /// - /// Adds Umbraco composers for plugins - /// - public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder) - { - IEnumerable composerTypes = builder.TypeLoader.GetTypes(); - IEnumerable enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); - new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger()).Compose(); - - return builder; - } - - /// - /// Add Umbraco configuration services and options - /// - public static IUmbracoBuilder AddConfiguration(this IUmbracoBuilder builder) - { - // Register configuration validators. - builder.Services.AddSingleton, ContentSettingsValidator>(); - builder.Services.AddSingleton, GlobalSettingsValidator>(); - builder.Services.AddSingleton, HealthChecksSettingsValidator>(); - builder.Services.AddSingleton, RequestHandlerSettingsValidator>(); - - // Register configuration sections. - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigActiveDirectory)); - builder.Services.Configure(builder.Config.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigContent)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigCoreDebug)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExceptionFilter)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigGlobal)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHealthChecks)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHosting)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigImaging)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExamine)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigKeepAlive)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigLogging)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigMemberPassword)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigModelsBuilder), o => o.BindNonPublicProperties = true); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigNuCache)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRequestHandler)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRuntime)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigSecurity)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTours)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting)); - builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigPlugins)); - - return builder; - } - /// /// Add Umbraco hosted services /// @@ -195,8 +164,7 @@ namespace Umbraco.Web.Common.DependencyInjection return builder; } - // TODO: Not sure this needs to exist and/or be public? - public static IUmbracoBuilder AddHttpClients(this IUmbracoBuilder builder) + private static IUmbracoBuilder AddHttpClients(this IUmbracoBuilder builder) { builder.Services.AddHttpClient(); return builder; @@ -241,6 +209,9 @@ namespace Umbraco.Web.Common.DependencyInjection return builder; } + /// + /// Adds all web based services required for Umbraco to run + /// public static IUmbracoBuilder AddWebComponents(this IUmbracoBuilder builder) { // Add service session @@ -257,6 +228,59 @@ namespace Umbraco.Web.Common.DependencyInjection builder.Services.TryAddEnumerable(ServiceDescriptor.Transient()); builder.Services.AddUmbracoImageSharp(builder.Config); + // AspNetCore specific services + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + // Our own netcore implementations + builder.Services.AddMultipleUnique(); + + builder.Services.AddUnique(); + + // The umbraco request lifetime + builder.Services.AddMultipleUnique(); + + // Password hasher + builder.Services.AddUnique(); + + builder.Services.AddUnique(); + builder.Services.AddTransient(); + builder.Services.AddUnique(); + + builder.Services.AddMultipleUnique(); + + builder.Services.AddUnique(); + + builder.Services.AddUnique(); + + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + // register the umbraco context factory + + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); + builder.WithCollectionBuilder() + .Add(umbracoApiControllerTypes); + + builder.Services.AddUnique(); + + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + builder.Services.AddUnique(); + + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + builder.AddNuCache(); + builder.AddHttpClients(); + return builder; } diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs deleted file mode 100644 index 758125b425..0000000000 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Composing; -using Umbraco.Web.Common.Middleware; - -namespace Umbraco.Web.Common.Runtime -{ - /// - /// Executes if the boot fails to ensure critical services are registered - /// - public class AspNetCoreBootFailedComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - } - } -} diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index 42352d19f2..34a8b7583a 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -35,63 +35,5 @@ namespace Umbraco.Web.Common.Runtime [ComposeBefore(typeof(ICoreComposer))] public class AspNetCoreComposer : ComponentComposer, IComposer { - public override void Compose(IUmbracoBuilder builder) - { - base.Compose(builder); - - // AspNetCore specific services - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - // Our own netcore implementations - builder.Services.AddMultipleUnique(); - - builder.Services.AddUnique(); - - // The umbraco request lifetime - builder.Services.AddMultipleUnique(); - - // Password hasher - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - builder.Services.AddTransient(); - builder.Services.AddUnique(); - - builder.Services.AddMultipleUnique(); - - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - // register the umbraco context factory - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - //register the install components - builder.AddInstaller(); - - var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); - builder.WithCollectionBuilder() - .Add(umbracoApiControllerTypes); - - - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - } } } diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index f495c09d3c..5762a5fb69 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Core.DependencyInjection; +using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Web.Website.Controllers; using Umbraco.Web.Website.Routing; @@ -35,7 +36,7 @@ namespace Umbraco.Web.Website.DependencyInjection builder.Services.AddScoped(); builder.Services.AddSingleton(); - builder.AddNuCache(); + builder.AddDistributedCache(); return builder; } From 307ef4c1e070193aae9c40dec562dbe371eef8ef Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 14:44:42 +1100 Subject: [PATCH 12/26] Removes IBatchedDatabaseServerMessenger, renames methods of IServerMessenger --- src/Umbraco.Core/Cache/DistributedCache.cs | 16 +++++++------- .../Sync/DatabaseServerMessengerCallbacks.cs | 4 ++-- .../Sync/IBatchedDatabaseServerMessenger.cs | 12 ----------- src/Umbraco.Core/Sync/IServerMessenger.cs | 21 ++++++++++++------- .../BatchedDatabaseServerMessenger.cs | 7 ++++--- ...abaseServerMessengerNotificationHandler.cs | 6 +++--- .../HostedServices/ScheduledPublishing.cs | 4 ++-- .../Sync/ServerMessengerBase.cs | 21 ++++++++++--------- .../Testing/IntegrationTestComposer.cs | 18 +++++++++------- .../Scoping/ScopedRepositoryTests.cs | 2 ++ .../Services/ContentEventsTests.cs | 2 ++ .../DistributedCache/DistributedCacheTests.cs | 18 +++++++++------- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 4 +++- 13 files changed, 70 insertions(+), 65 deletions(-) delete mode 100644 src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs diff --git a/src/Umbraco.Core/Cache/DistributedCache.cs b/src/Umbraco.Core/Cache/DistributedCache.cs index 569ff47724..7ad9f9569f 100644 --- a/src/Umbraco.Core/Cache/DistributedCache.cs +++ b/src/Umbraco.Core/Cache/DistributedCache.cs @@ -46,7 +46,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty || instances.Length == 0 || getNumericId == null) return; - _serverMessenger.PerformRefresh( + _serverMessenger.QueueRefresh( GetRefresherById(refresherGuid), getNumericId, instances); @@ -61,7 +61,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty || id == default(int)) return; - _serverMessenger.PerformRefresh( + _serverMessenger.QueueRefresh( GetRefresherById(refresherGuid), id); } @@ -75,7 +75,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty || id == Guid.Empty) return; - _serverMessenger.PerformRefresh( + _serverMessenger.QueueRefresh( GetRefresherById(refresherGuid), id); } @@ -86,7 +86,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty || payload == null) return; - _serverMessenger.PerformRefresh( + _serverMessenger.QueueRefresh( GetRefresherById(refresherGuid), payload); } @@ -97,7 +97,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty || payloads == null) return; - _serverMessenger.PerformRefresh( + _serverMessenger.QueueRefresh( GetRefresherById(refresherGuid), payloads.ToArray()); } @@ -125,7 +125,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty) return; - _serverMessenger.PerformRefreshAll( + _serverMessenger.QueueRefreshAll( GetRefresherById(refresherGuid)); } @@ -138,7 +138,7 @@ namespace Umbraco.Web.Cache { if (refresherGuid == Guid.Empty || id == default(int)) return; - _serverMessenger.PerformRemove( + _serverMessenger.QueueRemove( GetRefresherById(refresherGuid), id); } @@ -155,7 +155,7 @@ namespace Umbraco.Web.Cache /// public void Remove(Guid refresherGuid, Func getNumericId, params T[] instances) { - _serverMessenger.PerformRemove( + _serverMessenger.QueueRemove( GetRefresherById(refresherGuid), getNumericId, instances); diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs b/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs index 7438762295..f7dafac7a6 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs @@ -1,10 +1,10 @@ -using System; +using System; using System.Collections.Generic; namespace Umbraco.Core.Sync { /// - /// Holds a list of callbacks associated with implementations of . + /// Holds a list of callbacks associated with implementations of . /// public class DatabaseServerMessengerCallbacks { diff --git a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs deleted file mode 100644 index 02859ff6f0..0000000000 --- a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Umbraco.Core.Sync -{ - /// - /// An implementation that works by storing messages in the database. - /// - public interface IBatchedDatabaseServerMessenger : IServerMessenger - { - // TODO: We only ever use IBatchedDatabaseServerMessenger so just combine these interfaces - - void FlushBatch(); - } -} diff --git a/src/Umbraco.Core/Sync/IServerMessenger.cs b/src/Umbraco.Core/Sync/IServerMessenger.cs index a6c5b5d755..df2d665057 100644 --- a/src/Umbraco.Core/Sync/IServerMessenger.cs +++ b/src/Umbraco.Core/Sync/IServerMessenger.cs @@ -14,12 +14,17 @@ namespace Umbraco.Core.Sync /// void Sync(); + /// + /// Called to send/commit the queued messages created with the Perform methods + /// + void SendMessages(); + /// /// Notifies the distributed cache, for a specified . /// /// The ICacheRefresher. /// The notification content. - void PerformRefresh(ICacheRefresher refresher, TPayload[] payload); + void QueueRefresh(ICacheRefresher refresher, TPayload[] payload); /// /// Notifies the distributed cache of specified item invalidation, for a specified . @@ -28,7 +33,7 @@ namespace Umbraco.Core.Sync /// The ICacheRefresher. /// A function returning the unique identifier of items. /// The invalidated items. - void PerformRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances); + void QueueRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances); /// /// Notifies the distributed cache of specified item invalidation, for a specified . @@ -37,7 +42,7 @@ namespace Umbraco.Core.Sync /// The ICacheRefresher. /// A function returning the unique identifier of items. /// The invalidated items. - void PerformRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances); + void QueueRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances); /// /// Notifies all servers of specified items removal, for a specified . @@ -46,33 +51,33 @@ namespace Umbraco.Core.Sync /// The ICacheRefresher. /// A function returning the unique identifier of items. /// The removed items. - void PerformRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances); + void QueueRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances); /// /// Notifies all servers of specified items removal, for a specified . /// /// The ICacheRefresher. /// The unique identifiers of the removed items. - void PerformRemove(ICacheRefresher refresher, params int[] numericIds); + void QueueRemove(ICacheRefresher refresher, params int[] numericIds); /// /// Notifies all servers of specified items invalidation, for a specified . /// /// The ICacheRefresher. /// The unique identifiers of the invalidated items. - void PerformRefresh(ICacheRefresher refresher, params int[] numericIds); + void QueueRefresh(ICacheRefresher refresher, params int[] numericIds); /// /// Notifies all servers of specified items invalidation, for a specified . /// /// The ICacheRefresher. /// The unique identifiers of the invalidated items. - void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds); + void QueueRefresh(ICacheRefresher refresher, params Guid[] guidIds); /// /// Notifies all servers of a global invalidation for a specified . /// /// The ICacheRefresher. - void PerformRefreshAll(ICacheRefresher refresher); + void QueueRefreshAll(ICacheRefresher refresher); } } diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs index 131aac23f7..caba831aff 100644 --- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web /// /// This binds to appropriate umbraco events in order to trigger the Boot(), Sync() & FlushBatch() calls /// - public class BatchedDatabaseServerMessenger : DatabaseServerMessenger, IBatchedDatabaseServerMessenger + public class BatchedDatabaseServerMessenger : DatabaseServerMessenger { private readonly IRequestCache _requestCache; private readonly IRequestAccessor _requestAccessor; @@ -58,7 +58,7 @@ namespace Umbraco.Web BatchMessage(refresher, messageType, idsA, arrayType, json); } - public void FlushBatch() + public override void SendMessages() { var batch = GetBatch(false); if (batch == null) return; @@ -66,13 +66,14 @@ namespace Umbraco.Web var instructions = batch.SelectMany(x => x.Instructions).ToArray(); batch.Clear(); - //Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount + // Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount using (var scope = ScopeProvider.CreateScope()) { foreach (var instructionsBatch in instructions.InGroupsOf(GlobalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) { WriteInstructions(scope, instructionsBatch); } + scope.Complete(); } diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs index 43527b5486..c8d8c81ab1 100644 --- a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs +++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs @@ -15,7 +15,7 @@ namespace Umbraco.Infrastructure.Cache /// public sealed class DatabaseServerMessengerNotificationHandler : INotificationHandler { - private readonly IBatchedDatabaseServerMessenger _messenger; + private readonly IServerMessenger _messenger; private readonly IRequestAccessor _requestAccessor; private readonly IUmbracoDatabaseFactory _databaseFactory; private readonly IDistributedCacheBinder _distributedCacheBinder; @@ -35,7 +35,7 @@ namespace Umbraco.Infrastructure.Cache _databaseFactory = databaseFactory; _distributedCacheBinder = distributedCacheBinder; _logger = logger; - _messenger = serverMessenger as IBatchedDatabaseServerMessenger; + _messenger = serverMessenger; } /// @@ -88,6 +88,6 @@ namespace Umbraco.Infrastructure.Cache /// /// Clear the batch on end request /// - private void EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.FlushBatch(); + private void EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.SendMessages(); } } diff --git a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs index 4c235255c2..bd73310c29 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs @@ -123,9 +123,9 @@ namespace Umbraco.Infrastructure.HostedServices finally { // If running on a temp context, we have to flush the messenger - if (contextReference.IsRoot && _serverMessenger is IBatchedDatabaseServerMessenger m) + if (contextReference.IsRoot) { - m.FlushBatch(); + _serverMessenger.SendMessages(); } } } diff --git a/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs b/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs index 150f3428a7..dfba90291b 100644 --- a/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs +++ b/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs @@ -55,7 +55,7 @@ namespace Umbraco.Core.Sync #region IServerMessenger - public void PerformRefresh(ICacheRefresher refresher, TPayload[] payload) + public void QueueRefresh(ICacheRefresher refresher, TPayload[] payload) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); if (payload == null) throw new ArgumentNullException(nameof(payload)); @@ -72,7 +72,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RefreshByJson, json: jsonPayload); } - public void PerformRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances) + public void QueueRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -83,7 +83,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RefreshByInstance, getId, instances); } - public void PerformRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances) + public void QueueRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -94,7 +94,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RefreshByInstance, getId, instances); } - public void PerformRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances) + public void QueueRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -105,7 +105,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RemoveByInstance, getId, instances); } - public void PerformRemove(ICacheRefresher refresher, params int[] numericIds) + public void QueueRemove(ICacheRefresher refresher, params int[] numericIds) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -114,7 +114,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RemoveById, numericIds.Cast()); } - public void PerformRefresh(ICacheRefresher refresher, params int[] numericIds) + public void QueueRefresh(ICacheRefresher refresher, params int[] numericIds) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -123,7 +123,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RefreshById, numericIds.Cast()); } - public void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds) + public void QueueRefresh(ICacheRefresher refresher, params Guid[] guidIds) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -132,7 +132,7 @@ namespace Umbraco.Core.Sync Deliver(refresher, MessageType.RefreshById, guidIds.Cast()); } - public void PerformRefreshAll(ICacheRefresher refresher) + public void QueueRefreshAll(ICacheRefresher refresher) { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); @@ -346,8 +346,6 @@ namespace Umbraco.Core.Sync DeliverRemote(refresher, messageType, idsA); } - public abstract void Sync(); - //protected virtual void Deliver(ICacheRefresher refresher, object payload) //{ // if (servers == null) throw new ArgumentNullException("servers"); @@ -367,5 +365,8 @@ namespace Umbraco.Core.Sync //} #endregion + + public abstract void Sync(); + public abstract void SendMessages(); } } diff --git a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs index 1aeaec1bca..842a2a8a34 100644 --- a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs +++ b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs @@ -114,47 +114,49 @@ namespace Umbraco.Tests.Integration.Testing public NoopServerMessenger() { } - public void PerformRefresh(ICacheRefresher refresher, TPayload[] payload) + public void QueueRefresh(ICacheRefresher refresher, TPayload[] payload) { } - public void PerformRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances) + public void QueueRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances) { } - public void PerformRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances) + public void QueueRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances) { } - public void PerformRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances) + public void QueueRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances) { } - public void PerformRemove(ICacheRefresher refresher, params int[] numericIds) + public void QueueRemove(ICacheRefresher refresher, params int[] numericIds) { } - public void PerformRefresh(ICacheRefresher refresher, params int[] numericIds) + public void QueueRefresh(ICacheRefresher refresher, params int[] numericIds) { } - public void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds) + public void QueueRefresh(ICacheRefresher refresher, params Guid[] guidIds) { } - public void PerformRefreshAll(ICacheRefresher refresher) + public void QueueRefreshAll(ICacheRefresher refresher) { } public void Sync() { } + + public void SendMessages() { } } } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs index e42fd7dbf1..0a1e46274b 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs @@ -328,6 +328,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Scoping : base(false) { } + public override void SendMessages() { } + public override void Sync() { } protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs index 44459550d2..68ec7fcf5f 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs @@ -2166,6 +2166,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services public LocalServerMessenger() : base(false) { } + public override void SendMessages() { } + public override void Sync() { } protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs index 6211711202..706ca94e71 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs @@ -134,30 +134,32 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache.DistributedCache public List PayloadsRefreshed { get; } = new List(); public int CountOfFullRefreshes { get; private set; } = 0; - public void PerformRefresh(ICacheRefresher refresher, TPayload[] payload) + public void QueueRefresh(ICacheRefresher refresher, TPayload[] payload) { // doing nothing } public void PerformRefresh(ICacheRefresher refresher, string jsonPayload) => PayloadsRefreshed.Add(jsonPayload); - public void PerformRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances) => IntIdsRefreshed.AddRange(instances.Select(getNumericId)); + public void QueueRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances) => IntIdsRefreshed.AddRange(instances.Select(getNumericId)); - public void PerformRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances) => GuidIdsRefreshed.AddRange(instances.Select(getGuidId)); + public void QueueRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances) => GuidIdsRefreshed.AddRange(instances.Select(getGuidId)); public void PerformRemove(ICacheRefresher refresher, string jsonPayload) => PayloadsRemoved.Add(jsonPayload); - public void PerformRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances) => IntIdsRemoved.AddRange(instances.Select(getNumericId)); + public void QueueRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances) => IntIdsRemoved.AddRange(instances.Select(getNumericId)); - public void PerformRemove(ICacheRefresher refresher, params int[] numericIds) => IntIdsRemoved.AddRange(numericIds); + public void QueueRemove(ICacheRefresher refresher, params int[] numericIds) => IntIdsRemoved.AddRange(numericIds); - public void PerformRefresh(ICacheRefresher refresher, params int[] numericIds) => IntIdsRefreshed.AddRange(numericIds); + public void QueueRefresh(ICacheRefresher refresher, params int[] numericIds) => IntIdsRefreshed.AddRange(numericIds); - public void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds) => GuidIdsRefreshed.AddRange(guidIds); + public void QueueRefresh(ICacheRefresher refresher, params Guid[] guidIds) => GuidIdsRefreshed.AddRange(guidIds); - public void PerformRefreshAll(ICacheRefresher refresher) => CountOfFullRefreshes++; + public void QueueRefreshAll(ICacheRefresher refresher) => CountOfFullRefreshes++; public void Sync() { } + + public void SendMessages() { } } internal class TestServerRegistrar : IServerRegistrar diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 51c306a864..b4009d6f3e 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Xml; using Microsoft.Extensions.DependencyInjection; @@ -300,6 +300,8 @@ namespace Umbraco.Tests.Scoping : base(false) { } + public override void SendMessages() { } + public override void Sync() { } protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) From 91486bbede4dc15c949704141b4a34d612301ed6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 16:35:59 +1100 Subject: [PATCH 13/26] Removes IServerRegistrar, new IServerRoleAccessor, removes more composers, moves more to ext, --- .../UmbracoBuilder.Composers.cs | 5 +- .../DependencyInjection/UmbracoBuilder.cs | 21 ++++++++ src/Umbraco.Core/Diagnostics/NoopMarchal.cs | 9 ++++ .../IUmbracoApplicationLifetime.cs | 11 ++-- .../IUmbracoApplicationLifetimeManager.cs | 8 +++ .../NoopApplicationShutdownRegistry.cs | 8 +++ .../NoopUmbracoApplicationLifetimeManager.cs | 7 +++ .../InstallSteps/StarterKitInstallStep.cs | 2 +- .../{VoidProfiler.cs => NoopProfiler.cs} | 4 +- src/Umbraco.Core/Manifest/ManifestWatcher.cs | 2 +- .../Services/IServerRegistrationService.cs | 10 +--- .../Sync/DatabaseServerRegistrar.cs | 43 ---------------- .../Sync/ElectedServerRoleAccessor.cs | 29 +++++++++++ src/Umbraco.Core/Sync/IServerRegistrar.cs | 21 -------- src/Umbraco.Core/Sync/IServerRoleAccessor.cs | 15 ++++++ .../Sync/SingleServerRegistrar.cs | 44 ---------------- .../Sync/SingleServerRoleAccessor.cs | 19 +++++++ .../BatchedDatabaseServerMessenger.cs | 2 +- .../UmbracoBuilder.CoreServices.cs | 51 +++++++------------ .../UmbracoBuilder.DistributedCache.cs | 25 ++------- .../HostedServices/HealthCheckNotifier.cs | 6 +-- .../HostedServices/KeepAlive.cs | 6 +-- .../HostedServices/LogScrubber.cs | 6 +-- .../HostedServices/ScheduledPublishing.cs | 6 +-- .../ServerRegistration/TouchServerTask.cs | 4 +- .../InstallSteps/StarterKitDownloadStep.cs | 2 +- .../Enrichers/ThreadAbortExceptionEnricher.cs | 4 +- .../Logging/Serilog/SerilogComposer.cs | 21 -------- .../Implement/ServerRegistrationService.cs | 35 ++++++------- .../Sync/DatabaseServerMessenger.cs | 6 +-- .../Compose/ModelsBuilderComponent.cs | 2 +- .../UmbracoBuilderExtensions.cs} | 50 +++++++++--------- .../Implementations/TestHelper.cs | 2 +- src/Umbraco.Tests.Integration/RuntimeTests.cs | 6 ++- .../UmbracoBuilderExtensions.cs | 27 ---------- .../UmbracoTestServerTestBase.cs | 4 +- .../Testing/UmbracoIntegrationTest.cs | 16 +++--- .../DistributedCache/DistributedCacheTests.cs | 6 +-- .../HealthCheckNotifierTests.cs | 4 +- .../HostedServices/KeepAliveTests.cs | 4 +- .../HostedServices/LogScrubberTests.cs | 4 +- .../ScheduledPublishingTests.cs | 4 +- .../TouchServerTaskTests.cs | 5 +- .../Scoping/ScopedNuCacheTests.cs | 4 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 2 +- .../Controllers/PackageInstallController.cs | 1 - .../AspNetCoreApplicationShutdownRegistry.cs | 17 +++---- .../AspNetCoreUmbracoApplicationLifetime.cs | 9 ++-- .../UmbracoBuilderExtensions.cs | 21 ++++---- .../Install/InstallApiController.cs | 2 +- .../Profiler/WebProfilerComponent.cs | 4 +- .../Runtime/AspNetCoreComponent.cs | 4 +- .../AspNetUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 4 +- 54 files changed, 273 insertions(+), 363 deletions(-) create mode 100644 src/Umbraco.Core/Diagnostics/NoopMarchal.cs rename src/Umbraco.Core/{Net => Hosting}/IUmbracoApplicationLifetime.cs (73%) create mode 100644 src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs create mode 100644 src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs create mode 100644 src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs rename src/Umbraco.Core/Logging/{VoidProfiler.cs => NoopProfiler.cs} (89%) delete mode 100644 src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs create mode 100644 src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs delete mode 100644 src/Umbraco.Core/Sync/IServerRegistrar.cs create mode 100644 src/Umbraco.Core/Sync/IServerRoleAccessor.cs delete mode 100644 src/Umbraco.Core/Sync/SingleServerRegistrar.cs create mode 100644 src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs delete mode 100644 src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs rename src/Umbraco.Tests.Integration/{Testing/IntegrationTestComposer.cs => DependencyInjection/UmbracoBuilderExtensions.cs} (78%) delete mode 100644 src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs index 3479bd74d6..5bd2fe9e8c 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using Umbraco.Core.Composing; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; +using Umbraco.Core.Composing; namespace Umbraco.Core.DependencyInjection { @@ -16,6 +15,8 @@ namespace Umbraco.Core.DependencyInjection /// public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder) { + // TODO: Should have a better name + IEnumerable composerTypes = builder.TypeLoader.GetTypes(); IEnumerable enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger()).Compose(); diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index 32eed6d78d..96f01d111a 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -8,10 +8,13 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Grid; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Diagnostics; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.Hosting; @@ -107,6 +110,14 @@ namespace Umbraco.Core.DependencyInjection Services.AddLazySupport(); + // Adds no-op registrations as many core services require these dependencies but these + // dependencies cannot be fulfilled in the Core project + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); + Services.AddUnique(); + + Services.AddUnique(); Services.AddUnique(); Services.AddUnique(factory => @@ -195,6 +206,16 @@ namespace Umbraco.Core.DependencyInjection Services.AddUnique(); Services.AddUnique(); + + // register a server registrar, by default it's the db registrar + Services.AddUnique(f => + { + GlobalSettings globalSettings = f.GetRequiredService>().Value; + var singleServer = globalSettings.DisableElectionForSingleServer; + return singleServer + ? (IServerRoleAccessor)new SingleServerRoleAccessor() + : new ElectedServerRoleAccessor(f.GetRequiredService()); + }); } } } diff --git a/src/Umbraco.Core/Diagnostics/NoopMarchal.cs b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs new file mode 100644 index 0000000000..09629f9595 --- /dev/null +++ b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs @@ -0,0 +1,9 @@ +using System; + +namespace Umbraco.Core.Diagnostics +{ + internal class NoopMarchal : IMarchal + { + public IntPtr GetExceptionPointers() => IntPtr.Zero; + } +} diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs similarity index 73% rename from src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs rename to src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs index a032720d46..a4368a2634 100644 --- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs @@ -1,25 +1,20 @@ using System; -namespace Umbraco.Net +namespace Umbraco.Core.Hosting { - // TODO: This shouldn't be in this namespace? public interface IUmbracoApplicationLifetime { /// /// A value indicating whether the application is restarting after the current request. /// bool IsRestarting { get; } + /// /// Terminates the current application. The application restarts the next time a request is received for it. /// void Restart(); + // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications event EventHandler ApplicationInit; } - - - public interface IUmbracoApplicationLifetimeManager - { - void InvokeApplicationInit(); - } } diff --git a/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs new file mode 100644 index 0000000000..778edc24dd --- /dev/null +++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Hosting +{ + // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications + public interface IUmbracoApplicationLifetimeManager + { + void InvokeApplicationInit(); + } +} diff --git a/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs new file mode 100644 index 0000000000..3ffef04410 --- /dev/null +++ b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Hosting +{ + internal class NoopApplicationShutdownRegistry : IApplicationShutdownRegistry + { + public void RegisterObject(IRegisteredObject registeredObject) { } + public void UnregisterObject(IRegisteredObject registeredObject) { } + } +} diff --git a/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs b/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs new file mode 100644 index 0000000000..7833fd1224 --- /dev/null +++ b/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Core.Hosting +{ + internal class NoopUmbracoApplicationLifetimeManager : IUmbracoApplicationLifetimeManager + { + public void InvokeApplicationInit() { } + } +} diff --git a/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs index e3cd56c5c1..4866c472e6 100644 --- a/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs @@ -2,9 +2,9 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Umbraco.Core.Hosting; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Core/Logging/VoidProfiler.cs b/src/Umbraco.Core/Logging/NoopProfiler.cs similarity index 89% rename from src/Umbraco.Core/Logging/VoidProfiler.cs rename to src/Umbraco.Core/Logging/NoopProfiler.cs index d771fd7630..e7b43e5e2d 100644 --- a/src/Umbraco.Core/Logging/VoidProfiler.cs +++ b/src/Umbraco.Core/Logging/NoopProfiler.cs @@ -1,8 +1,8 @@ -using System; +using System; namespace Umbraco.Core.Logging { - public class VoidProfiler : IProfiler + public class NoopProfiler : IProfiler { private readonly VoidDisposable _disposable = new VoidDisposable(); diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs index e74393a179..b6cd82b31f 100644 --- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs +++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Extensions.Logging; -using Umbraco.Net; +using Umbraco.Core.Hosting; namespace Umbraco.Core.Manifest { diff --git a/src/Umbraco.Core/Services/IServerRegistrationService.cs b/src/Umbraco.Core/Services/IServerRegistrationService.cs index 62bb68eb14..f0246dd287 100644 --- a/src/Umbraco.Core/Services/IServerRegistrationService.cs +++ b/src/Umbraco.Core/Services/IServerRegistrationService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Umbraco.Core.Models; using Umbraco.Core.Sync; @@ -11,9 +11,8 @@ namespace Umbraco.Core.Services /// Touches a server to mark it as active; deactivate stale servers. /// /// The server URL. - /// The server unique identity. /// The time after which a server is considered stale. - void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout); + void TouchServer(string serverAddress, TimeSpan staleTimeout); /// /// Deactivates a server. @@ -38,11 +37,6 @@ namespace Umbraco.Core.Services /// from the database. IEnumerable GetActiveServers(bool refresh = false); - /// - /// Gets the current server identity. - /// - string CurrentServerIdentity { get; } - /// /// Gets the role of the current server. /// diff --git a/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs b/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs deleted file mode 100644 index f361eb7a67..0000000000 --- a/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core.Services; - -namespace Umbraco.Core.Sync -{ - /// - /// A registrar that stores registered server nodes in the database. - /// - /// - /// This is the default registrar which determines a server's role by using a master election process. - /// The master election process doesn't occur until just after startup so this election process doesn't really affect the primary startup phase. - /// - public sealed class DatabaseServerRegistrar : IServerRegistrar - { - private readonly Lazy _registrationService; - - /// - /// Initializes a new instance of the class. - /// - /// The registration service. - /// Some options. - public DatabaseServerRegistrar(Lazy registrationService) - { - _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService)); - } - - /// - /// Gets the registered servers. - /// - public IEnumerable Registrations => _registrationService.Value.GetActiveServers(); - - /// - /// Gets the role of the current server in the application environment. - /// - public ServerRole GetCurrentServerRole() - { - var service = _registrationService.Value; - return service.GetCurrentServerRole(); - } - - } -} diff --git a/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs b/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs new file mode 100644 index 0000000000..e4accd046b --- /dev/null +++ b/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs @@ -0,0 +1,29 @@ +using System; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Sync +{ + /// + /// Gets the current server's based on active servers registered with + /// + /// + /// This is the default service which determines a server's role by using a master election process. + /// The master election process doesn't occur until just after startup so this election process doesn't really affect the primary startup phase. + /// + public sealed class ElectedServerRoleAccessor : IServerRoleAccessor + { + private readonly IServerRegistrationService _registrationService; + + /// + /// Initializes a new instance of the class. + /// + /// The registration service. + /// Some options. + public ElectedServerRoleAccessor(IServerRegistrationService registrationService) => _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService)); + + /// + /// Gets the role of the current server in the application environment. + /// + public ServerRole CurrentServerRole => _registrationService.GetCurrentServerRole(); + } +} diff --git a/src/Umbraco.Core/Sync/IServerRegistrar.cs b/src/Umbraco.Core/Sync/IServerRegistrar.cs deleted file mode 100644 index 7e63b6b170..0000000000 --- a/src/Umbraco.Core/Sync/IServerRegistrar.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Sync -{ - /// - /// Provides server registrations to the distributed cache. - /// - public interface IServerRegistrar - { - /// - /// Gets the server registrations. - /// - IEnumerable Registrations { get; } // TODO: This isn't even used anymore, this whole interface can probably go away - - /// - /// Gets the role of the current server in the application environment. - /// - ServerRole GetCurrentServerRole(); - - } -} diff --git a/src/Umbraco.Core/Sync/IServerRoleAccessor.cs b/src/Umbraco.Core/Sync/IServerRoleAccessor.cs new file mode 100644 index 0000000000..b23acbac7c --- /dev/null +++ b/src/Umbraco.Core/Sync/IServerRoleAccessor.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Sync +{ + /// + /// Gets the current server's + /// + public interface IServerRoleAccessor + { + /// + /// Gets the role of the current server in the application environment. + /// + ServerRole CurrentServerRole { get; } + } +} diff --git a/src/Umbraco.Core/Sync/SingleServerRegistrar.cs b/src/Umbraco.Core/Sync/SingleServerRegistrar.cs deleted file mode 100644 index fe03e195b2..0000000000 --- a/src/Umbraco.Core/Sync/SingleServerRegistrar.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Web; - -namespace Umbraco.Core.Sync -{ - /// - /// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup performance - /// - /// - /// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the - /// which by default is done with master election by a database query. The master election process doesn't occur until just after startup - /// so this micro optimization doesn't really affect the primary startup phase. - /// - public class SingleServerRegistrar : IServerRegistrar - { - private readonly IRequestAccessor _requestAccessor; - private readonly Lazy _registrations; - - public IEnumerable Registrations => _registrations.Value; - - public SingleServerRegistrar(IRequestAccessor requestAccessor) - { - _requestAccessor = requestAccessor; - _registrations = new Lazy(() => new IServerAddress[] { new ServerAddressImpl(_requestAccessor.GetApplicationUrl().ToString()) }); - } - - public ServerRole GetCurrentServerRole() - { - return ServerRole.Single; - } - - - private class ServerAddressImpl : IServerAddress - { - public ServerAddressImpl(string serverAddress) - { - ServerAddress = serverAddress; - } - - public string ServerAddress { get; } - } - } -} diff --git a/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs new file mode 100644 index 0000000000..65b9559522 --- /dev/null +++ b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using Umbraco.Web; + +namespace Umbraco.Core.Sync +{ + /// + /// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup performance + /// + /// + /// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the + /// which by default is done with master election by a database query. The master election process doesn't occur until just after startup + /// so this micro optimization doesn't really affect the primary startup phase. + /// + public class SingleServerRoleAccessor : IServerRoleAccessor + { + public ServerRole CurrentServerRole => ServerRole.Single; + } +} diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs index caba831aff..6900354202 100644 --- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web IScopeProvider scopeProvider, IProfilingLogger proflog, ILogger logger, - IServerRegistrar serverRegistrar, + IServerRoleAccessor serverRegistrar, DatabaseServerMessengerCallbacks callbacks, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers, diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index b5c76aad83..94c1e3dcfa 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -6,10 +6,10 @@ using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Dashboards; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Hosting; using Umbraco.Core.Install; +using Umbraco.Core.Logging.Serilog.Enrichers; using Umbraco.Core.Mail; using Umbraco.Core.Manifest; using Umbraco.Core.Media; @@ -19,28 +19,22 @@ using Umbraco.Core.Migrations.PostMigrations; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Runtime; using Umbraco.Core.Scoping; using Umbraco.Core.Serialization; using Umbraco.Core.Strings; using Umbraco.Core.Templates; -using Umbraco.Core.Trees; using Umbraco.Examine; using Umbraco.Infrastructure.Examine; +using Umbraco.Infrastructure.Logging.Serilog.Enrichers; using Umbraco.Infrastructure.Media; using Umbraco.Infrastructure.Runtime; using Umbraco.Web; -using Umbraco.Web.Actions; -using Umbraco.Web.ContentApps; -using Umbraco.Web.Editors; using Umbraco.Web.HealthCheck; using Umbraco.Web.HealthCheck.NotificationMethods; using Umbraco.Web.Install; using Umbraco.Web.Media; -using Umbraco.Web.Media.EmbedProviders; using Umbraco.Web.Migrations.PostMigrations; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.PropertyEditors; @@ -48,39 +42,20 @@ using Umbraco.Web.PropertyEditors.ValueConverters; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Search; -using Umbraco.Web.Sections; using Umbraco.Web.Trees; namespace Umbraco.Infrastructure.DependencyInjection { public static partial class UmbracoBuilderExtensions { - - /* - * TODO: Many of these things are not "Core" services and are probably not required to run - * - * This should be split up: - * - Distributed Cache - * - BackOffice - * - Manifest - * - Property Editors - * - Packages - * - Dashboards - * - OEmbed - * - Sections - * - Content Apps - * - Health Checks - * - ETC... - * - Installation - * - Front End - */ - /// /// Adds all core Umbraco services required to run which may be replaced later in the pipeline /// public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder) { - builder.AddMainDom(); + builder + .AddMainDom() + .AddLogging(); builder.Services.AddUnique(); builder.Services.AddUnique(factory => factory.GetRequiredService().CreateDatabase()); @@ -155,7 +130,7 @@ namespace Umbraco.Infrastructure.DependencyInjection // register *all* checks, except those marked [HideFromTypeFinder] of course builder.Services.AddUnique(); - + builder.Services.AddUnique(); builder.Services.AddScoped(); @@ -198,10 +173,20 @@ namespace Umbraco.Infrastructure.DependencyInjection return builder; } + /// + /// Adds logging requirements for Umbraco + /// + private static IUmbracoBuilder AddLogging(this IUmbracoBuilder builder) + { + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + return builder; + } + private static IUmbracoBuilder AddMainDom(this IUmbracoBuilder builder) { - builder.Services.AddUnique(); - builder.Services.AddUnique(factory => { var globalSettings = factory.GetRequiredService>().Value; diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs index 8be46d38fb..3ad7556c92 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs @@ -26,27 +26,10 @@ namespace Umbraco.Infrastructure.DependencyInjection /// public static IUmbracoBuilder AddDistributedCache(this IUmbracoBuilder builder) { - // NOTE: the `DistributedCache` is registered in UmbracoBuilder since it's a core service - builder.SetDatabaseServerMessengerCallbacks(GetCallbacks); builder.SetServerMessenger(); builder.AddNotificationHandler(); - // TODO: We don't need server registrar anymore - // register a server registrar, by default it's the db registrar - builder.Services.AddUnique(f => - { - var globalSettings = f.GetRequiredService>().Value; - - // TODO: we still register the full IServerMessenger because - // even on 1 single server we can have 2 concurrent app domains - var singleServer = globalSettings.DisableElectionForSingleServer; - return singleServer - ? (IServerRegistrar)new SingleServerRegistrar(f.GetRequiredService()) - : new DatabaseServerRegistrar( - new Lazy(f.GetRequiredService)); - }); - builder.Services.AddUnique(); return builder; } @@ -57,15 +40,15 @@ namespace Umbraco.Infrastructure.DependencyInjection /// The type of the server registrar. /// The builder. public static void SetServerRegistrar(this IUmbracoBuilder builder) - where T : class, IServerRegistrar - => builder.Services.AddUnique(); + where T : class, IServerRoleAccessor + => builder.Services.AddUnique(); /// /// Sets the server registrar. /// /// The builder. /// A function creating a server registrar. - public static void SetServerRegistrar(this IUmbracoBuilder builder, Func factory) + public static void SetServerRegistrar(this IUmbracoBuilder builder, Func factory) => builder.Services.AddUnique(factory); /// @@ -73,7 +56,7 @@ namespace Umbraco.Infrastructure.DependencyInjection /// /// The builder. /// A server registrar. - public static void SetServerRegistrar(this IUmbracoBuilder builder, IServerRegistrar registrar) + public static void SetServerRegistrar(this IUmbracoBuilder builder, IServerRoleAccessor registrar) => builder.Services.AddUnique(registrar); /// diff --git a/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs b/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs index cd89ebc046..c1412d4169 100644 --- a/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs +++ b/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs @@ -30,7 +30,7 @@ namespace Umbraco.Infrastructure.HostedServices private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; private readonly IRuntimeState _runtimeState; - private readonly IServerRegistrar _serverRegistrar; + private readonly IServerRoleAccessor _serverRegistrar; private readonly IMainDom _mainDom; private readonly IScopeProvider _scopeProvider; private readonly ILogger _logger; @@ -54,7 +54,7 @@ namespace Umbraco.Infrastructure.HostedServices HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, IRuntimeState runtimeState, - IServerRegistrar serverRegistrar, + IServerRoleAccessor serverRegistrar, IMainDom mainDom, IScopeProvider scopeProvider, ILogger logger, @@ -87,7 +87,7 @@ namespace Umbraco.Infrastructure.HostedServices return; } - switch (_serverRegistrar.GetCurrentServerRole()) + switch (_serverRegistrar.CurrentServerRole) { case ServerRole.Replica: _logger.LogDebug("Does not run on replica servers."); diff --git a/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs b/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs index 6a56b6f98e..0ec237c6d6 100644 --- a/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs +++ b/src/Umbraco.Infrastructure/HostedServices/KeepAlive.cs @@ -24,7 +24,7 @@ namespace Umbraco.Infrastructure.HostedServices private readonly KeepAliveSettings _keepAliveSettings; private readonly ILogger _logger; private readonly IProfilingLogger _profilingLogger; - private readonly IServerRegistrar _serverRegistrar; + private readonly IServerRoleAccessor _serverRegistrar; private readonly IHttpClientFactory _httpClientFactory; /// @@ -43,7 +43,7 @@ namespace Umbraco.Infrastructure.HostedServices IOptions keepAliveSettings, ILogger logger, IProfilingLogger profilingLogger, - IServerRegistrar serverRegistrar, + IServerRoleAccessor serverRegistrar, IHttpClientFactory httpClientFactory) : base(TimeSpan.FromMinutes(5), DefaultDelay) { @@ -64,7 +64,7 @@ namespace Umbraco.Infrastructure.HostedServices } // Don't run on replicas nor unknown role servers - switch (_serverRegistrar.GetCurrentServerRole()) + switch (_serverRegistrar.CurrentServerRole) { case ServerRole.Replica: _logger.LogDebug("Does not run on replica servers."); diff --git a/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs b/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs index ca87d3e84e..c933ee2470 100644 --- a/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs +++ b/src/Umbraco.Infrastructure/HostedServices/LogScrubber.cs @@ -23,7 +23,7 @@ namespace Umbraco.Infrastructure.HostedServices public class LogScrubber : RecurringHostedServiceBase { private readonly IMainDom _mainDom; - private readonly IServerRegistrar _serverRegistrar; + private readonly IServerRoleAccessor _serverRegistrar; private readonly IAuditService _auditService; private readonly LoggingSettings _settings; private readonly IProfilingLogger _profilingLogger; @@ -42,7 +42,7 @@ namespace Umbraco.Infrastructure.HostedServices /// The profiling logger. public LogScrubber( IMainDom mainDom, - IServerRegistrar serverRegistrar, + IServerRoleAccessor serverRegistrar, IAuditService auditService, IOptions settings, IScopeProvider scopeProvider, @@ -61,7 +61,7 @@ namespace Umbraco.Infrastructure.HostedServices internal override Task PerformExecuteAsync(object state) { - switch (_serverRegistrar.GetCurrentServerRole()) + switch (_serverRegistrar.CurrentServerRole) { case ServerRole.Replica: _logger.LogDebug("Does not run on replica servers."); diff --git a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs index bd73310c29..b42de1add5 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs @@ -27,7 +27,7 @@ namespace Umbraco.Infrastructure.HostedServices private readonly IRuntimeState _runtimeState; private readonly IServerMessenger _serverMessenger; private readonly IBackOfficeSecurityFactory _backofficeSecurityFactory; - private readonly IServerRegistrar _serverRegistrar; + private readonly IServerRoleAccessor _serverRegistrar; private readonly IUmbracoContextFactory _umbracoContextFactory; /// @@ -44,7 +44,7 @@ namespace Umbraco.Infrastructure.HostedServices public ScheduledPublishing( IRuntimeState runtimeState, IMainDom mainDom, - IServerRegistrar serverRegistrar, + IServerRoleAccessor serverRegistrar, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, @@ -69,7 +69,7 @@ namespace Umbraco.Infrastructure.HostedServices return Task.CompletedTask; } - switch (_serverRegistrar.GetCurrentServerRole()) + switch (_serverRegistrar.CurrentServerRole) { case ServerRole.Replica: _logger.LogDebug("Does not run on replica servers."); diff --git a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs index 25e975582d..69f9280fc0 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTask.cs @@ -57,9 +57,7 @@ namespace Umbraco.Infrastructure.HostedServices.ServerRegistration try { - // TouchServer uses a proper unit of work etc underneath so even in a - // background task it is safe to call it without dealing with any scope. - _serverRegistrationService.TouchServer(serverAddress, _serverRegistrationService.CurrentServerIdentity, _globalSettings.DatabaseServerRegistrar.StaleServerTimeout); + _serverRegistrationService.TouchServer(serverAddress, _globalSettings.DatabaseServerRegistrar.StaleServerTimeout); } catch (Exception ex) { diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs index 77385eb2fa..8bc5bcfdff 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs @@ -6,9 +6,9 @@ using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Security; -using Umbraco.Net; using Umbraco.Web.Install.Models; using Umbraco.Web.Security; +using Umbraco.Core.Hosting; namespace Umbraco.Web.Install.InstallSteps { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs index 8428b60fde..a85e52cffe 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Reflection; using System.Threading; using Microsoft.Extensions.Options; @@ -55,6 +55,7 @@ namespace Umbraco.Infrastructure.Logging.Serilog.Enrichers logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ThreadAbortExceptionInfo", message)); } else + { try { var dumped = MiniDump.Dump(_marchal, _hostingEnvironment, withException: true); @@ -68,6 +69,7 @@ namespace Umbraco.Infrastructure.Logging.Serilog.Enrichers message = "Failed to create a minidump. " + ex; logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ThreadAbortExceptionInfo", message)); } + } } private static bool IsTimeoutThreadAbortException(Exception exception) diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs deleted file mode 100644 index 4d8046ee8c..0000000000 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Composing; -using Umbraco.Core.Logging.Serilog.Enrichers; -using Umbraco.Infrastructure.Logging.Serilog.Enrichers; - -namespace Umbraco.Infrastructure.Logging.Serilog -{ - public class SerilogComposer : ICoreComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - } - } -} diff --git a/src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs b/src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs index 145bf54aaf..14197762c6 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs @@ -1,8 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Logging; -using Umbraco.Core.Composing; using Umbraco.Core.Events; using Umbraco.Core.Hosting; using Umbraco.Core.Models; @@ -26,11 +25,12 @@ namespace Umbraco.Core.Services.Implement /// /// Initializes a new instance of the class. /// - /// A UnitOfWork provider. - /// A logger factory - /// - public ServerRegistrationService(IScopeProvider scopeProvider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, - IServerRegistrationRepository serverRegistrationRepository, IHostingEnvironment hostingEnvironment) + public ServerRegistrationService( + IScopeProvider scopeProvider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IServerRegistrationRepository serverRegistrationRepository, + IHostingEnvironment hostingEnvironment) : base(scopeProvider, loggerFactory, eventMessagesFactory) { _serverRegistrationRepository = serverRegistrationRepository; @@ -41,10 +41,10 @@ namespace Umbraco.Core.Services.Implement /// Touches a server to mark it as active; deactivate stale servers. /// /// The server URL. - /// The server unique identity. /// The time after which a server is considered stale. - public void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout) + public void TouchServer(string serverAddress, TimeSpan staleTimeout) { + var serverIdentity = GetCurrentServerIdentity(); using (var scope = ScopeProvider.CreateScope()) { scope.WriteLock(Constants.Locks.Servers); @@ -144,19 +144,16 @@ namespace Umbraco.Core.Services.Implement } } - /// - /// Gets the local server identity. - /// - public string CurrentServerIdentity => NetworkHelper.MachineName // eg DOMAIN\SERVER - + "/" + _hostingEnvironment.ApplicationId; // eg /LM/S3SVC/11/ROOT; - /// /// Gets the role of the current server. /// /// The role of the current server. - public ServerRole GetCurrentServerRole() - { - return _currentServerRole; - } + public ServerRole GetCurrentServerRole() => _currentServerRole; + + /// + /// Gets the local server identity. + /// + private string GetCurrentServerIdentity() => NetworkHelper.MachineName // eg DOMAIN\SERVER + + "/" + _hostingEnvironment.ApplicationId; // eg /LM/S3SVC/11/ROOT; } } diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index 11e1596529..26b1de5080 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Sync private readonly ManualResetEvent _syncIdle; private readonly object _locko = new object(); private readonly IProfilingLogger _profilingLogger; - private readonly IServerRegistrar _serverRegistrar; + private readonly IServerRoleAccessor _serverRegistrar; private readonly IHostingEnvironment _hostingEnvironment; private readonly CacheRefresherCollection _cacheRefreshers; @@ -60,7 +60,7 @@ namespace Umbraco.Core.Sync IScopeProvider scopeProvider, IProfilingLogger proflog, ILogger logger, - IServerRegistrar serverRegistrar, + IServerRoleAccessor serverRegistrar, bool distributedEnabled, DatabaseServerMessengerCallbacks callbacks, IHostingEnvironment hostingEnvironment, @@ -312,7 +312,7 @@ namespace Umbraco.Core.Sync _lastPruned = _lastSync; - switch (_serverRegistrar.GetCurrentServerRole()) + switch (_serverRegistrar.CurrentServerRole) { case ServerRole.Single: case ServerRole.Master: diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs index fb39007bd0..7afb166069 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs @@ -6,13 +6,13 @@ using Microsoft.Extensions.Options; using Umbraco.Configuration; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; using Umbraco.Extensions; using Umbraco.ModelsBuilder.Embedded.BackOffice; -using Umbraco.Net; using Umbraco.Web.Common.Lifetime; using Umbraco.Web.Common.ModelBinders; using Umbraco.Web.WebAssets; diff --git a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs b/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs similarity index 78% rename from src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs rename to src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs index 842a2a8a34..88e0e9f502 100644 --- a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs +++ b/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs @@ -1,72 +1,70 @@ -using Moq; -using NUnit.Framework; using System; -using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Moq; +using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.DependencyInjection; using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Runtime; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Sync; using Umbraco.Core.WebAssets; using Umbraco.Examine; +using Umbraco.Tests.Integration.Implementations; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web.PublishedCache.NuCache; -using Umbraco.Web.Scheduling; using Umbraco.Web.Search; -using Umbraco.Infrastructure.Cache; -namespace Umbraco.Tests.Integration.Testing +namespace Umbraco.Tests.Integration.DependencyInjection { /// /// This is used to replace certain services that are normally registered from our Core / Infrastructure that /// we do not want active within integration tests /// - /// - /// This is a IUserComposer so that it runs after all core composers - /// - public class IntegrationTestComposer : ComponentComposer + public static class UmbracoBuilderExtensions { - // TODO: Kill this and only enable using ext methods what we need (first we need to kill composers) - - public override void Compose(IUmbracoBuilder builder) + /// + /// Uses/Replaces services with testing services + /// + public static IUmbracoBuilder AddTestServices(this IUmbracoBuilder builder, TestHelper testHelper) { - base.Compose(builder); + builder.Services.AddUnique(AppCaches.NoCache); + builder.Services.AddUnique(Mock.Of()); + builder.Services.AddUnique(testHelper.MainDom); builder.Services.AddUnique(); - builder.Services.AddUnique(factory => Mock.Of()); + builder.Services.AddUnique(factory => Mock.Of()); // we don't want persisted nucache files in tests builder.Services.AddTransient(factory => new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }); - #if IS_WINDOWS +#if IS_WINDOWS // ensure all lucene indexes are using RAM directory (no file system) builder.Services.AddUnique(); - #endif +#endif // replace this service so that it can lookup the correct file locations - builder.Services.AddUnique(GetLocalizedTextService); + builder.Services.AddUnique(GetLocalizedTextService); builder.Services.AddUnique(); builder.Services.AddUnique(); + + return builder; } /// /// Used to register a replacement for where the file sources are the ones within the netcore project so /// we don't need to copy files /// - private ILocalizedTextService GetLocalizedTextService(IServiceProvider factory) + private static ILocalizedTextService GetLocalizedTextService(IServiceProvider factory) { var globalSettings = factory.GetRequiredService>(); var loggerFactory = factory.GetRequiredService(); @@ -77,7 +75,7 @@ namespace Umbraco.Tests.Integration.Testing { // get the src folder var currFolder = new DirectoryInfo(TestContext.CurrentContext.TestDirectory); - while(!currFolder.Name.Equals("src", StringComparison.InvariantCultureIgnoreCase)) + while (!currFolder.Name.Equals("src", StringComparison.InvariantCultureIgnoreCase)) { currFolder = currFolder.Parent; } @@ -98,8 +96,8 @@ namespace Umbraco.Tests.Integration.Testing // replace the default so there is no background index rebuilder private class TestBackgroundIndexRebuilder : BackgroundIndexRebuilder { - public TestBackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger profilingLogger , ILoggerFactory loggerFactory, IApplicationShutdownRegistry hostingEnvironment, IndexRebuilder indexRebuilder) - : base(mainDom, profilingLogger , loggerFactory, hostingEnvironment, indexRebuilder) + public TestBackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger profilingLogger, ILoggerFactory loggerFactory, IApplicationShutdownRegistry hostingEnvironment, IndexRebuilder indexRebuilder) + : base(mainDom, profilingLogger, loggerFactory, hostingEnvironment, indexRebuilder) { } diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index fd9ffe5d26..9c2da39076 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -105,7 +105,7 @@ namespace Umbraco.Tests.Integration.Implementations public ILoggerFactory ConsoleLoggerFactory { get; private set; } public IProfilingLogger ProfilingLogger { get; private set; } - public IProfiler Profiler { get; } = new VoidProfiler(); + public IProfiler Profiler { get; } = new NoopProfiler(); public IHttpContextAccessor GetHttpContextAccessor() => _httpContextAccessor; diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 394884a0db..502936a04a 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -37,10 +37,10 @@ namespace Umbraco.Tests.Integration } /// - /// Calling AddUmbracoCore to configure the container and UseUmbracoCore to start the runtime + /// This will boot up umbraco with components enabled to show they initialize and shutdown /// [Test] - public async Task UseUmbracoCore() + public async Task Start_And_Stop_Umbraco_With_Components_Enabled() { var testHelper = new TestHelper(); @@ -70,6 +70,8 @@ namespace Umbraco.Tests.Integration builder.Services.AddUnique(AppCaches.NoCache); builder.AddConfiguration() .AddUmbracoCore() + .AddWebComponents() + .AddComposers() .Build(); services.AddRouting(); // LinkGenerator diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs deleted file mode 100644 index 796f9a8669..0000000000 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Moq; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Runtime; -using Umbraco.Tests.Integration.Implementations; -using Umbraco.Web.Common.DependencyInjection; - -namespace Umbraco.Tests.Integration.TestServerTest -{ - public static class UmbracoBuilderExtensions - { - /// - /// Uses a test version of Umbraco Core with a test IRuntime - /// - public static IUmbracoBuilder AddTestCore(this IUmbracoBuilder builder, TestHelper testHelper) - { - builder.AddUmbracoCore(); - - builder.Services.AddUnique(AppCaches.NoCache); - builder.Services.AddUnique(Mock.Of()); - builder.Services.AddUnique(testHelper.MainDom); - - return builder; - } - } -} diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 017b0ddb45..33c1c28e48 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.DependencyInjection; using Umbraco.Extensions; using Umbraco.Infrastructure.PublishedCache.DependencyInjection; +using Umbraco.Tests.Integration.DependencyInjection; using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -135,7 +136,7 @@ namespace Umbraco.Tests.Integration.TestServerTest builder .AddConfiguration() - .AddTestCore(TestHelper) // This is the important one! + .AddUmbracoCore() .AddWebComponents() .AddRuntimeMinifier() .AddBackOfficeAuthentication() @@ -154,6 +155,7 @@ namespace Umbraco.Tests.Integration.TestServerTest mvcBuilder.AddApplicationPart(typeof(SurfaceController).Assembly); }) .AddWebServer() + .AddTestServices(TestHelper) // This is the important one! .Build(); } diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index d8f27d27a7..21c3cf8304 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -27,8 +27,10 @@ using Umbraco.Core.Strings; using Umbraco.Extensions; using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Integration.DependencyInjection; using Umbraco.Tests.Integration.Extensions; using Umbraco.Tests.Integration.Implementations; +using Umbraco.Tests.Integration.TestServerTest; using Umbraco.Tests.Testing; using Umbraco.Web; using Umbraco.Web.BackOffice.DependencyInjection; @@ -212,7 +214,6 @@ namespace Umbraco.Tests.Integration.Testing TestHelper.Profiler); var builder = new UmbracoBuilder(services, Configuration, typeLoader, TestHelper.ConsoleLoggerFactory); - builder.Services.AddLogger(TestHelper.GetHostingEnvironment(), TestHelper.GetLoggingConfiguration(), Configuration); builder.AddConfiguration() @@ -222,13 +223,14 @@ namespace Umbraco.Tests.Integration.Testing builder.Services.AddUnique(Mock.Of()); builder.Services.AddUnique(TestHelper.MainDom); + //.AddTestServices(TestHelper) + builder.AddWebComponents() + .AddRuntimeMinifier() + .AddBackOfficeAuthentication() + .AddBackOfficeIdentity(); + //.AddComposers(); + services.AddSignalR(); - - builder.AddWebComponents(); - builder.AddRuntimeMinifier(); - builder.AddBackOfficeAuthentication(); - builder.AddBackOfficeIdentity(); - services.AddMvc(); builder.Build(); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs index 706ca94e71..0f16da11c7 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DistributedCache/DistributedCacheTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache.DistributedCache { private global::Umbraco.Web.Cache.DistributedCache _distributedCache; - private IServerRegistrar ServerRegistrar { get; set; } + private IServerRoleAccessor ServerRegistrar { get; set; } private TestServerMessenger ServerMessenger { get; set; } @@ -162,14 +162,14 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache.DistributedCache public void SendMessages() { } } - internal class TestServerRegistrar : IServerRegistrar + internal class TestServerRegistrar : IServerRoleAccessor { public IEnumerable Registrations => new List { new TestServerAddress("localhost") }; - public ServerRole GetCurrentServerRole() => throw new NotImplementedException(); + public ServerRole CurrentServerRole => throw new NotImplementedException(); } public class TestServerAddress : IServerAddress diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs index ffad002928..d5bd10fe3c 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/HealthCheckNotifierTests.cs @@ -138,8 +138,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices var mockRunTimeState = new Mock(); mockRunTimeState.SetupGet(x => x.Level).Returns(runtimeLevel); - var mockServerRegistrar = new Mock(); - mockServerRegistrar.Setup(x => x.GetCurrentServerRole()).Returns(serverRole); + var mockServerRegistrar = new Mock(); + mockServerRegistrar.Setup(x => x.CurrentServerRole).Returns(serverRole); var mockMainDom = new Mock(); mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs index 98164a7aac..752da01f0f 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/KeepAliveTests.cs @@ -81,8 +81,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices var mockRequestAccessor = new Mock(); mockRequestAccessor.Setup(x => x.GetApplicationUrl()).Returns(new Uri(ApplicationUrl)); - var mockServerRegistrar = new Mock(); - mockServerRegistrar.Setup(x => x.GetCurrentServerRole()).Returns(serverRole); + var mockServerRegistrar = new Mock(); + mockServerRegistrar.Setup(x => x.CurrentServerRole).Returns(serverRole); var mockMainDom = new Mock(); mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs index 564b716f75..b7e2f7d80e 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/LogScrubberTests.cs @@ -67,8 +67,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices MaxLogAge = TimeSpan.FromMinutes(MaxLogAgeInMinutes), }; - var mockServerRegistrar = new Mock(); - mockServerRegistrar.Setup(x => x.GetCurrentServerRole()).Returns(serverRole); + var mockServerRegistrar = new Mock(); + mockServerRegistrar.Setup(x => x.CurrentServerRole).Returns(serverRole); var mockMainDom = new Mock(); mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs index fa3a609ce6..17ff9f0c5d 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs @@ -90,8 +90,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices var mockRunTimeState = new Mock(); mockRunTimeState.SetupGet(x => x.Level).Returns(runtimeLevel); - var mockServerRegistrar = new Mock(); - mockServerRegistrar.Setup(x => x.GetCurrentServerRole()).Returns(serverRole); + var mockServerRegistrar = new Mock(); + mockServerRegistrar.Setup(x => x.CurrentServerRole).Returns(serverRole); var mockMainDom = new Mock(); mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs index 7f58f39346..d293a5b7e8 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ServerRegistration/TouchServerTaskTests.cs @@ -21,7 +21,6 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRe private Mock _mockServerRegistrationService; private const string ApplicationUrl = "https://mysite.com/"; - private const string ServerIdentity = "Test/1"; private readonly TimeSpan _staleServerTimeout = TimeSpan.FromMinutes(2); [TestCase(RuntimeLevel.Boot)] @@ -63,8 +62,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRe var mockLogger = new Mock>(); _mockServerRegistrationService = new Mock(); - _mockServerRegistrationService.SetupGet(x => x.CurrentServerIdentity).Returns(ServerIdentity); - + var settings = new GlobalSettings { DatabaseServerRegistrar = new DatabaseServerRegistrarSettings @@ -89,7 +87,6 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRe .Verify( x => x.TouchServer( It.Is(y => y == ApplicationUrl), - It.Is(y => y == ServerIdentity), It.Is(y => y == _staleServerTimeout)), times); } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 4f424f4bb0..71809d063a 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Models; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; +using Umbraco.Core.Hosting; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; @@ -19,7 +20,6 @@ using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Infrastructure.PublishedCache.Persistence; -using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Scoping // FIXME: and we cannot inject a DistributedCache yet // so doing all this mess Builder.Services.AddUnique(); - Builder.Services.AddUnique(f => Mock.Of()); + Builder.Services.AddUnique(f => Mock.Of()); Builder.WithCollectionBuilder() .Add(() => Builder.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index b4009d6f3e..af94f6b2e1 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Scoping // FIXME: and we cannot inject a DistributedCache yet // so doing all this mess Builder.Services.AddUnique(); - Builder.Services.AddUnique(f => Mock.Of()); + Builder.Services.AddUnique(f => Mock.Of()); Builder.WithCollectionBuilder() .Add(() => Builder.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs b/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs index 961ec388f7..d1f5d36b0f 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs @@ -11,7 +11,6 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Models.Packaging; -using Umbraco.Net; using Umbraco.Core.Packaging; using Umbraco.Core.Security; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs index 57ad83d4ba..93347ddaa0 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs @@ -13,10 +13,11 @@ namespace Umbraco.Web.Common.AspNetCore private readonly ConcurrentDictionary _registeredObjects = new ConcurrentDictionary(); + /// + /// Initializes a new instance of the class. + /// public AspNetCoreApplicationShutdownRegistry(IHostApplicationLifetime hostApplicationLifetime) - { - _hostApplicationLifetime = hostApplicationLifetime; - } + => _hostApplicationLifetime = hostApplicationLifetime; public void RegisterObject(IRegisteredObject registeredObject) { @@ -43,17 +44,11 @@ namespace Umbraco.Web.Common.AspNetCore { private readonly IRegisteredObject _inner; - public RegisteredObjectWrapper(IRegisteredObject inner) - { - _inner = inner; - } + public RegisteredObjectWrapper(IRegisteredObject inner) => _inner = inner; public CancellationTokenRegistration CancellationTokenRegistration { get; set; } - public void Stop(bool immediate) - { - _inner.Stop(immediate); - } + public void Stop(bool immediate) => _inner.Stop(immediate); } } } diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs index f34197d23e..cdba8273a0 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs @@ -1,22 +1,21 @@ using System; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; -using Umbraco.Net; +using Umbraco.Core.Hosting; namespace Umbraco.Web.Common.AspNetCore { public class AspNetCoreUmbracoApplicationLifetime : IUmbracoApplicationLifetime, IUmbracoApplicationLifetimeManager { - private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHostApplicationLifetime _hostApplicationLifetime; - public AspNetCoreUmbracoApplicationLifetime(IHttpContextAccessor httpContextAccessor, IHostApplicationLifetime hostApplicationLifetime) + public AspNetCoreUmbracoApplicationLifetime(IHostApplicationLifetime hostApplicationLifetime) { - _httpContextAccessor = httpContextAccessor; _hostApplicationLifetime = hostApplicationLifetime; } public bool IsRestarting { get; set; } + public void Restart() { IsRestarting = true; @@ -27,6 +26,8 @@ namespace Umbraco.Web.Common.AspNetCore { ApplicationInit?.Invoke(this, EventArgs.Empty); } + + // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications public event EventHandler ApplicationInit; } } diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 29e3820637..a2dde620b9 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -88,8 +88,6 @@ namespace Umbraco.Web.Common.DependencyInjection throw new ArgumentNullException(nameof(config)); } - // TODO: Should some/all of these registrations be moved directly into UmbracoBuilder? - IHostingEnvironment tempHostingEnvironment = GetTemporaryHostingEnvironment(webHostEnvironment, config); var loggingDir = tempHostingEnvironment.MapPathContentRoot(Core.Constants.SystemDirectories.LogFiles); @@ -116,6 +114,9 @@ namespace Umbraco.Web.Common.DependencyInjection /// /// Adds core Umbraco services /// + /// + /// This will not add any composers/components + /// public static IUmbracoBuilder AddUmbracoCore(this IUmbracoBuilder builder) { if (builder is null) @@ -142,8 +143,9 @@ namespace Umbraco.Web.Common.DependencyInjection builder.AddCoreInitialServices(); - // TODO: This should be a separate call to opt-in to plugins - builder.AddComposers(); + // aspnet app lifetime mgmt + builder.Services.AddMultipleUnique(); + builder.Services.AddUnique(); return builder; } @@ -232,11 +234,6 @@ namespace Umbraco.Web.Common.DependencyInjection builder.Services.AddUnique(); builder.Services.AddUnique(); - // Our own netcore implementations - builder.Services.AddMultipleUnique(); - - builder.Services.AddUnique(); - // The umbraco request lifetime builder.Services.AddMultipleUnique(); @@ -278,9 +275,11 @@ namespace Umbraco.Web.Common.DependencyInjection builder.Services.AddUnique(); builder.Services.AddUnique(); - builder.AddNuCache(); builder.AddHttpClients(); + // TODO: Does this belong in web components?? + builder.AddNuCache(); + return builder; } @@ -364,7 +363,7 @@ namespace Umbraco.Web.Common.DependencyInjection { // should let it be null, that's how MiniProfiler is meant to work, // but our own IProfiler expects an instance so let's get one - return new VoidProfiler(); + return new NoopProfiler(); } var webProfiler = new WebProfiler(); diff --git a/src/Umbraco.Web.Common/Install/InstallApiController.cs b/src/Umbraco.Web.Common/Install/InstallApiController.cs index 8c32796ad8..6deecc2ce5 100644 --- a/src/Umbraco.Web.Common/Install/InstallApiController.cs +++ b/src/Umbraco.Web.Common/Install/InstallApiController.cs @@ -7,9 +7,9 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; -using Umbraco.Net; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Common.Filters; diff --git a/src/Umbraco.Web.Common/Profiler/WebProfilerComponent.cs b/src/Umbraco.Web.Common/Profiler/WebProfilerComponent.cs index 0c10b7d95a..498b550c1a 100644 --- a/src/Umbraco.Web.Common/Profiler/WebProfilerComponent.cs +++ b/src/Umbraco.Web.Common/Profiler/WebProfilerComponent.cs @@ -4,9 +4,9 @@ using System.Collections.Generic; using Microsoft.Extensions.Logging; using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Net; using Umbraco.Web.Common.Lifetime; using Umbraco.Web.Common.Middleware; +using Umbraco.Core.Hosting; namespace Umbraco.Web.Common.Profiler { @@ -31,7 +31,7 @@ namespace Umbraco.Web.Common.Profiler if (_profiler != null) return; // if VoidProfiler was registered, let it be known - if (profiler is VoidProfiler) + if (profiler is NoopProfiler) logger.LogInformation( "Profiler is VoidProfiler, not profiling (must run debug mode to profile)."); _profile = false; diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComponent.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComponent.cs index 9309bd7e38..5c7e47cf3f 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComponent.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComponent.cs @@ -1,9 +1,9 @@ -using System; +using System; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Net; +using Umbraco.Core.Hosting; using Umbraco.Web.Common.Lifetime; namespace Umbraco.Web.Common.Runtime diff --git a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs index f0ff6e3cad..90261b1a5a 100644 --- a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs @@ -1,7 +1,7 @@ using System; using System.Threading; using System.Web; -using Umbraco.Net; +using Umbraco.Core.Hosting; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index bdf5b40a02..82182e26b7 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -68,10 +68,10 @@ namespace Umbraco.Web { // should let it be null, that's how MiniProfiler is meant to work, // but our own IProfiler expects an instance so let's get one - return new VoidProfiler(); + return new NoopProfiler(); } - return new VoidProfiler(); + return new NoopProfiler(); } protected UmbracoApplicationBase(ILogger logger, ILoggerFactory loggerFactory, SecuritySettings securitySettings, GlobalSettings globalSettings, ConnectionStrings connectionStrings, IIOHelper ioHelper, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) From cc84c866bcb2aac3187ef7a241c0edc9e44808d4 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 16:44:50 +1100 Subject: [PATCH 14/26] moves file --- .../UmbracoBuilder.DistributedCache.cs | 2 +- .../{ => Sync}/BatchedDatabaseServerMessenger.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) rename src/Umbraco.Infrastructure/{ => Sync}/BatchedDatabaseServerMessenger.cs (96%) diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs index 3ad7556c92..54c0feeea0 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Sync; using Umbraco.Infrastructure.Cache; -using Umbraco.Web; +using Umbraco.Core.Sync; using Umbraco.Web.Cache; using Umbraco.Web.PublishedCache; using Umbraco.Web.Search; diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs similarity index 96% rename from src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs rename to src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs index 6900354202..c265461c99 100644 --- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs @@ -12,8 +12,9 @@ using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Scoping; using Umbraco.Core.Sync; +using Umbraco.Web; -namespace Umbraco.Web +namespace Umbraco.Core.Sync { /// /// An implementation that works by storing messages in the database. @@ -61,7 +62,8 @@ namespace Umbraco.Web public override void SendMessages() { var batch = GetBatch(false); - if (batch == null) return; + if (batch == null) + return; var instructions = batch.SelectMany(x => x.Instructions).ToArray(); batch.Clear(); @@ -95,7 +97,8 @@ namespace Umbraco.Web { var key = nameof(BatchedDatabaseServerMessenger); - if (!_requestCache.IsAvailable) return null; + if (!_requestCache.IsAvailable) + return null; // no thread-safety here because it'll run in only 1 thread (request) at a time var batch = (ICollection)_requestCache.Get(key); From 1a0d961e42cf6831cb215b8f577c44fbbc738327 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 24 Dec 2020 18:11:16 +1100 Subject: [PATCH 15/26] removes WebsiteComposer, BackOfficeComposer --- src/Umbraco.Core/Composing/Composers.cs | 3 +- .../ComponentRuntimeTests.cs | 76 ++++++++++ .../UmbracoBuilderExtensions.cs | 4 +- src/Umbraco.Tests.Integration/RuntimeTests.cs | 132 ------------------ .../UmbracoTestServerTestBase.cs | 1 + .../Testing/UmbracoIntegrationTest.cs | 17 +-- .../UmbracoBuilderExtensions.cs | 54 ++++++- .../Runtime/BackOfficeComposer.cs | 64 --------- .../Runtime/AspNetCoreComposer.cs | 27 ---- src/Umbraco.Web.UI.NetCore/Startup.cs | 1 + .../UmbracoBuilderExtensions.cs | 7 + .../Runtime/WebsiteComposer.cs | 24 ---- 12 files changed, 147 insertions(+), 263 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/ComponentRuntimeTests.cs delete mode 100644 src/Umbraco.Tests.Integration/RuntimeTests.cs delete mode 100644 src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs delete mode 100644 src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs diff --git a/src/Umbraco.Core/Composing/Composers.cs b/src/Umbraco.Core/Composing/Composers.cs index 47f272cbf4..91c8244324 100644 --- a/src/Umbraco.Core/Composing/Composers.cs +++ b/src/Umbraco.Core/Composing/Composers.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -70,7 +70,6 @@ namespace Umbraco.Core.Composing foreach (var composer in composers) { - var componentType = composer.GetType(); composer.Compose(_builder); } } diff --git a/src/Umbraco.Tests.Integration/ComponentRuntimeTests.cs b/src/Umbraco.Tests.Integration/ComponentRuntimeTests.cs new file mode 100644 index 0000000000..ba6c6473fa --- /dev/null +++ b/src/Umbraco.Tests.Integration/ComponentRuntimeTests.cs @@ -0,0 +1,76 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.DependencyInjection; +using Umbraco.Extensions; +using Umbraco.Infrastructure.PublishedCache.DependencyInjection; +using Umbraco.Tests.Integration.Extensions; +using Umbraco.Tests.Integration.Implementations; +using Umbraco.Tests.Integration.Testing; +using Umbraco.Tests.Testing; +using Umbraco.Web.Common.DependencyInjection; + +namespace Umbraco.Tests.Integration +{ + + [TestFixture] + [UmbracoTest(Boot = true)] + public class ComponentRuntimeTests : UmbracoIntegrationTest + { + // ensure composers are added + protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddComposers(); + + /// + /// This will boot up umbraco with components enabled to show they initialize and shutdown + /// + [Test] + public async Task Start_And_Stop_Umbraco_With_Components_Enabled() + { + IRuntime runtime = Services.GetRequiredService(); + IRuntimeState runtimeState = Services.GetRequiredService(); + IMainDom mainDom = Services.GetRequiredService(); + ComponentCollection components = Services.GetRequiredService(); + + MyComponent myComponent = components.OfType().First(); + + Assert.IsTrue(mainDom.IsMainDom); + Assert.IsNull(runtimeState.BootFailedException); + Assert.IsTrue(myComponent.IsInit, "The component was not initialized"); + + // force stop now + await runtime.StopAsync(CancellationToken.None); + Assert.IsTrue(myComponent.IsTerminated, "The component was not terminated"); + } + + public class MyComposer : IUserComposer + { + public void Compose(IUmbracoBuilder builder) => builder.Components().Append(); + } + + public class MyComponent : IComponent + { + public bool IsInit { get; private set; } + + public bool IsTerminated { get; private set; } + + private readonly ILogger _logger; + + public MyComponent(ILogger logger) => _logger = logger; + + public void Initialize() => IsInit = true; + + public void Terminate() => IsTerminated = true; + + } + } +} diff --git a/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs index 88e0e9f502..c1bdf19069 100644 --- a/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs @@ -34,9 +34,9 @@ namespace Umbraco.Tests.Integration.DependencyInjection /// /// Uses/Replaces services with testing services /// - public static IUmbracoBuilder AddTestServices(this IUmbracoBuilder builder, TestHelper testHelper) + public static IUmbracoBuilder AddTestServices(this IUmbracoBuilder builder, TestHelper testHelper, AppCaches appCaches = null) { - builder.Services.AddUnique(AppCaches.NoCache); + builder.Services.AddUnique(appCaches ?? AppCaches.NoCache); builder.Services.AddUnique(Mock.Of()); builder.Services.AddUnique(testHelper.MainDom); diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs deleted file mode 100644 index 502936a04a..0000000000 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.DependencyInjection; -using Umbraco.Extensions; -using Umbraco.Infrastructure.PublishedCache.DependencyInjection; -using Umbraco.Tests.Integration.Extensions; -using Umbraco.Tests.Integration.Implementations; -using Umbraco.Web.Common.DependencyInjection; - -namespace Umbraco.Tests.Integration -{ - - [TestFixture] - public class RuntimeTests - { - [TearDown] - public void TearDown() - { - MyComponent.Reset(); - MyComposer.Reset(); - } - - [SetUp] - public void Setup() - { - MyComponent.Reset(); - MyComposer.Reset(); - } - - /// - /// This will boot up umbraco with components enabled to show they initialize and shutdown - /// - [Test] - public async Task Start_And_Stop_Umbraco_With_Components_Enabled() - { - var testHelper = new TestHelper(); - - IHostBuilder hostBuilder = new HostBuilder() - .ConfigureServices((hostContext, services) => - { - IWebHostEnvironment webHostEnvironment = testHelper.GetWebHostEnvironment(); - services.AddSingleton(testHelper.DbProviderFactoryCreator); - services.AddRequiredNetCoreServices(testHelper, webHostEnvironment); - - // Add it! - TypeLoader typeLoader = services.AddTypeLoader( - GetType().Assembly, - webHostEnvironment, - testHelper.GetHostingEnvironment(), - testHelper.ConsoleLoggerFactory, - AppCaches.NoCache, - hostContext.Configuration, - testHelper.Profiler); - - var builder = new UmbracoBuilder( - services, - hostContext.Configuration, - typeLoader, - testHelper.ConsoleLoggerFactory); - - builder.Services.AddUnique(AppCaches.NoCache); - builder.AddConfiguration() - .AddUmbracoCore() - .AddWebComponents() - .AddComposers() - .Build(); - - services.AddRouting(); // LinkGenerator - }); - - IHost host = await hostBuilder.StartAsync(); - var app = new ApplicationBuilder(host.Services); - - app.UseUmbracoCore(); - - // assert results - IRuntimeState runtimeState = app.ApplicationServices.GetRequiredService(); - IMainDom mainDom = app.ApplicationServices.GetRequiredService(); - - Assert.IsTrue(mainDom.IsMainDom); - Assert.IsNull(runtimeState.BootFailedException); - Assert.IsTrue(MyComponent.IsInit); - - await host.StopAsync(); - - Assert.IsTrue(MyComponent.IsTerminated); - } - - public class MyComposer : IUserComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Components().Append(); - IsComposed = true; - } - - public static void Reset() => IsComposed = false; - - public static bool IsComposed { get; private set; } - } - - public class MyComponent : IComponent - { - public static bool IsInit { get; private set; } - - public static bool IsTerminated { get; private set; } - - private readonly ILogger _logger; - - public MyComponent(ILogger logger) => _logger = logger; - - public void Initialize() => IsInit = true; - - public void Terminate() => IsTerminated = true; - - public static void Reset() - { - IsTerminated = false; - IsInit = false; - } - } - } -} diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 33c1c28e48..27209182fe 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -139,6 +139,7 @@ namespace Umbraco.Tests.Integration.TestServerTest .AddUmbracoCore() .AddWebComponents() .AddRuntimeMinifier() + .AddBackOfficeCore() .AddBackOfficeAuthentication() .AddBackOfficeIdentity() .AddBackOfficeAuthorizationPolicies(TestAuthHandler.TestAuthenticationScheme) diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 21c3cf8304..17778f986c 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -217,25 +217,20 @@ namespace Umbraco.Tests.Integration.Testing builder.Services.AddLogger(TestHelper.GetHostingEnvironment(), TestHelper.GetLoggingConfiguration(), Configuration); builder.AddConfiguration() - .AddUmbracoCore(); - - builder.Services.AddUnique(GetAppCaches()); - builder.Services.AddUnique(Mock.Of()); - builder.Services.AddUnique(TestHelper.MainDom); - - //.AddTestServices(TestHelper) - builder.AddWebComponents() + .AddUmbracoCore() + .AddWebComponents() .AddRuntimeMinifier() .AddBackOfficeAuthentication() - .AddBackOfficeIdentity(); + .AddBackOfficeIdentity() + .AddTestServices(TestHelper, GetAppCaches()); //.AddComposers(); services.AddSignalR(); services.AddMvc(); - builder.Build(); - CustomTestSetup(builder); + + builder.Build(); } protected virtual AppCaches GetAppCaches() diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index 30e6bdcbc7..fb2cbfb607 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -1,11 +1,21 @@ using System; +using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Core.Services; +using Umbraco.Extensions; using Umbraco.Infrastructure.DependencyInjection; -using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Web.BackOffice.Authorization; +using Umbraco.Web.BackOffice.Controllers; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Middleware; +using Umbraco.Web.BackOffice.Routing; using Umbraco.Web.BackOffice.Security; +using Umbraco.Web.BackOffice.Services; using Umbraco.Web.BackOffice.Trees; using Umbraco.Web.Common.Authorization; using Umbraco.Web.Common.DependencyInjection; @@ -25,6 +35,7 @@ namespace Umbraco.Web.BackOffice.DependencyInjection .AddUmbracoCore() .AddWebComponents() .AddRuntimeMinifier() + .AddBackOfficeCore() .AddBackOfficeAuthentication() .AddBackOfficeIdentity() .AddBackOfficeAuthorizationPolicies() @@ -64,6 +75,11 @@ namespace Umbraco.Web.BackOffice.DependencyInjection }); builder.Services.ConfigureOptions(); + + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + return builder; } @@ -117,5 +133,41 @@ namespace Umbraco.Web.BackOffice.DependencyInjection /// public static TreeCollectionBuilder Trees(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + + public static IUmbracoBuilder AddBackOfficeCore(this IUmbracoBuilder builder) + { + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + + // register back office trees + // the collection builder only accepts types inheriting from TreeControllerBase + // and will filter out those that are not attributed with TreeAttribute + var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); + builder.Trees() + .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); + + builder.ComposeWebMappingProfiles(); + + builder.Services.AddUnique(factory => + { + var path = "~/"; + var hostingEnvironment = factory.GetRequiredService(); + return new PhysicalFileSystem( + factory.GetRequiredService(), + hostingEnvironment, + factory.GetRequiredService>(), + hostingEnvironment.MapPathContentRoot(path), + hostingEnvironment.ToAbsolute(path) + ); + }); + + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + return builder; + } } } diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs deleted file mode 100644 index d933d00d68..0000000000 --- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Umbraco.Core.Composing; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Services; -using Umbraco.Extensions; -using Umbraco.Web.BackOffice.Controllers; -using Umbraco.Web.BackOffice.DependencyInjection; -using Umbraco.Web.BackOffice.Filters; -using Umbraco.Web.BackOffice.Middleware; -using Umbraco.Web.BackOffice.Routing; -using Umbraco.Web.BackOffice.Security; -using Umbraco.Web.BackOffice.Services; -using Umbraco.Web.BackOffice.Trees; -using Umbraco.Web.Common.Runtime; - -namespace Umbraco.Web.BackOffice.Runtime -{ - [ComposeBefore(typeof(ICoreComposer))] - [ComposeAfter(typeof(AspNetCoreComposer))] - public class BackOfficeComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - builder.Services.AddUnique(); - - // register back office trees - // the collection builder only accepts types inheriting from TreeControllerBase - // and will filter out those that are not attributed with TreeAttribute - var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); - builder.Trees() - .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); - - builder.ComposeWebMappingProfiles(); - - builder.Services.AddUnique(factory => - { - var path = "~/"; - var hostingEnvironment = factory.GetRequiredService(); - return new PhysicalFileSystem( - factory.GetRequiredService(), - hostingEnvironment, - factory.GetRequiredService>(), - hostingEnvironment.MapPathContentRoot(path), - hostingEnvironment.ToAbsolute(path) - ); - }); - - builder.Services.AddUnique(); - builder.Services.AddUnique(); - } - } -} diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index 34a8b7583a..1eda1cc23a 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -1,31 +1,4 @@ -using System.Linq; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core; -using Umbraco.Core.DependencyInjection; using Umbraco.Core.Composing; -using Umbraco.Core.Diagnostics; -using Umbraco.Core.Hosting; -using Umbraco.Core.Logging; -using Umbraco.Core.Security; -using Umbraco.Extensions; -using Umbraco.Net; -using Umbraco.Web.Common.AspNetCore; -using Umbraco.Web.Common.Controllers; -using Umbraco.Web.Common.Install; -using Umbraco.Web.Common.Lifetime; -using Umbraco.Web.Common.Macros; -using Umbraco.Web.Common.Middleware; -using Umbraco.Web.Common.Profiler; -using Umbraco.Web.Common.Routing; -using Umbraco.Web.Common.Security; -using Umbraco.Web.Common.Templates; -using Umbraco.Web.Macros; -using Umbraco.Web.Security; -using Umbraco.Web.Templates; -using Umbraco.Web.Common.ModelBinders; -using Umbraco.Infrastructure.DependencyInjection; - namespace Umbraco.Web.Common.Runtime { diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index 75212e3077..a09b850d98 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -46,6 +46,7 @@ namespace Umbraco.Web.UI.NetCore services.AddUmbraco(_env, _config) .AddBackOffice() .AddWebsite() + .AddComposers() .Build(); #pragma warning restore IDE0022 // Use expression body for methods diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 5762a5fb69..52f6d5df11 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -2,8 +2,10 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Core.DependencyInjection; +using Umbraco.Extensions; using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.PublishedCache.DependencyInjection; +using Umbraco.Web.Website.Collections; using Umbraco.Web.Website.Controllers; using Umbraco.Web.Website.Routing; using Umbraco.Web.Website.ViewEngines; @@ -20,6 +22,11 @@ namespace Umbraco.Web.Website.DependencyInjection /// public static IUmbracoBuilder AddWebsite(this IUmbracoBuilder builder) { + builder.Services.AddUnique(); + + builder.WithCollectionBuilder() + .Add(builder.TypeLoader.GetSurfaceControllers()); + // Set the render & plugin view engines (Super complicated, but this allows us to use the IServiceCollection // to inject dependencies into the viewEngines) builder.Services.AddTransient, RenderMvcViewOptionsSetup>(); diff --git a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs deleted file mode 100644 index 2a4b85a0df..0000000000 --- a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Composing; -using Umbraco.Extensions; -using Umbraco.Web.Website.Routing; -using Umbraco.Web.Common.Runtime; -using Umbraco.Web.Website.Collections; - -namespace Umbraco.Web.Website.Runtime -{ - // web's initial composer composes after core's, and before all core composers - [ComposeBefore(typeof(ICoreComposer))] - [ComposeAfter(typeof(AspNetCoreComposer))] - public class WebsiteComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - - builder.WithCollectionBuilder() - .Add(builder.TypeLoader.GetSurfaceControllers()); - } - } -} - From 4ce5dc8eff552d5c67c48f09259f7644335f67b9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 11:32:36 +1100 Subject: [PATCH 16/26] fixing tests --- .../DependencyInjection/UmbracoBuilder.Events.cs | 5 +++-- .../TestServerTest/UmbracoTestServerTestBase.cs | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs index d5090de01b..138fa9bf9c 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs @@ -24,8 +24,9 @@ namespace Umbraco.Core.DependencyInjection where TNotification : INotification { // Register the handler as transient. This ensures that anything can be injected into it. - // TODO: Waiting on feedback here https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 - builder.Services.TryAddTransient(typeof(INotificationHandler), typeof(TNotificationHandler)); + // TODO: Waiting on feedback here for TryAddTransient https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 + // ... though this will fail tests so it's not the final answer so we'll see where that discussion goes. + builder.Services.AddTransient(typeof(INotificationHandler), typeof(TNotificationHandler)); return builder; } } diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 27209182fe..5a704c2b5d 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -25,6 +25,7 @@ using Umbraco.Web.BackOffice.DependencyInjection; using Umbraco.Web.Common.Controllers; using Umbraco.Web.Common.DependencyInjection; using Umbraco.Web.Website.Controllers; +using Umbraco.Web.Website.DependencyInjection; namespace Umbraco.Tests.Integration.TestServerTest { @@ -156,6 +157,7 @@ namespace Umbraco.Tests.Integration.TestServerTest mvcBuilder.AddApplicationPart(typeof(SurfaceController).Assembly); }) .AddWebServer() + .AddWebsite() .AddTestServices(TestHelper) // This is the important one! .Build(); } From 2848f4083b2e672256bbb15ccd44042125e4d76e Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 12:01:52 +1100 Subject: [PATCH 17/26] notes - why isn't this building? --- .../DependencyInjection/UmbracoBuilder.Configuration.cs | 7 ------- .../Extensions/ApplicationBuilderExtensions.cs | 3 +++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs index 1733536908..a31a44beeb 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs @@ -1,12 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.Models.Validation; diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs index 5c7c4ee713..5dee7d10e1 100644 --- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs @@ -28,6 +28,9 @@ namespace Umbraco.Extensions /// public static IApplicationBuilder UseUmbraco(this IApplicationBuilder app) { + // TODO: Should we do some checks like this to verify that the corresponding "Add" methods have been called for the + // corresponding "Use" methods? + // https://github.com/dotnet/aspnetcore/blob/b795ac3546eb3e2f47a01a64feb3020794ca33bb/src/Mvc/Mvc.Core/src/Builder/MvcApplicationBuilderExtensions.cs#L132 if (app == null) { throw new ArgumentNullException(nameof(app)); From 999c20a75576be4df86f0b51d109c30648884b94 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 12:22:03 +1100 Subject: [PATCH 18/26] Fixes UmbracoIntegrationTest Mapping flag and missing using in Startup --- .../Testing/UmbracoIntegrationTest.cs | 10 +++++++++- .../Umbraco.Core/Mapping/UmbracoMapperTests.cs | 2 +- .../DependencyInjection/UmbracoBuilderExtensions.cs | 2 +- .../Extensions/WebMappingProfiles.cs | 2 +- src/Umbraco.Web.UI.NetCore/Startup.cs | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 17778f986c..885668acca 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -25,6 +25,7 @@ using Umbraco.Core.Runtime; using Umbraco.Core.Scoping; using Umbraco.Core.Strings; using Umbraco.Extensions; +using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Integration.DependencyInjection; @@ -223,7 +224,14 @@ namespace Umbraco.Tests.Integration.Testing .AddBackOfficeAuthentication() .AddBackOfficeIdentity() .AddTestServices(TestHelper, GetAppCaches()); - //.AddComposers(); + + if (TestOptions.Mapper) + { + // TODO: Should these just be called from within AddUmbracoCore/AddWebComponents? + builder + .AddCoreMappingProfiles() + .AddWebMappingProfiles(); + } services.AddSignalR(); services.AddMvc(); diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs index 4028889b01..244e8c8d1a 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; using System.Linq; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index fb2cbfb607..0d12fae687 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -149,7 +149,7 @@ namespace Umbraco.Web.BackOffice.DependencyInjection builder.Trees() .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); - builder.ComposeWebMappingProfiles(); + builder.AddWebMappingProfiles(); builder.Services.AddUnique(factory => { diff --git a/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs b/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs index eeb0903e88..f66c175f29 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs @@ -7,7 +7,7 @@ namespace Umbraco.Extensions { public static class WebMappingProfiles { - public static IUmbracoBuilder ComposeWebMappingProfiles(this IUmbracoBuilder builder) + public static IUmbracoBuilder AddWebMappingProfiles(this IUmbracoBuilder builder) { builder.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index a09b850d98..46f7b2d7ae 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Umbraco.Core.DependencyInjection; using Umbraco.Extensions; using Umbraco.Web.BackOffice.DependencyInjection; using Umbraco.Web.BackOffice.Security; From cf9dd9bfeca897ec2dc93c552cb4f5c7e4a4bec0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 12:48:59 +1100 Subject: [PATCH 19/26] Adds notes, another hacky fix for hacky test/code --- .../Cache/DatabaseServerMessengerNotificationHandler.cs | 5 ++++- .../DependencyInjection/UmbracoBuilder.DistributedCache.cs | 5 ----- .../Umbraco.Infrastructure/Services/ContentServiceTests.cs | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs index c8d8c81ab1..5b4dd4f0ed 100644 --- a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs +++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs @@ -70,7 +70,10 @@ namespace Umbraco.Infrastructure.Cache } // TODO: I don't really know or think that the Application Url plays a role anymore with the DB dist cache, - // this might be really old stuff + // this might be really old stuff. I 'think' all this is doing is ensuring that the IRequestAccessor.GetApplicationUrl + // is definitely called during the first request. If that is still required, that logic doesn't belong here. That logic + // should be part of it's own service/middleware. There's also TODO notes within IRequestAccessor.GetApplicationUrl directly + // mentioning that the property doesn't belong on that service either. This should be investigated and resolved in a separate task. private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e) { if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest) diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs index 54c0feeea0..db1d22e86c 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs @@ -1,15 +1,10 @@ using System; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Umbraco.Core; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; -using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Sync; using Umbraco.Infrastructure.Cache; -using Umbraco.Core.Sync; using Umbraco.Web.Cache; using Umbraco.Web.PublishedCache; using Umbraco.Web.Search; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServiceTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServiceTests.cs index c9f8dc5391..10fe206290 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServiceTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -2283,7 +2283,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services // This sleep ensures the save is called on later ticks then the SetValue and SetCultureName. Therefore // we showcase the currect lack of handling dirty on variants on save. When this is implemented the sleep // helps showcase the functionality is actually working - Thread.Sleep(1); + Thread.Sleep(5); ContentService.Save(page); var versionId5 = page.VersionId; From d1d664c44952f2cdd3e2b820f86ed982ccba07c9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 12:51:13 +1100 Subject: [PATCH 20/26] removes unneeded cast --- .../HostedServices/ServerRegistration/InstructionProcessTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs index f3d970d2b0..8b194e32ef 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ServerRegistration/InstructionProcessTask.cs @@ -31,7 +31,7 @@ namespace Umbraco.Infrastructure.HostedServices.ServerRegistration : base(globalSettings.Value.DatabaseServerMessenger.TimeBetweenSyncOperations, TimeSpan.FromMinutes(1)) { _runtimeState = runtimeState; - _messenger = messenger as IServerMessenger ?? throw new ArgumentNullException(nameof(messenger)); + _messenger = messenger; _logger = logger; } From cbc08fb00879315b6191c9da0688695425c8180d Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 12:56:44 +1100 Subject: [PATCH 21/26] notes/cleanup --- .../Sync/BatchedDatabaseServerMessenger.cs | 40 ++++++++++--------- .../Sync/DatabaseServerMessenger.cs | 5 +-- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs index c265461c99..d1a9481f47 100644 --- a/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/BatchedDatabaseServerMessenger.cs @@ -4,14 +4,12 @@ using System.Linq; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Scoping; -using Umbraco.Core.Sync; using Umbraco.Web; namespace Umbraco.Core.Sync @@ -19,9 +17,6 @@ namespace Umbraco.Core.Sync /// /// An implementation that works by storing messages in the database. /// - /// - /// This binds to appropriate umbraco events in order to trigger the Boot(), Sync() & FlushBatch() calls - /// public class BatchedDatabaseServerMessenger : DatabaseServerMessenger { private readonly IRequestCache _requestCache; @@ -48,37 +43,41 @@ namespace Umbraco.Core.Sync _requestAccessor = requestAccessor; } + /// protected override void DeliverRemote(ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) { var idsA = ids?.ToArray(); - Type arrayType; - if (GetArrayType(idsA, out arrayType) == false) + if (GetArrayType(idsA, out Type arrayType) == false) + { throw new ArgumentException("All items must be of the same type, either int or Guid.", nameof(ids)); + } BatchMessage(refresher, messageType, idsA, arrayType, json); } + /// public override void SendMessages() { - var batch = GetBatch(false); + ICollection batch = GetBatch(false); if (batch == null) + { return; + } - var instructions = batch.SelectMany(x => x.Instructions).ToArray(); + RefreshInstruction[] instructions = batch.SelectMany(x => x.Instructions).ToArray(); batch.Clear(); // Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount - using (var scope = ScopeProvider.CreateScope()) + using (IScope scope = ScopeProvider.CreateScope()) { - foreach (var instructionsBatch in instructions.InGroupsOf(GlobalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) + foreach (IEnumerable instructionsBatch in instructions.InGroupsOf(GlobalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) { WriteInstructions(scope, instructionsBatch); } scope.Complete(); } - } private void WriteInstructions(IScope scope, IEnumerable instructions) @@ -93,12 +92,14 @@ namespace Umbraco.Core.Sync scope.Database.Insert(dto); } - protected ICollection GetBatch(bool create) + private ICollection GetBatch(bool create) { var key = nameof(BatchedDatabaseServerMessenger); if (!_requestCache.IsAvailable) + { return null; + } // no thread-safety here because it'll run in only 1 thread (request) at a time var batch = (ICollection)_requestCache.Get(key); @@ -111,26 +112,27 @@ namespace Umbraco.Core.Sync return batch; } - protected void BatchMessage( + private void BatchMessage( ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, Type idType = null, string json = null) { - var batch = GetBatch(true); - var instructions = RefreshInstruction.GetInstructions(refresher, messageType, ids, idType, json); + ICollection batch = GetBatch(true); + IEnumerable instructions = RefreshInstruction.GetInstructions(refresher, messageType, ids, idType, json); // batch if we can, else write to DB immediately if (batch == null) { - //only write the json blob with a maximum count of the MaxProcessingInstructionCount - using (var scope = ScopeProvider.CreateScope()) + // only write the json blob with a maximum count of the MaxProcessingInstructionCount + using (IScope scope = ScopeProvider.CreateScope()) { - foreach (var maxBatch in instructions.InGroupsOf(GlobalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) + foreach (IEnumerable maxBatch in instructions.InGroupsOf(GlobalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) { WriteInstructions(scope, maxBatch); } + scope.Complete(); } } diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index 26b1de5080..09c90461ac 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -25,9 +25,6 @@ namespace Umbraco.Core.Sync /// public abstract class DatabaseServerMessenger : ServerMessengerBase { - // TODO: This class is never used directly, only BatchedDatabaseServerMessenger is used so - // this could/should be combined with that or made abstract and/or just cleaned up. - // TODO: This class needs to be split into a service/repo for DB access /* @@ -55,7 +52,7 @@ namespace Umbraco.Core.Sync /// /// Initializes a new instance of the class. /// - public DatabaseServerMessenger( + protected DatabaseServerMessenger( IMainDom mainDom, IScopeProvider scopeProvider, IProfilingLogger proflog, From d46545faa01a3a8f0a7dad086de6888ccdaf0e8e Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 13:01:49 +1100 Subject: [PATCH 22/26] For now, we explicitly require AddDistributedCache in Startup so it's not called twice. --- .../DependencyInjection/UmbracoBuilderExtensions.cs | 3 +-- src/Umbraco.Web.UI.NetCore/Startup.cs | 2 ++ .../DependencyInjection/UmbracoBuilderExtensions.cs | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index 0d12fae687..6bb75e774a 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -43,8 +43,7 @@ namespace Umbraco.Web.BackOffice.DependencyInjection .AddMvcAndRazor() .AddWebServer() .AddPreviewSupport() - .AddHostedServices() - .AddDistributedCache(); + .AddHostedServices(); /// /// Adds Umbraco back office authentication requirements diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index 46f7b2d7ae..5b262098e6 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Umbraco.Core.DependencyInjection; using Umbraco.Extensions; +using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Web.BackOffice.DependencyInjection; using Umbraco.Web.BackOffice.Security; using Umbraco.Web.Common.DependencyInjection; @@ -47,6 +48,7 @@ namespace Umbraco.Web.UI.NetCore services.AddUmbraco(_env, _config) .AddBackOffice() .AddWebsite() + .AddDistributedCache() .AddComposers() .Build(); #pragma warning restore IDE0022 // Use expression body for methods diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 52f6d5df11..41292b9415 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -43,8 +43,6 @@ namespace Umbraco.Web.Website.DependencyInjection builder.Services.AddScoped(); builder.Services.AddSingleton(); - builder.AddDistributedCache(); - return builder; } From 34427b010434e73c56a9cb5fb21060f1f6e8cc24 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 13:22:29 +1100 Subject: [PATCH 23/26] Moves AddDistributed cache back to being called implicitly, ensures notification handlers are not added twice --- .../DependencyInjection/UmbracoBuilder.Events.cs | 12 +++++++++--- .../Umbraco.Core/Events/EventAggregatorTests.cs | 1 + .../DependencyInjection/UmbracoBuilderExtensions.cs | 3 ++- src/Umbraco.Web.UI.NetCore/Startup.cs | 2 -- .../DependencyInjection/UmbracoBuilderExtensions.cs | 2 ++ 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs index 138fa9bf9c..c24936b4fb 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs @@ -24,9 +24,15 @@ namespace Umbraco.Core.DependencyInjection where TNotification : INotification { // Register the handler as transient. This ensures that anything can be injected into it. - // TODO: Waiting on feedback here for TryAddTransient https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 - // ... though this will fail tests so it's not the final answer so we'll see where that discussion goes. - builder.Services.AddTransient(typeof(INotificationHandler), typeof(TNotificationHandler)); + var descriptor = new ServiceDescriptor(typeof(INotificationHandler), typeof(TNotificationHandler), ServiceLifetime.Transient); + + // TODO: Waiting on feedback here https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 about whether + // we perform this duplicate check or not. + if (!builder.Services.Contains(descriptor)) + { + builder.Services.Add(descriptor); + } + return builder; } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Events/EventAggregatorTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Events/EventAggregatorTests.cs index 08d78af59e..cbf3d02542 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Events/EventAggregatorTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Events/EventAggregatorTests.cs @@ -13,6 +13,7 @@ using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Events { + [TestFixture] public class EventAggregatorTests { private const int A = 3; diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index 6bb75e774a..0d12fae687 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -43,7 +43,8 @@ namespace Umbraco.Web.BackOffice.DependencyInjection .AddMvcAndRazor() .AddWebServer() .AddPreviewSupport() - .AddHostedServices(); + .AddHostedServices() + .AddDistributedCache(); /// /// Adds Umbraco back office authentication requirements diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index 5b262098e6..46f7b2d7ae 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -6,7 +6,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Umbraco.Core.DependencyInjection; using Umbraco.Extensions; -using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Web.BackOffice.DependencyInjection; using Umbraco.Web.BackOffice.Security; using Umbraco.Web.Common.DependencyInjection; @@ -48,7 +47,6 @@ namespace Umbraco.Web.UI.NetCore services.AddUmbraco(_env, _config) .AddBackOffice() .AddWebsite() - .AddDistributedCache() .AddComposers() .Build(); #pragma warning restore IDE0022 // Use expression body for methods diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 41292b9415..52f6d5df11 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -43,6 +43,8 @@ namespace Umbraco.Web.Website.DependencyInjection builder.Services.AddScoped(); builder.Services.AddSingleton(); + builder.AddDistributedCache(); + return builder; } From a6f281789b53722a958acaff409521d0ab244bd5 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 13:29:13 +1100 Subject: [PATCH 24/26] Add explicit package sources --- NuGet.Config | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/NuGet.Config b/NuGet.Config index d6c63173f8..92eaf83792 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,13 +1,15 @@  - - - - - - + + + + + + + From a126977a4e0b6296afa33b782272103b2b983f87 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Jan 2021 15:43:30 +1100 Subject: [PATCH 25/26] Simplifies how view locations are determined AB#9720 --- .../UmbracoBuilderExtensions.cs | 10 +- .../ViewEngines/IPluginViewEngine.cs | 8 -- .../ViewEngines/IRenderViewEngine.cs | 8 -- .../ViewEngines/PluginMvcViewOptionsSetup.cs | 26 ----- .../PluginRazorViewEngineOptionsSetup.cs | 52 ++++++++++ .../ViewEngines/PluginViewEngine.cs | 52 ---------- ...ingViewEngineWrapperMvcViewOptionsSetup.cs | 24 +++-- .../ViewEngines/RenderMvcViewOptionsSetup.cs | 26 ----- .../RenderRazorViewEngineOptionsSetup.cs | 48 ++++++++++ .../ViewEngines/RenderViewEngine.cs | 94 ------------------- 10 files changed, 120 insertions(+), 228 deletions(-) delete mode 100644 src/Umbraco.Web.Website/ViewEngines/IPluginViewEngine.cs delete mode 100644 src/Umbraco.Web.Website/ViewEngines/IRenderViewEngine.cs delete mode 100644 src/Umbraco.Web.Website/ViewEngines/PluginMvcViewOptionsSetup.cs create mode 100644 src/Umbraco.Web.Website/ViewEngines/PluginRazorViewEngineOptionsSetup.cs delete mode 100644 src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs delete mode 100644 src/Umbraco.Web.Website/ViewEngines/RenderMvcViewOptionsSetup.cs create mode 100644 src/Umbraco.Web.Website/ViewEngines/RenderRazorViewEngineOptionsSetup.cs delete mode 100644 src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 52f6d5df11..64d7cd0205 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Core.DependencyInjection; @@ -27,12 +28,9 @@ namespace Umbraco.Web.Website.DependencyInjection builder.WithCollectionBuilder() .Add(builder.TypeLoader.GetSurfaceControllers()); - // Set the render & plugin view engines (Super complicated, but this allows us to use the IServiceCollection - // to inject dependencies into the viewEngines) - builder.Services.AddTransient, RenderMvcViewOptionsSetup>(); - builder.Services.AddSingleton(); - builder.Services.AddTransient, PluginMvcViewOptionsSetup>(); - builder.Services.AddSingleton(); + // Configure MVC startup options for custom view locations + builder.Services.AddTransient, RenderRazorViewEngineOptionsSetup>(); + builder.Services.AddTransient, PluginRazorViewEngineOptionsSetup>(); // Wraps all existing view engines in a ProfilerViewEngine builder.Services.AddTransient, ProfilingViewEngineWrapperMvcViewOptionsSetup>(); diff --git a/src/Umbraco.Web.Website/ViewEngines/IPluginViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/IPluginViewEngine.cs deleted file mode 100644 index 4bcb7b5dc2..0000000000 --- a/src/Umbraco.Web.Website/ViewEngines/IPluginViewEngine.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Microsoft.AspNetCore.Mvc.Razor; - -namespace Umbraco.Web.Website.ViewEngines -{ - public interface IPluginViewEngine : IRazorViewEngine - { - } -} diff --git a/src/Umbraco.Web.Website/ViewEngines/IRenderViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/IRenderViewEngine.cs deleted file mode 100644 index 6f21d21494..0000000000 --- a/src/Umbraco.Web.Website/ViewEngines/IRenderViewEngine.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Microsoft.AspNetCore.Mvc.Razor; - -namespace Umbraco.Web.Website.ViewEngines -{ - public interface IRenderViewEngine : IRazorViewEngine - { - } -} diff --git a/src/Umbraco.Web.Website/ViewEngines/PluginMvcViewOptionsSetup.cs b/src/Umbraco.Web.Website/ViewEngines/PluginMvcViewOptionsSetup.cs deleted file mode 100644 index cf703ddaca..0000000000 --- a/src/Umbraco.Web.Website/ViewEngines/PluginMvcViewOptionsSetup.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; - -namespace Umbraco.Web.Website.ViewEngines -{ - public class PluginMvcViewOptionsSetup : IConfigureOptions - { - private readonly IPluginViewEngine _pluginViewEngine; - - public PluginMvcViewOptionsSetup(IPluginViewEngine pluginViewEngine) - { - _pluginViewEngine = pluginViewEngine ?? throw new ArgumentNullException(nameof(pluginViewEngine)); - } - - public void Configure(MvcViewOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - options.ViewEngines.Add(_pluginViewEngine); - } - } -} diff --git a/src/Umbraco.Web.Website/ViewEngines/PluginRazorViewEngineOptionsSetup.cs b/src/Umbraco.Web.Website/ViewEngines/PluginRazorViewEngineOptionsSetup.cs new file mode 100644 index 0000000000..3cb6d78113 --- /dev/null +++ b/src/Umbraco.Web.Website/ViewEngines/PluginRazorViewEngineOptionsSetup.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.Extensions.Options; + +namespace Umbraco.Web.Website.ViewEngines +{ + /// + /// Configure view engine locations for front-end rendering based on App_Plugins views + /// + public class PluginRazorViewEngineOptionsSetup : IConfigureOptions + { + /// + public void Configure(RazorViewEngineOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + options.ViewLocationExpanders.Add(new ViewLocationExpander()); + } + + /// + /// Expands the default view locations + /// + private class ViewLocationExpander : IViewLocationExpander + { + public IEnumerable ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable viewLocations) + { + string[] umbViewLocations = new string[] + { + // area view locations for the plugin folder + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), + + // will be used when we have partial view and child action macros + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"), + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.cshtml") + }; + + viewLocations = umbViewLocations.Concat(viewLocations); + + return viewLocations; + } + + // not a dynamic expander + public void PopulateValues(ViewLocationExpanderContext context) { } + } + } +} diff --git a/src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs deleted file mode 100644 index e0b16a351e..0000000000 --- a/src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Diagnostics; -using System.Text.Encodings.Web; -using Microsoft.AspNetCore.Mvc.Razor; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Umbraco.Web.Website.ViewEngines -{ - // TODO: We don't really need to have different view engines simply to search additional places, - // we can just do ConfigureOptions on startup to add more to the - // default list so this can be totally removed/replaced with configure options logic. - - /// - /// A view engine to look into the App_Plugins folder for views for packaged controllers - /// - public class PluginViewEngine : RazorViewEngine, IPluginViewEngine - { - public PluginViewEngine( - IRazorPageFactoryProvider pageFactory, - IRazorPageActivator pageActivator, - HtmlEncoder htmlEncoder, - ILoggerFactory loggerFactory, - DiagnosticListener diagnosticListener) - : base(pageFactory, pageActivator, htmlEncoder, OverrideViewLocations(), loggerFactory, diagnosticListener) - { - } - - private static IOptions OverrideViewLocations() => Options.Create(new RazorViewEngineOptions() - { - // This is definitely not doing what it used to do :P see: - // https://github.com/umbraco/Umbraco-CMS/blob/v8/contrib/src/Umbraco.Web/Mvc/PluginViewEngine.cs#L23 - - AreaViewLocationFormats = - { - // set all of the area view locations to the plugin folder - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), - - // will be used when we have partial view and child action macros - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"), - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.cshtml"), - // for partialsCurrent. - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), - }, - ViewLocationFormats = - { - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), - } - }); - } -} diff --git a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetup.cs b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetup.cs index b8fbe1e527..1510975f14 100644 --- a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetup.cs +++ b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetup.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; @@ -8,15 +8,20 @@ using Umbraco.Core.Logging; namespace Umbraco.Web.Website.ViewEngines { + /// + /// Wraps all view engines with a + /// public class ProfilingViewEngineWrapperMvcViewOptionsSetup : IConfigureOptions { private readonly IProfiler _profiler; - public ProfilingViewEngineWrapperMvcViewOptionsSetup(IProfiler profiler) - { - _profiler = profiler ?? throw new ArgumentNullException(nameof(profiler)); - } + /// + /// Initializes a new instance of the class. + /// + /// The + public ProfilingViewEngineWrapperMvcViewOptionsSetup(IProfiler profiler) => _profiler = profiler ?? throw new ArgumentNullException(nameof(profiler)); + /// public void Configure(MvcViewOptions options) { if (options == null) @@ -29,13 +34,16 @@ namespace Umbraco.Web.Website.ViewEngines private void WrapViewEngines(IList viewEngines) { - if (viewEngines == null || viewEngines.Count == 0) return; + if (viewEngines == null || viewEngines.Count == 0) + { + return; + } var originalEngines = viewEngines.ToList(); viewEngines.Clear(); - foreach (var engine in originalEngines) + foreach (IViewEngine engine in originalEngines) { - var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine, _profiler); + IViewEngine wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine, _profiler); viewEngines.Add(wrappedEngine); } } diff --git a/src/Umbraco.Web.Website/ViewEngines/RenderMvcViewOptionsSetup.cs b/src/Umbraco.Web.Website/ViewEngines/RenderMvcViewOptionsSetup.cs deleted file mode 100644 index d8ad58cc91..0000000000 --- a/src/Umbraco.Web.Website/ViewEngines/RenderMvcViewOptionsSetup.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; - -namespace Umbraco.Web.Website.ViewEngines -{ - public class RenderMvcViewOptionsSetup : IConfigureOptions - { - private readonly IRenderViewEngine _renderViewEngine; - - public RenderMvcViewOptionsSetup(IRenderViewEngine renderViewEngine) - { - _renderViewEngine = renderViewEngine ?? throw new ArgumentNullException(nameof(renderViewEngine)); - } - - public void Configure(MvcViewOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - options.ViewEngines.Add(_renderViewEngine); - } - } -} diff --git a/src/Umbraco.Web.Website/ViewEngines/RenderRazorViewEngineOptionsSetup.cs b/src/Umbraco.Web.Website/ViewEngines/RenderRazorViewEngineOptionsSetup.cs new file mode 100644 index 0000000000..39009d44a1 --- /dev/null +++ b/src/Umbraco.Web.Website/ViewEngines/RenderRazorViewEngineOptionsSetup.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.Extensions.Options; + +namespace Umbraco.Web.Website.ViewEngines +{ + /// + /// Configure view engine locations for front-end rendering + /// + public class RenderRazorViewEngineOptionsSetup : IConfigureOptions + { + /// + public void Configure(RazorViewEngineOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + options.ViewLocationExpanders.Add(new ViewLocationExpander()); + } + + /// + /// Expands the default view locations + /// + private class ViewLocationExpander : IViewLocationExpander + { + public IEnumerable ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable viewLocations) + { + string[] umbViewLocations = new string[] + { + "/Views/Partials/{0}.cshtml", + "/Views/MacroPartials/{0}.cshtml", + "/Views/{0}.cshtml" + }; + + viewLocations = umbViewLocations.Concat(viewLocations); + + return viewLocations; + } + + // not a dynamic expander + public void PopulateValues(ViewLocationExpanderContext context) { } + } + } +} diff --git a/src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs deleted file mode 100644 index 8c53255928..0000000000 --- a/src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.Encodings.Web; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Razor; -using Microsoft.AspNetCore.Mvc.ViewEngines; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Umbraco.Core.Hosting; -using Umbraco.Extensions; -using Umbraco.Web.Models; - -namespace Umbraco.Web.Website.ViewEngines -{ - // TODO: We don't really need to have different view engines simply to search additional places, - // we can just do ConfigureOptions on startup to add more to the - // default list so this can be totally removed/replaced with configure options logic. - - /// - /// A view engine to look into the template location specified in the config for the front-end/Rendering part of the cms, - /// this includes paths to render partial macros and media item templates. - /// - public class RenderViewEngine : RazorViewEngine, IRenderViewEngine - { - - /// - /// Initializes a new instance of the class. - /// - public RenderViewEngine( - IRazorPageFactoryProvider pageFactory, - IRazorPageActivator pageActivator, - HtmlEncoder htmlEncoder, - ILoggerFactory loggerFactory, - DiagnosticListener diagnosticListener) - : base(pageFactory, pageActivator, htmlEncoder, OverrideViewLocations(), loggerFactory, diagnosticListener) - { - } - - private static IOptions OverrideViewLocations() => Options.Create(new RazorViewEngineOptions() - { - // NOTE: we will make the main view location the last to be searched since if it is the first to be searched and there is both a view and a partial - // view in both locations and the main view is rendering a partial view with the same name, we will get a stack overflow exception. - // http://issues.umbraco.org/issue/U4-1287, http://issues.umbraco.org/issue/U4-1215 - ViewLocationFormats = - { - "/Views/Partials/{0}.cshtml", - "/Views/MacroPartials/{0}.cshtml", - "/Views/{0}.cshtml" - }, - AreaViewLocationFormats = - { - "/Views/Partials/{0}.cshtml", - "/Views/MacroPartials/{0}.cshtml", - "/Views/{0}.cshtml" - } - }); - - public new ViewEngineResult FindView(ActionContext context, string viewName, bool isMainPage) - { - return ShouldFindView(context, isMainPage) - ? base.FindView(context, viewName, isMainPage) - : ViewEngineResult.NotFound(viewName, Array.Empty()); - } - - /// - /// Determines if the view should be found, this is used for view lookup performance and also to ensure - /// less overlap with other user's view engines. This will return true if the Umbraco back office is rendering - /// and its a partial view or if the umbraco front-end is rendering but nothing else. - /// - /// - /// - /// - private static bool ShouldFindView(ActionContext context, bool isMainPage) - { - return true; - // TODO: Determine if this is required, i don't think it is - ////In v8, this was testing recursively into if it was a child action, but child action do not exist anymore, - ////And my best guess is that it - //context.RouteData.DataTokens.TryGetValue(Core.Constants.Web.UmbracoDataToken, out var umbracoToken); - //// first check if we're rendering a partial view for the back office, or surface controller, etc... - //// anything that is not ContentModel as this should only pertain to Umbraco views. - //if (!isMainPage && !(umbracoToken is ContentModel)) - // return true; - //// only find views if we're rendering the umbraco front end - //return umbracoToken is ContentModel; - } - - - } -} From eb6e5f9af283ce12a900b1e28b724dce91e62c71 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 5 Jan 2021 10:57:00 +0100 Subject: [PATCH 26/26] Removed tests that is not useful anymore --- ...ewEngineWrapperMvcViewOptionsSetupTests.cs | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetupTests.cs diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetupTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetupTests.cs deleted file mode 100644 index ba791dd8f2..0000000000 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/ViewEngines/ProfilingViewEngineWrapperMvcViewOptionsSetupTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Microsoft.AspNetCore.Mvc; -using Moq; -using NUnit.Framework; -using Umbraco.Core.Logging; -using Umbraco.Web.Website.ViewEngines; - -namespace Umbraco.Tests.Runtimes -{ - [TestFixture] - public class ProfilingViewEngineWrapperMvcViewOptionsSetupTests - { - private ProfilingViewEngineWrapperMvcViewOptionsSetup Sut => - new ProfilingViewEngineWrapperMvcViewOptionsSetup(Mock.Of()); - - [Test] - public void WrapViewEngines_HasEngines_WrapsAll() - { - var options = new MvcViewOptions() - { - ViewEngines = - { - Mock.Of(), - Mock.Of(), - } - }; - - Sut.Configure(options); - - Assert.That(options.ViewEngines.Count, Is.EqualTo(2)); - Assert.That(options.ViewEngines[0], Is.InstanceOf()); - Assert.That(options.ViewEngines[1], Is.InstanceOf()); - } - - [Test] - public void WrapViewEngines_HasEngines_KeepsSortOrder() - { - var options = new MvcViewOptions() - { - ViewEngines = - { - Mock.Of(), - Mock.Of(), - } - }; - - Sut.Configure(options); - - Assert.That(options.ViewEngines.Count, Is.EqualTo(2)); - Assert.That(((ProfilingViewEngine)options.ViewEngines[0]).Inner, Is.InstanceOf()); - Assert.That(((ProfilingViewEngine)options.ViewEngines[1]).Inner, Is.InstanceOf()); - } - - [Test] - public void WrapViewEngines_HasProfiledEngine_AddsSameInstance() - { - var profiledEngine = new ProfilingViewEngine(Mock.Of(), Mock.Of()); - var options = new MvcViewOptions() - { - ViewEngines = - { - profiledEngine - } - }; - - Sut.Configure(options); - - Assert.That(options.ViewEngines[0], Is.SameAs(profiledEngine)); - } - - [Test] - public void WrapViewEngines_CollectionIsNull_DoesNotThrow() => Assert.DoesNotThrow(() => Sut.Configure(new MvcViewOptions())); - } -}