diff --git a/.github/workflows/continuous-integration-prototypes.yml b/.github/workflows/continuous-integration-prototypes.yml index 252c4c7e9..57efce21d 100644 --- a/.github/workflows/continuous-integration-prototypes.yml +++ b/.github/workflows/continuous-integration-prototypes.yml @@ -36,7 +36,7 @@ jobs: run: Get-ChildItem -Recurse -Include *.sln | ForEach-Object {dotnet build $_ --configuration Release --no-restore; if ($LASTEXITCODE -ne 0 ) {throw "Build for $_ FAILED"; }} - name: Test .Net - run: Get-ChildItem -Recurse -Include *.sln | ForEach-Object {dotnet test $_ --no-restore --verbosity normal --collect:"XPlat Code Coverage"} + run: Get-ChildItem -Recurse -Include *.sln | ForEach-Object {dotnet test $_ --configuration Release --no-restore --verbosity normal --collect:"XPlat Code Coverage"} - name: Setup Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 56d4e67fb..9517addd0 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -31,5 +31,5 @@ jobs: run: Get-ChildItem -Recurse -Include *.sln | ForEach-Object {dotnet build $_ --configuration Release --no-restore; if ($LASTEXITCODE -ne 0 ) {throw "Build for $_ FAILED"; }} working-directory: src - name: Test - run: Get-ChildItem -Recurse -Include *.sln | ForEach-Object {dotnet test $_ --no-restore --verbosity normal} + run: Get-ChildItem -Recurse -Include *.sln | ForEach-Object {dotnet test $_ --configuration Release --no-restore --verbosity normal} working-directory: src \ No newline at end of file diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/.editorconfig b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/.editorconfig similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/.editorconfig rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/.editorconfig diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/ProcessExplorer.sln b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/ProcessExplorer.sln new file mode 100644 index 000000000..d3c76f00c --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/ProcessExplorer.sln @@ -0,0 +1,86 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{D12A440D-CF68-4A10-B673-4FCB41B4B0BC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3413C687-1DD1-4751-8C4F-0CD308248CB2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{55657FBD-CD23-40A2-B8E9-2BBE734924CC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocalCollector", "src\LocalCollector\LocalCollector.csproj", "{FA0A0669-6699-4059-BDEF-4E5BFA73E50B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Core", "src\ProcessExplorer.Core\ProcessExplorer.Core.csproj", "{5B1C8C4A-6179-488F-B5DB-25A3C313286C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Server", "src\ProcessExplorer.Server\ProcessExplorer.Server.csproj", "{AF40EAD5-8A98-465E-BF26-2EB06274A384}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Abstractions", "src\ProcessExplorer.Abstractions\ProcessExplorer.Abstractions.csproj", "{51110571-1082-4790-AA00-3DDDEE80641A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Core.Tests", "test\ProcessExplorer.Core.Tests\ProcessExplorer.Core.Tests.csproj", "{3C2B4F9E-CA84-4FB1-AE2B-CC61886A3CE7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Server.IntegrationTests", "test\ProcessExplorer.Server.EndToEndTests\ProcessExplorer.Server.IntegrationTests.csproj", "{18B9042E-0D77-4917-97FF-14BC34085385}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsoleApp", "test\TestConsoleApp\TestConsoleApp.csproj", "{B9A770BB-7FBE-46A9-A62E-5E7FDAD8EAA3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsoleApp2", "test\TestConsoleApp2\TestConsoleApp2.csproj", "{F9BCB268-66F2-4551-ABB6-58E1843B5A64}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApplications", "TestApplications", "{23E408F5-CA2E-4CBD-BAB1-48FFAC9F5357}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FA0A0669-6699-4059-BDEF-4E5BFA73E50B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA0A0669-6699-4059-BDEF-4E5BFA73E50B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA0A0669-6699-4059-BDEF-4E5BFA73E50B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA0A0669-6699-4059-BDEF-4E5BFA73E50B}.Release|Any CPU.Build.0 = Release|Any CPU + {5B1C8C4A-6179-488F-B5DB-25A3C313286C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B1C8C4A-6179-488F-B5DB-25A3C313286C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B1C8C4A-6179-488F-B5DB-25A3C313286C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B1C8C4A-6179-488F-B5DB-25A3C313286C}.Release|Any CPU.Build.0 = Release|Any CPU + {AF40EAD5-8A98-465E-BF26-2EB06274A384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF40EAD5-8A98-465E-BF26-2EB06274A384}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF40EAD5-8A98-465E-BF26-2EB06274A384}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF40EAD5-8A98-465E-BF26-2EB06274A384}.Release|Any CPU.Build.0 = Release|Any CPU + {51110571-1082-4790-AA00-3DDDEE80641A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51110571-1082-4790-AA00-3DDDEE80641A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51110571-1082-4790-AA00-3DDDEE80641A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51110571-1082-4790-AA00-3DDDEE80641A}.Release|Any CPU.Build.0 = Release|Any CPU + {3C2B4F9E-CA84-4FB1-AE2B-CC61886A3CE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C2B4F9E-CA84-4FB1-AE2B-CC61886A3CE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C2B4F9E-CA84-4FB1-AE2B-CC61886A3CE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C2B4F9E-CA84-4FB1-AE2B-CC61886A3CE7}.Release|Any CPU.Build.0 = Release|Any CPU + {18B9042E-0D77-4917-97FF-14BC34085385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18B9042E-0D77-4917-97FF-14BC34085385}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18B9042E-0D77-4917-97FF-14BC34085385}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18B9042E-0D77-4917-97FF-14BC34085385}.Release|Any CPU.Build.0 = Release|Any CPU + {B9A770BB-7FBE-46A9-A62E-5E7FDAD8EAA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9A770BB-7FBE-46A9-A62E-5E7FDAD8EAA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9A770BB-7FBE-46A9-A62E-5E7FDAD8EAA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9A770BB-7FBE-46A9-A62E-5E7FDAD8EAA3}.Release|Any CPU.Build.0 = Release|Any CPU + {F9BCB268-66F2-4551-ABB6-58E1843B5A64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9BCB268-66F2-4551-ABB6-58E1843B5A64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9BCB268-66F2-4551-ABB6-58E1843B5A64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9BCB268-66F2-4551-ABB6-58E1843B5A64}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {FA0A0669-6699-4059-BDEF-4E5BFA73E50B} = {3413C687-1DD1-4751-8C4F-0CD308248CB2} + {5B1C8C4A-6179-488F-B5DB-25A3C313286C} = {3413C687-1DD1-4751-8C4F-0CD308248CB2} + {AF40EAD5-8A98-465E-BF26-2EB06274A384} = {3413C687-1DD1-4751-8C4F-0CD308248CB2} + {51110571-1082-4790-AA00-3DDDEE80641A} = {3413C687-1DD1-4751-8C4F-0CD308248CB2} + {3C2B4F9E-CA84-4FB1-AE2B-CC61886A3CE7} = {55657FBD-CD23-40A2-B8E9-2BBE734924CC} + {18B9042E-0D77-4917-97FF-14BC34085385} = {55657FBD-CD23-40A2-B8E9-2BBE734924CC} + {B9A770BB-7FBE-46A9-A62E-5E7FDAD8EAA3} = {23E408F5-CA2E-4CBD-BAB1-48FFAC9F5357} + {F9BCB268-66F2-4551-ABB6-58E1843B5A64} = {23E408F5-CA2E-4CBD-BAB1-48FFAC9F5357} + {23E408F5-CA2E-4CBD-BAB1-48FFAC9F5357} = {55657FBD-CD23-40A2-B8E9-2BBE734924CC} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {819F883C-DDD0-4F2B-82C5-820D4D6AB446} + EndGlobalSection +EndGlobal diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/architecture.puml b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/architecture.puml similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/architecture.puml rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/architecture.puml diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Connections/ConnectionMonitor.cs similarity index 70% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionMonitor.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Connections/ConnectionMonitor.cs index cbba3e013..13c991fdc 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionMonitor.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Connections/ConnectionMonitor.cs @@ -10,14 +10,22 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. +using ProcessExplorer.Abstractions.Entities.Connections; + namespace LocalCollector.Connections; public class ConnectionMonitor : IConnectionMonitor { - private ConnectionMonitorInfo Data { get; } = new(); - ConnectionMonitorInfo IConnectionMonitor.Data + private readonly ConnectionMonitorInfo _connections = new(); + ConnectionMonitorInfo IConnectionMonitor.Connections { - get => Data; + get + { + lock (_locker) + { + return _connections; + } + } } private readonly object _locker = new(); @@ -26,14 +34,14 @@ ConnectionMonitorInfo IConnectionMonitor.Data public ConnectionMonitor(SynchronizedCollection connections) { - Data.Connections = connections; + _connections.Connections = connections; } public void AddConnection(ConnectionInfo connectionInfo) { lock (_locker) { - Data.Connections.Add(connectionInfo); + _connections.Connections.Add(connectionInfo); } } @@ -41,7 +49,7 @@ public void RemoveConnection(ConnectionInfo connectionInfo) { lock (_locker) { - var element = Data.Connections + var element = _connections.Connections .FirstOrDefault(x => x.Id == connectionInfo.Id); if (element == null) @@ -49,8 +57,8 @@ public void RemoveConnection(ConnectionInfo connectionInfo) return; } - var index = Data.Connections.IndexOf(element); - Data.Connections.RemoveAt(index); + var index = _connections.Connections.IndexOf(element); + _connections.Connections.RemoveAt(index); } } @@ -60,7 +68,7 @@ public void AddConnections(SynchronizedCollection connections) { foreach (var conn in connections) { - var element = Data.Connections + var element = _connections.Connections .FirstOrDefault(item => item.Id == conn.Id); if (element == null) @@ -68,14 +76,14 @@ public void AddConnections(SynchronizedCollection connections) continue; } - var index = Data.Connections.IndexOf(element); + var index = _connections.Connections.IndexOf(element); if (index != -1) { - Data.Connections[index] = conn; + _connections.Connections[index] = conn; } else { - Data.Connections.Add(conn); + _connections.Connections.Add(conn); } } } @@ -83,14 +91,14 @@ public void AddConnections(SynchronizedCollection connections) public void UpdateConnection(Guid connId, ConnectionStatus status) { - if (Data.Connections.Count <= 0) - { - return; - } - lock (_locker) { - var conn = Data.Connections + if (_connections.Connections.Count <= 0) + { + return; + } + + var conn = _connections.Connections .FirstOrDefault(c => c.Id == connId); if (conn == null || conn.Status == status.ToStringCached()) diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/EnvironmentVariables/EnvironmentVariableMonitorInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/EnvironmentVariables/EnvironmentVariableMonitorInfo.cs similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/EnvironmentVariables/EnvironmentVariableMonitorInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/EnvironmentVariables/EnvironmentVariableMonitorInfo.cs diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ProcessInfoDataComparer.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Extensions/HelperExtensionMethods.cs similarity index 51% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ProcessInfoDataComparer.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Extensions/HelperExtensionMethods.cs index 6fd8f4493..6569b5a75 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ProcessInfoDataComparer.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Extensions/HelperExtensionMethods.cs @@ -10,28 +10,23 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using ModuleProcessMonitor.Processes; +namespace LocalCollector.Extensions; -namespace ModuleProcessMonitor; - -internal class ProcessInfoDataComparer : EqualityComparer +internal static class HelperExtensionMethods { - public ProcessInfoDataComparer() + public static int IndexOf(this IEnumerable source, T value, IEqualityComparer? comparer = null) { - } + comparer ??= EqualityComparer.Default; - public override bool Equals(ProcessInfoData? thisData, ProcessInfoData? otherData) - { - if(thisData == null && otherData == null) return true; - if (thisData == null || otherData == null) return false; + var index = source + .Select((scopeValue, indexOf) => new { value = scopeValue, indexOf }) + .FirstOrDefault(nextValue => comparer.Equals(nextValue.value, value)); - return (thisData.PID == otherData.PID); + return index?.indexOf ?? -1; } - public override int GetHashCode(ProcessInfoData data) + public static IEnumerable Replace(this IEnumerable enumerable, int index, T value) { - int hCode = (int)data.PID! ^ (int)data.ParentId!; - return hCode.GetHashCode(); + return enumerable.Select((x, i) => index == i ? value : x); } } - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/IProcessInfoCollector.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/IProcessInfoCollector.cs similarity index 83% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/IProcessInfoCollector.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/IProcessInfoCollector.cs index 4560438da..9b7180b30 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/IProcessInfoCollector.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/IProcessInfoCollector.cs @@ -10,21 +10,16 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using LocalCollector.Communicator; -using LocalCollector.Connections; using LocalCollector.EnvironmentVariables; using LocalCollector.Modules; using LocalCollector.Registrations; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Infrastructure; namespace LocalCollector; public interface IProcessInfoCollector { - /// - /// Contains information of the environment variables, connections, registrations, modules - /// - ProcessInfoCollectorData Data { get; } - /// /// Adds a list of connections to the existing one. /// @@ -61,7 +56,7 @@ public interface IProcessInfoCollector Task AddModules(ModuleMonitorInfo modules); /// - /// Adds information of conenctions/environment variables/registrations/modules to the colelction. + /// Adds information of connections/environment variables/registrations/modules to the colelction. /// /// /// @@ -71,12 +66,6 @@ public interface IProcessInfoCollector Task AddRuntimeInformation(IConnectionMonitor connections, EnvironmentMonitorInfo environmentVariables, RegistrationMonitorInfo registrations, ModuleMonitorInfo modules); - /// - /// Sets communicator, which talks with the Process Explorer backend. Also after the connection initialized it will send the data of the existing collections. - /// - /// - void SetCommunicator(ICommunicator communicator); - /// /// Sends the runtime information of the current process. /// diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/LocalCollector.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/LocalCollector.csproj similarity index 76% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/LocalCollector.csproj rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/LocalCollector.csproj index 503fd2bf3..c6029454e 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/LocalCollector.csproj +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/LocalCollector.csproj @@ -3,6 +3,7 @@ net6.0 enable + true enable @@ -10,8 +11,11 @@ - - + + + + + diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Logging/SourceGeneratedLoggerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Logging/SourceGeneratedLoggerExtensions.cs similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Logging/SourceGeneratedLoggerExtensions.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Logging/SourceGeneratedLoggerExtensions.cs diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Modules/ModuleMonitorInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Modules/ModuleMonitorInfo.cs similarity index 96% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Modules/ModuleMonitorInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Modules/ModuleMonitorInfo.cs index 07910f0ae..b16f7c5ff 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Modules/ModuleMonitorInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Modules/ModuleMonitorInfo.cs @@ -10,6 +10,8 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. +using ProcessExplorer.Abstractions.Entities.Modules; + namespace LocalCollector.Modules; public class ModuleMonitorInfo diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/ProcessInfoCollector.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/ProcessInfoCollector.cs new file mode 100644 index 000000000..2a19ca146 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/ProcessInfoCollector.cs @@ -0,0 +1,242 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Diagnostics; +using LocalCollector.EnvironmentVariables; +using LocalCollector.Extensions; +using LocalCollector.Logging; +using LocalCollector.Modules; +using LocalCollector.Registrations; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Infrastructure; + +namespace LocalCollector; + +public class ProcessInfoCollector : IProcessInfoCollector +{ + private readonly ProcessInfoCollectorData _processInformation = new(); + private readonly ICommunicator _communicator; + private readonly ILogger _logger; + private readonly RuntimeInformation _runtimeId = new(); + private readonly object _locker = new(); + + public ProcessInfoCollector( + ICommunicator communicator, + ILogger? logger = null, + EnvironmentMonitorInfo? environmentVariables = null, + IConnectionMonitor? connections = null, + RegistrationMonitorInfo? registrations = null, + ModuleMonitorInfo? modules = null, + string? assemblyId = null, + int? processId = null) + { + _logger = logger ?? NullLogger.Instance; + + _processInformation.Id = processId ?? Process.GetCurrentProcess().Id; + + _processInformation.EnvironmentVariables = environmentVariables != null + ? environmentVariables.EnvironmentVariables + : EnvironmentMonitorInfo.FromEnvironment().EnvironmentVariables; + + _processInformation.Modules = modules != null + ? modules.CurrentModules + : ModuleMonitorInfo.FromAssembly().CurrentModules; + + if (assemblyId != null) _runtimeId.Name = assemblyId; + + if (connections != null) + { + _processInformation.Connections = connections.Connections.Connections; + + SetConnectionChangedEvent(connections); + } + + if (registrations != null) + { + _processInformation.Registrations = registrations.Services; + } + + _communicator = communicator; + } + + private void SetConnectionChangedEvent(IConnectionMonitor connectionMonitor) + { + connectionMonitor._connectionStatusChanged += ConnectionStatusChangedHandler; + } + + private async void ConnectionStatusChangedHandler(object? sender, ConnectionInfo connection) + { + IEnumerable> connections; + + try + { + lock (_locker) + { + var info = _processInformation.Connections.FirstOrDefault(p => p.Id == connection.Id); + if (info != null) + { + var index = _processInformation.Connections.IndexOf(info); + if (index >= 0 && _processInformation.Connections.Count <= index) + { + _processInformation.Connections[Convert.ToInt32(index)] = connection; + } + } + + connections = new Dictionary() + { + { _runtimeId, connection } + }; + } + } + catch (Exception exception) + { + _logger.ConnectionStatusChangedError(exception); + return; + } + + await _communicator.UpdateConnectionInformation(connections); + } + + public async Task SendRuntimeInfo() + { + IEnumerable> runtimeInfo; + + lock(_locker) + { + runtimeInfo = new Dictionary() + { + { _runtimeId, _processInformation } + }; + } + + await _communicator.AddRuntimeInfo(runtimeInfo); + } + + public async Task AddConnectionMonitor(ConnectionMonitorInfo connections) + { + await AddOrUpdateElements( + connections.Connections, + _processInformation.Connections, + (item) => (conn) => conn.Id == item.Id, + _communicator.AddConnectionCollection); + } + + public async Task AddConnectionMonitor(IConnectionMonitor connections) + { + await AddConnectionMonitor(connections.Connections); + } + + public async Task AddEnvironmentVariables(EnvironmentMonitorInfo environmentVariables) + { + IEnumerable>>> info; + + lock (_locker) + { + foreach (var env in environmentVariables.EnvironmentVariables) + { + _processInformation.EnvironmentVariables.AddOrUpdate(env.Key, env.Value, (_, _) => env.Value); + } + + info = new Dictionary>>() + { + { _runtimeId, environmentVariables.EnvironmentVariables } + }; + } + + await _communicator.UpdateEnvironmentVariableInformation(info); + } + + private async Task AddOrUpdateElements( + IEnumerable source, + IEnumerable target, + Func> predicate, + Func>>, ValueTask> handler) + { + IEnumerable>> info; + + lock (_locker) + { + if (!target.Any()) target = source; + else + { + foreach (var item in source) + { + var element = target.FirstOrDefault(predicate(item)); + + if (element == null) continue; + + var index = target.IndexOf(element); + + if (index == -1) + { + target = target.Append(item); + } + else + { + target = target.Replace(index, element); + } + } + } + + info = new Dictionary>() { { _runtimeId, source } }; + } + + await handler(info); + } + + public async Task AddRegistrations(RegistrationMonitorInfo registrations) + { + await AddOrUpdateElements( + registrations.Services, + _processInformation.Registrations, + (item) => (reg) => reg.LifeTime == item.LifeTime && reg.ImplementationType == item.ImplementationType && reg.LifeTime == item.LifeTime, + _communicator.UpdateRegistrationInformation); + } + + public async Task AddModules(ModuleMonitorInfo modules) + { + await AddOrUpdateElements( + modules.CurrentModules, + _processInformation.Modules, + (item) => (mod) => mod.Name == item.Name && mod.PublicKeyToken == item.PublicKeyToken && mod.Version == item.Version, + _communicator.UpdateModuleInformation); + } + + public async Task AddRuntimeInformation(IConnectionMonitor connections, + EnvironmentMonitorInfo environmentVariables, + RegistrationMonitorInfo registrations, ModuleMonitorInfo modules) + { + await AddConnectionMonitor(connections); + await AddEnvironmentVariables(environmentVariables); + await AddRegistrations(registrations); + await AddModules(modules); + } + + public void SetAssemblyId(string assemblyId) + { + lock (_locker) + { + _runtimeId.Name = assemblyId; + } + } + + public void SetClientPid(int clientPid) + { + lock (_locker) + { + _processInformation.Id = clientPid; + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Registrations/RegistrationsMonitorInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Registrations/RegistrationsMonitorInfo.cs similarity index 96% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Registrations/RegistrationsMonitorInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Registrations/RegistrationsMonitorInfo.cs index 7abe03c06..92617d3de 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Registrations/RegistrationsMonitorInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/LocalCollector/Registrations/RegistrationsMonitorInfo.cs @@ -11,6 +11,7 @@ // and limitations under the License. using Microsoft.Extensions.DependencyInjection; +using ProcessExplorer.Abstractions.Entities.Registrations; namespace LocalCollector.Registrations; diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionInfo.cs similarity index 94% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionInfo.cs index a60b40375..b51b95884 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionInfo.cs @@ -12,7 +12,7 @@ using System.Collections.Concurrent; -namespace LocalCollector.Connections; +namespace ProcessExplorer.Abstractions.Entities.Connections; public record ConnectionInfo { diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionMonitorInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionMonitorInfo.cs similarity index 90% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionMonitorInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionMonitorInfo.cs index c8df353b7..f3506fc3b 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionMonitorInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionMonitorInfo.cs @@ -10,9 +10,9 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace LocalCollector.Connections; +namespace ProcessExplorer.Abstractions.Entities.Connections; public class ConnectionMonitorInfo { - public SynchronizedCollection Connections { get; internal set; } = new(); + public SynchronizedCollection Connections { get; set; } = new(); } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionStatus.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionStatus.cs similarity index 92% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionStatus.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionStatus.cs index fa9bd4f44..2509a65e7 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionStatus.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionStatus.cs @@ -10,7 +10,7 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace LocalCollector.Connections; +namespace ProcessExplorer.Abstractions.Entities.Connections; public enum ConnectionStatus { diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionStatusExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionStatusExtensions.cs similarity index 94% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionStatusExtensions.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionStatusExtensions.cs index 16c5218f9..c98edad2c 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/ConnectionStatusExtensions.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/ConnectionStatusExtensions.cs @@ -10,7 +10,7 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace LocalCollector.Connections; +namespace ProcessExplorer.Abstractions.Entities.Connections; public static class ConnectionStatusExtensions { diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/IConnectionMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/IConnectionMonitor.cs similarity index 94% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/IConnectionMonitor.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/IConnectionMonitor.cs index 9e818407b..36c754cb9 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Connections/IConnectionMonitor.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Connections/IConnectionMonitor.cs @@ -10,14 +10,15 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace LocalCollector.Connections; + +namespace ProcessExplorer.Abstractions.Entities.Connections; public interface IConnectionMonitor { /// /// Contains the information of the relevant connections. /// - ConnectionMonitorInfo Data { get; } + ConnectionMonitorInfo Connections { get; } /// /// Event for status change of a connection. diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Modules/ModuleInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Modules/ModuleInfo.cs similarity index 88% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Modules/ModuleInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Modules/ModuleInfo.cs index 28f094fa4..476a83331 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Modules/ModuleInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Modules/ModuleInfo.cs @@ -12,7 +12,7 @@ using System.Reflection; -namespace LocalCollector.Modules; +namespace ProcessExplorer.Abstractions.Entities.Modules; public class ModuleInfo { @@ -21,9 +21,8 @@ public class ModuleInfo public string? VersionRedirectedFrom { get; set; } public byte[]? PublicKeyToken { get; set; } public string? Location { get; set; } - public SynchronizedCollection Information { get; set; } = new(); - internal static ModuleInfo FromModule(Assembly assembly, Module module) + public static ModuleInfo FromModule(Assembly assembly, System.Reflection.Module module) { string? location; try diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/ProcessInfoCollectorData.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/ProcessInfoCollectorData.cs similarity index 77% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/ProcessInfoCollectorData.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/ProcessInfoCollectorData.cs index 0bad39c6e..db1778f08 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/ProcessInfoCollectorData.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/ProcessInfoCollectorData.cs @@ -12,21 +12,20 @@ using System.Collections.Concurrent; using System.Diagnostics; -using LocalCollector.Connections; -using LocalCollector.EnvironmentVariables; -using LocalCollector.Modules; -using LocalCollector.Registrations; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; -namespace LocalCollector; +namespace ProcessExplorer.Abstractions.Entities; [Serializable] public class ProcessInfoCollectorData { public int Id { get; set; } = Process.GetCurrentProcess().Id; public SynchronizedCollection Registrations { get; set; } = new(); - public ConcurrentDictionary EnvironmentVariables { get; set; } = EnvironmentMonitorInfo.FromEnvironment().EnvironmentVariables; + public ConcurrentDictionary EnvironmentVariables { get; set; } = new(); public SynchronizedCollection Connections { get; set; } = new(); - public SynchronizedCollection Modules { get; set; } = ModuleMonitorInfo.FromAssembly().CurrentModules; + public SynchronizedCollection Modules { get; set; } = new(); private readonly object _locker = new(); @@ -40,6 +39,12 @@ public void UpdateConnection(ConnectionInfo connection) lock (_locker) { var index = Connections.IndexOf(connection); + if (index == -1) + { + var element = Connections.FirstOrDefault(c => c.Id == connection.Id); + if(element != null) + index = Connections.IndexOf(element); + } if (index >= 0) { Connections[index] = connection; @@ -47,7 +52,7 @@ public void UpdateConnection(ConnectionInfo connection) } } - public void UpdateEnvironmentVariables(IEnumerable> envs) + public void UpdateOrAddEnvironmentVariables(IEnumerable> envs) { foreach (var item in envs) { @@ -55,13 +60,13 @@ public void UpdateEnvironmentVariables(IEnumerable> } } - public void UpdateRegistrations(IEnumerable services) + public void UpdateOrAddRegistrations(IEnumerable services) { UpdateOrAdd(services, Registrations, (item) => reg => reg.ImplementationType == item.ImplementationType && reg.ServiceType == item.ServiceType && reg.LifeTime == item.LifeTime); } - public void UpdateModules(IEnumerable currentModules) + public void UpdateOrAddModules(IEnumerable currentModules) { UpdateOrAdd(currentModules, Modules, (item) => (item2) => item.Name == item2.Name && item.PublicKeyToken == item2.PublicKeyToken); } @@ -90,6 +95,10 @@ private void UpdateOrAdd(IEnumerable source, SynchronizedCollection tar target.Add(item); } } + else + { + target.Add(item); + } } } } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Registrations/RegistrationInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Registrations/RegistrationInfo.cs similarity index 92% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Registrations/RegistrationInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Registrations/RegistrationInfo.cs index edb82aa6d..f61d157d3 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Registrations/RegistrationInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/Registrations/RegistrationInfo.cs @@ -10,7 +10,7 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace LocalCollector.Registrations; +namespace ProcessExplorer.Abstractions.Entities.Registrations; public class RegistrationInfo { diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Communicator/AssemblyInformation.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/RuntimeInformation.cs similarity index 89% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Communicator/AssemblyInformation.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/RuntimeInformation.cs index 483a35b8d..ccb6083c6 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Communicator/AssemblyInformation.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Entities/RuntimeInformation.cs @@ -10,10 +10,10 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace LocalCollector.Communicator; +namespace ProcessExplorer.Abstractions.Entities; [Serializable] -public class AssemblyInformation +public class RuntimeInformation { public string Name { get; set; } = string.Empty; } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/EnumExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Extensions/EnumExtensions.cs similarity index 82% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/EnumExtensions.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Extensions/EnumExtensions.cs index b8706a912..446ee213f 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/EnumExtensions.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Extensions/EnumExtensions.cs @@ -11,24 +11,26 @@ // and limitations under the License. using System.Diagnostics; +using ProcessExplorer.Abstractions.Processes; using ThreadState = System.Diagnostics.ThreadState; -namespace ModuleProcessMonitor.Processes; +namespace ProcessExplorer.Abstractions.Extensions; -internal static class EnumExtensions +public static class EnumExtensions { - internal static string ToStringCached(this Status status) + public static string ToStringCached(this ProcessStatus status) { return status switch { - Status.Terminated => nameof(Status.Terminated), - Status.Running => nameof(Status.Running), - Status.Stopped => nameof(Status.Stopped), + ProcessStatus.Modified => nameof(ProcessStatus.Modified), + ProcessStatus.Terminated => nameof(ProcessStatus.Terminated), + ProcessStatus.Running => nameof(ProcessStatus.Running), + ProcessStatus.Stopped => nameof(ProcessStatus.Stopped), _ => status.ToString(), }; } - internal static string ToStringCached(this ProcessPriorityClass priorityClass) + public static string ToStringCached(this ProcessPriorityClass priorityClass) { return priorityClass switch { @@ -42,7 +44,7 @@ internal static string ToStringCached(this ProcessPriorityClass priorityClass) }; } - internal static string ToStringCached(this ThreadState threadState) + public static string ToStringCached(this ThreadState threadState) { return threadState switch { @@ -58,7 +60,7 @@ internal static string ToStringCached(this ThreadState threadState) }; } - internal static string ToStringCached(this ThreadWaitReason waitReason) + public static string ToStringCached(this ThreadWaitReason waitReason) { return waitReason switch { diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/IProcessInfoAggregator.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/IProcessInfoAggregator.cs similarity index 53% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/IProcessInfoAggregator.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/IProcessInfoAggregator.cs index b81fc3bd4..403a9690d 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/IProcessInfoAggregator.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/IProcessInfoAggregator.cs @@ -10,84 +10,87 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using System.Collections.Concurrent; -using LocalCollector; -using LocalCollector.Connections; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using ModuleProcessMonitor.Processes; -using ProcessExplorer.Infrastructure; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; -namespace ProcessExplorer; +namespace ProcessExplorer.Abstractions; -public interface IProcessInfoAggregator +public interface IProcessInfoAggregator { /// - /// Contains information. - /// (connection/registrations/modules/environment variables) + /// The main id, which childprocesses should be watched. /// - ConcurrentDictionary? ProcessInformation { get; } + public int MainProcessId { get; set; } /// - /// Adds a compose process to keep track on it. + /// Delay for actually sending terminate request for the UI. /// - /// - void AddProcessInfo(ProcessInfoData processInfo); + public int TerminatingProcessDelay { get; } /// - /// Contains and collects the information about the related processes in the Compose. + /// Controls the initialized subsystems. /// - IProcessMonitor? ProcessMonitor { get; } + public ISubsystemController SubsystemController { get; } /// - /// Adds a runtime information to the collection. + /// Handles the communication between the server and clients. /// - /// - /// - Task AddInformation(string assemblyId, ProcessInfoCollectorData processInfo); + public IUiHandler UiHandler { get; } /// /// Removes a module information from the collection. /// /// - void RemoveAInfoAggregatorInformation(string assembly); + void RemoveRuntimeInformation(string assembly); /// - /// Sets Compose PID. + /// Sets the delay time for keeping a process after it was terminated.(s) + /// Default: 1 minute. /// - /// - void SetComposePid(int pid); - + /// + void SetDeadProcessRemovalDelay(int delay); + /// - /// Sets ProcessMonitor instance. + /// Enables to watch processes through ProcessMonitor. + /// Only available for Windows OS. /// - /// - Task SetProcessMonitor(IProcessMonitor processMonitor); + void EnableWatchingSavedProcesses(); /// - /// Sets the delay time for keeping a process after it was terminated.(s) - /// Default: 1 minute. + /// Disables to watch processes. /// - /// - void SetDeadProcessRemovalDelay(int delay); + void DisableWatchingProcesses(); /// - /// Returns the list containing the processes. + /// Sets the processes, which is gotten from the ModuleLoader. /// - /// - IEnumerable? GetProcesses(); + /// + void InitProcesses(ReadOnlySpan processIds); /// - /// Adds a UIClient to the collection. Keeps track of the UIClients. + /// Puts the given subsystem into the queue to send subsystem state changed information to the UI's. /// - /// - void AddUiConnection(IUIHandler uiHandler); + /// + /// + void ScheduleSubsystemStateChanged(Guid instanceId, string state); /// - /// Removes a UIClient from the collection. + /// Returns the initialized runtime information. + /// + /// + IEnumerable> GetRuntimeInformation(); + + /// + /// Adds a runtime information to the collection. /// - /// - void RemoveUiConnection(IUIHandler uiHandler); + /// + /// + Task AddRuntimeInformation(string assemblyId, ProcessInfoCollectorData processInfo); /// /// Adds or updates the connections in the collection. @@ -101,50 +104,46 @@ public interface IProcessInfoAggregator /// /// /// - Task UpdateConnectionInfo(string assemblyId, ConnectionInfo connectionInfo); + Task UpdateOrAddConnectionInfo(string assemblyId, ConnectionInfo connectionInfo); /// /// Updates the environment variables. /// /// /// - Task UpdateEnvironmentVariablesInfo(string assemblyId, IEnumerable> environmentVariables); + Task UpdateOrAddEnvironmentVariablesInfo(string assemblyId, IEnumerable> environmentVariables); /// - /// Updates the registrations in the collection. + /// Adds the registrations to the collection. /// /// /// - Task UpdateRegistrationInfo(string assemblyId, IEnumerable registrations); + Task UpdateRegistrations(string assemblyId, IEnumerable registrations); /// - /// Updates the modules in the collection. + /// Updates the modules to the collection. /// /// /// - Task UpdateModuleInfo(string assemblyId, IEnumerable modules); + Task UpdateOrAddModuleInfo(string assemblyId, IEnumerable modules); /// - /// Terminates a process by ID. + /// Adds processes to watch to the existing watchable process ids list. /// - /// + /// /// - Task RemoveProcessById(int pid); + Task AddProcesses(ReadOnlySpan processIds); /// - /// Enables to watch processes through ProcessMonitor. - /// Only available for Windows OS. + /// Asynchronously dequeue the changes of the registered subsystems, and send to the initialized UI's. /// - void EnableWatchingSavedProcesses(); - - /// - /// Disables to watch processes. - /// - void DisableWatchingProcesses(); + /// + /// + Task RunSubsystemStateQueue(CancellationToken cancellationToken); /// - /// Sets the processes, which is gotten from the ModuleLoader. + /// Returns the initialized processes. /// - /// - void InitProcesses(IEnumerable processInfo); + /// + IEnumerable GetProcesses(); } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessMonitorInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/IClientConnection.cs similarity index 79% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessMonitorInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/IClientConnection.cs index c39d22454..285e54b11 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessMonitorInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/IClientConnection.cs @@ -10,9 +10,10 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ModuleProcessMonitor.Processes; +namespace ProcessExplorer.Abstractions.Infrastructure; -public class ProcessMonitorInfo +public interface IClientConnection { - public SynchronizedCollection Processes { get; internal set; } = new(); + Task SendMessage(T message); } + diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Communicator/ICommunicator.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/ICommunicator.cs similarity index 70% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Communicator/ICommunicator.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/ICommunicator.cs index aea554a6d..dd8cf6cce 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/Communicator/ICommunicator.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/ICommunicator.cs @@ -10,11 +10,12 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using LocalCollector.Connections; -using LocalCollector.Modules; -using LocalCollector.Registrations; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; -namespace LocalCollector.Communicator; +namespace ProcessExplorer.Abstractions.Infrastructure; public interface ICommunicator { @@ -23,40 +24,40 @@ public interface ICommunicator /// /// /// - ValueTask AddRuntimeInfo(IEnumerable> listOfRuntimeInfos); + ValueTask AddRuntimeInfo(IEnumerable> listOfRuntimeInfos); /// /// Sends a message to the UI, if a new list of connections has been added. /// /// /// - ValueTask AddConnectionCollection(IEnumerable>> connections); + ValueTask AddConnectionCollection(IEnumerable>> connections); /// /// Sends a message to the UI, if a connection has been updated. /// /// /// - ValueTask UpdateConnectionInformation(IEnumerable> connections); + ValueTask UpdateConnectionInformation(IEnumerable> connections); /// /// Sends a message to the UI, if the environment variables of the collector has been updated. /// /// /// - ValueTask UpdateEnvironmentVariableInformation(IEnumerable>>> environmentVariables); + ValueTask UpdateEnvironmentVariableInformation(IEnumerable>>> environmentVariables); /// /// Sends a message to the UI, if the registrations of the collector has been updated. /// /// /// - ValueTask UpdateRegistrationInformation(IEnumerable>> registrations); + ValueTask UpdateRegistrationInformation(IEnumerable>> registrations); /// /// Sends a message to the UI, if the modules of the collector has been updated. /// /// /// - ValueTask UpdateModuleInformation(IEnumerable>> modules); + ValueTask UpdateModuleInformation(IEnumerable>> modules); } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/IUIHandler.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/IUIHandler.cs similarity index 82% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/IUIHandler.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/IUIHandler.cs index 71ad1f344..689c0c8a3 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/IUIHandler.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/IUIHandler.cs @@ -10,17 +10,20 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using LocalCollector; -using LocalCollector.Connections; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using ModuleProcessMonitor.Processes; -using ModuleProcessMonitor.Subsystems; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; -namespace ProcessExplorer.Infrastructure; +namespace ProcessExplorer.Abstractions.Infrastructure; -public interface IUIHandler +public interface IUiHandler { + void AddClientConnection(Guid id, IClientConnection connection); + void RemoveClientConnection(Guid id); + /// /// Adds a list of processes to the collection. /// @@ -47,7 +50,7 @@ public interface IUIHandler /// /// /// - Task RemoveProcessByID(int pid); + Task TerminateProcess(int pid); /// /// Collects runtime information to the collection. (Environment variables/modules/connections/registrations) @@ -86,7 +89,7 @@ public interface IUIHandler /// /// /// - Task UpdateEnvironmentVariables(string assemblyId, IEnumerable> environmentVariables); + Task UpdateEnvironmentVariables(string assemblyId, IEnumerable> environmentVariables); /// /// Updates information of registrations in the collection. @@ -120,13 +123,6 @@ public interface IUIHandler /// Task AddSubsystem(Guid subsystemId, SubsystemInfo subsystem); - /// - /// Removes a subsystem from the collection. - /// - /// - /// - Task RemoveSubsystem(Guid subsystemId); - /// /// Update an information of subsystem. /// Sends a message to the UI - probably that the state of the Subsystem is changed. @@ -135,4 +131,17 @@ public interface IUIHandler /// /// Task UpdateSubsystemInfo(Guid subsystemId, SubsystemInfo subsystem); + + /// + /// Updates the status of the process. Mostly used for sending update terminated process. + /// + /// + /// + Task UpdateProcessStatus(KeyValuePair process); + + /// + /// Updates the client that the connection has been established. + /// + /// + Task SubscriptionIsAliveUpdate(); } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/Protos/ProcessExplorerMessages.proto b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/Protos/ProcessExplorerMessages.proto new file mode 100644 index 000000000..b3237620c --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Infrastructure/Protos/ProcessExplorerMessages.proto @@ -0,0 +1,127 @@ +syntax = "proto3"; + +option csharp_namespace = "ProcessExplorer.Abstractions.Infrastructure.Protos"; + +import "google/protobuf/duration.proto"; +import "google/protobuf/empty.proto"; + +service ProcessExplorerMessageHandler{ + rpc Send(Message) returns (google.protobuf.Empty); + rpc Subscribe(google.protobuf.Empty) returns (stream Message); +} + +message Message{ + oneof action1 { + ActionType action = 1; + }; + optional string assemblyId = 2; + repeated Process processes = 3; + repeated Registration registrations = 4; + repeated Module modules = 5; + map environmentVariables = 6; + optional int32 processId = 7; + map subsystems = 8; + repeated ProcessInfoCollectorData runtimeInfo = 9; + repeated Connection connections = 10; + map multipleRuntimeInfo = 11; + int32 periodOfDelay = 12; + map processStatusChanges = 13; + optional string description = 14; +} + +enum ActionType{ + AddProcessListAction = 0; + AddConnectionListAction = 1; + AddProcessAction = 2; + AddRuntimeInfoAction = 3; + AddSubsystemAction = 4; + AddSubsystemsAction = 5; + RemoveProcessByIdAction = 6; + UpdateConnectionAction = 7; + UpdateEnvironmentVariablesAction = 8; + UpdateModulesAction = 9; + UpdateProcessAction = 10; + UpdateProcessStatusAction = 11; + UpdateRegistrationsAction = 12; + UpdateSubsystemAction = 13; + InitSubsystemsAction = 14; + ModifySubsystemAction = 15; + RemoveSubsystemsAction = 16; + AddMultipleRuntimeInfoAction = 17; + RestartSubsystemsAction = 18; + TerminateSubsystemsAction = 19; + LaunchSubsystemsAction = 20; + LaunchSubsystemsWithDelayAction = 21; + SubscriptionAliveAction = 22; +} + +message Process{ + optional string startTime = 4; + optional google.protobuf.Duration processorUsageTime = 5; + optional int64 physicalMemoryUsageBit = 6; + optional string processName = 7; + optional int32 processId = 8; + optional string processPriorityClass = 9; + repeated ProcessThreadInfo threads = 10; + optional int64 virtualMemorySize = 11; + optional int32 parentId = 12; + optional int64 privateMemoryUsage = 13; + optional string processStatus = 14; + optional float memoryUsage = 15; + optional float processorUsage = 16; +} + +message ProcessThreadInfo{ + optional string startTime = 1; + optional int32 priorityLevel = 2; + optional int32 id = 3; + optional string status = 4; + optional google.protobuf.Duration processorUsageTime = 5; + optional string waitReason = 6; +} + +message ProcessInfoCollectorData{ + int32 id = 1; + repeated Registration registrations = 2; + map environmentVariables = 3; + repeated Connection connections = 4; + repeated Module modules = 5; +} + +message Registration{ + optional string implementationType = 1; + optional string lifeTime = 2; + optional string serviceType = 3; +} + +message Connection{ + optional string id = 1; + optional string name = 2; + optional string localEndpoint = 3; + optional string remoteEndpoint = 4; + optional string remoteApplication = 5; + optional string remoteHostname = 6; + map connectionInformation = 7; + optional string status = 8; +} + +message Module{ + optional string name = 1; + optional string version = 2; + optional string versionRedirectedFrom = 3; + optional bytes publicKeyToken = 4; + optional string location = 5; +} + +message Subsystem{ + string name = 1; + optional string startupType = 2; + optional string uiType = 3; + optional string path = 4; + optional string url = 5; + repeated string arguments = 6; + optional int32 port = 7; + string state = 8; + optional string description = 9; + bool automatedStart = 10; +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Logging/SourceGeneratedLoggerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Logging/SourceGeneratedLoggerExtensions.cs new file mode 100644 index 000000000..315591200 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Logging/SourceGeneratedLoggerExtensions.cs @@ -0,0 +1,268 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.Logging; + +namespace ProcessExplorer.Abstractions.Logging; + +public static partial class SourceGeneratedLoggerExtensions +{ + [LoggerMessage(Level = LogLevel.Debug, Message = "Starting to watch processes, due it is enabled by the user.", SkipEnabledCheck = false)] + public static partial void ProcessMonitorEnabledDebug(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Couldn't find the PPID for the PID `{pid}`. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ManagementObjectPpid(this ILogger logger, int pid, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Starting a subsystem with id: {id}", SkipEnabledCheck = false)] + public static partial void SubsystemStartedDebug(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Stopping a subsystem with id: {id}", SkipEnabledCheck = false)] + public static partial void SubsystemStoppingDebug(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot add the connections to collection. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ConnectionCollectionCannotBeAdded(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Connection cannot be updated. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ConnectionCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Couldn't watch the processes. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void EnvironmentVariablesCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Registrations cannot be updated. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void RegistrationsCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Modules cannot be updated. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ModulesCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot modify subsystem's state with ID `{subsystemId}`. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ModifyingSubsystemsState(this ILogger logger, string subsystemId, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating the information on UI cannot be completed. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void UiInformationCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot send launch request to the SubsystemLauncher. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotSendLaunchRequest(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot terminate a subsystem/subsystems. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotTerminateSubsystem(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Information, Message = "A process with PID: `{pid}` is terminated", SkipEnabledCheck = false)] + public static partial void ProcessTerminatedInformation(this ILogger logger, int pid); + + [LoggerMessage(Level = LogLevel.Information, Message = "A process with PID: `{pid}` is created", SkipEnabledCheck = false)] + public static partial void ProcessCreatedInformation(this ILogger logger, int pid); + + [LoggerMessage(Level = LogLevel.Debug, Message = "A process with PID: `{pid}` is modified", SkipEnabledCheck = false)] + public static partial void ProcessModifiedDebug(this ILogger logger, int pid); + + [LoggerMessage(Level = LogLevel.Warning, Message = "The subsystem with `{id}` couldn't be terminated. Subsystem name: `{name}`", SkipEnabledCheck = false)] + public static partial void SubsystemTerminationAddWarning(this ILogger logger, string id, string name); + + [LoggerMessage(Level = LogLevel.Error, Message = "Couldn't read the child process. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ManagementObjectChild(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot find the process. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotFindProcess(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Debug, Message = "Couldn't read the event of the process. Probably the event is not set for this WMI handler or the ProcessMonitor is disabled. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void ManagementObjectWatchEvent(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot find an element with PID `{pid}` in the current process list. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotFindElement(this ILogger logger, int pid, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot stop process watcher. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotStopProcessWatcher(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot find an element with PID `{pid}` or the communicator has been not set properly. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CouldNotFoundModifiableProcess(this ILogger logger, int pid, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Nor PID does not exists: `{pid}` or the process list does not exists. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void PidNotExists(this ILogger logger, int pid, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Index does not exists for the PID: `{pid}` or the process list does not exists. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void IndexDoesNotExists(this ILogger logger, int pid, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Cannot terminate process or the process does not exists in the current context. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotKillProcess(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while initializing list. The main process might be deleted. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void CannotFillList(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while starting a subsystem with id: {id}. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void SubsystemStartFailure(this ILogger logger, string id, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while restarting a subsystem with id: {id}. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void SubsystemRestartFailure(this ILogger logger, string id, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while restarting a subsystem with id: {id}.", SkipEnabledCheck = true)] + private static partial void SubsystemRestartFailureWithoutException(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while stopping a subsystem with id: {id}. Detailed exception: `{exception}`", SkipEnabledCheck = true)] + private static partial void SubsystemStopFailure(this ILogger logger, string id, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while adding a subsystem with id: {id}, name: `{name}`", SkipEnabledCheck = true)] + private static partial void SubsystemAddFailure(this ILogger logger, string id, string name); + + [LoggerMessage(Level = LogLevel.Error, Message = "Unable to remove ProcessInfoCollectorData from collection. Id: `{assemblyId}`", SkipEnabledCheck = false)] + public static partial void UnableToRemoveRuntimeInformationError(this ILogger logger, string assemblyId); + + public static void SubsystemAddError(this ILogger logger, string id, string name) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.SubsystemAddFailure(id, name); + } + } + + public static void SubsystemStopError(this ILogger logger, string id, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.SubsystemStopFailure(id, exception, exception); + } + } + + public static void SubsystemRestartError(this ILogger logger, string id) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.SubsystemRestartFailureWithoutException(id); + } + } + + public static void SubsystemStartError(this ILogger logger, string id, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.SubsystemStartFailure(id, exception, exception); + } + } + + public static void ManagementObjectPpidExpected(this ILogger logger, int pid, Exception exception) + { + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.ManagementObjectPpid(pid, exception, exception); + } + } + + public static void InstanceEventExpected(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.ManagementObjectWatchEvent(exception, exception); + } + } + + public static void ChildProcessExpected(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.ManagementObjectChild(exception, exception); + } + } + + public static void ProcessExpected(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.CannotFindProcess(exception, exception); + } + } + + public static void WatcherInitializationError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.ManagementObjectChild(exception, exception); + } + } + + public static void PpidExpected(this ILogger logger, int pid, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.CannotFindElement(pid, exception, exception); + } + } + + public static void UiInformationCannotBeUpdatedError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.UiInformationCannotBeUpdated(exception, exception); + } + } + public static void CannotTerminateSubsystemError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.CannotTerminateSubsystem(exception, exception); + } + } + + public static void CannotSendLaunchRequestError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.CannotSendLaunchRequest(exception, exception); + } + } + + public static void ConnectionCollectionCannotBeAddedError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.ConnectionCollectionCannotBeAdded(exception, exception); + } + } + + public static void ConnectionCannotBeUpdatedError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.ConnectionCannotBeUpdated(exception, exception); + } + } + + public static void EnvironmentVariablesCannotBeUpdatedError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.EnvironmentVariablesCannotBeUpdated(exception, exception); + } + } + + public static void RegistrationsCannotBeUpdatedError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.RegistrationsCannotBeUpdated(exception, exception); + } + } + + public static void ModulesCannotBeUpdatedError(this ILogger logger, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.ModulesCannotBeUpdated(exception, exception); + } + } + + public static void ModifyingSubsystemsStateError(this ILogger logger, Guid subsystemId, Exception exception) + { + if (logger.IsEnabled(LogLevel.Error)) + { + logger.ModifyingSubsystemsState(subsystemId.ToString(), exception, exception); + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Module.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Module.cs similarity index 57% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Module.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Module.cs index 6a25863c5..fbb92e270 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Module.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Module.cs @@ -10,35 +10,38 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using ModuleProcessMonitor.Subsystems; -using MorganStanley.ComposeUI.Tryouts.Core.Abstractions.Modules; +using ProcessExplorer.Abstractions.Subsystems; -namespace ModuleProcessMonitor; +namespace ProcessExplorer.Abstractions; -public class Module +public struct Module { + public Module( + string name, + string startupType, + string uIType, + string path, + string? url, + string[]? arguments, + int? port, + string state) + { + Name = name; + StartupType = startupType; + UIType = uIType; + Path = path; + Url = url; + Arguments = arguments; + Port = port; + State = state; + } + public string Name { get; set; } public string StartupType { get; set; } public string UIType { get; set; } - public string? Path { get; set; } + public string Path { get; set; } public string? Url { get; set; } public string[]? Arguments { get; set; } public int? Port { get; set; } - public string? State { get; set; } = SubsystemState.Stopped; - - public static explicit operator Module(ModuleManifest manifest) - { - var module = new Module - { - Name = manifest.Name, - StartupType = manifest.StartupType, - UIType = manifest.UIType, - Path = manifest.Path, - Url = manifest.Url, - Arguments = manifest.Arguments, - Port = manifest.Port - }; - - return module; - } + public string State { get; set; } = SubsystemState.Stopped; } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/ProcessExplorer.Abstractions.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/ProcessExplorer.Abstractions.csproj new file mode 100644 index 000000000..ac26c13d4 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/ProcessExplorer.Abstractions.csproj @@ -0,0 +1,37 @@ + + + + net6.0 + enable + true + enable + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + Both + + + + diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/IProcessInfoMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/IProcessInfoMonitor.cs new file mode 100644 index 000000000..863231dc0 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/IProcessInfoMonitor.cs @@ -0,0 +1,74 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +namespace ProcessExplorer.Abstractions.Processes; + +public interface IProcessInfoMonitor : IDisposable +{ + /// + /// Returns the collection of processes. + /// + public IObservable> ProcessIds { get; } + + /// + /// Clears the currently initilialzed processes. + /// + void ClearProcessIds(); + + /// + /// Returns the CPU usage of the given process. + /// + /// + /// + /// + float GetCpuUsage(int processId, string processName); + + /// + /// Returns the memory usage of the given process. + /// + /// + /// + /// + float GetMemoryUsage(int processId, string processName); + + /// + /// Returns the parent id of the given process. + /// + /// + /// + /// + int? GetParentId(int processId, string processName); + + /// + /// Returns the initialized/watched process ids. + /// + /// + ReadOnlySpan GetProcessIds(); + + /// + /// Sets the watchable process list. + /// + /// + /// + void SetProcessIds(int mainProcessId, ReadOnlySpan processIds); + + /// + /// Enables watching processes. + /// + /// + void WatchProcesses(int mainProcessId); + + /// + /// Disables to watch processes. + /// + void StopWatchingProcesses(); +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoData.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessInfoData.cs similarity index 73% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoData.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessInfoData.cs index 34d0a38a4..e9198b577 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoData.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessInfoData.cs @@ -10,25 +10,25 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ModuleProcessMonitor.Processes; +using System.Diagnostics; +using ProcessExplorer.Abstractions.Extensions; + +namespace ProcessExplorer.Abstractions.Processes; public class ProcessInfoData { - public Guid? InstanceId { get; set; } - public string? UiType { get; set; } - public string? UiHint { get; set; } public string? StartTime { get; set; } - public TimeSpan? ProcessorUsageTime { get; set; } + public TimeSpan? ProcessorUsageTime { get; set; } public long? PhysicalMemoryUsageBit { get; set; } public string? ProcessName { get; set; } - public int? PID { get; set; } + public int ProcessId { get; set; } public int? PriorityLevel { get; set; } public string? ProcessPriorityClass { get; set; } - public SynchronizedCollection Threads { get; set; } = new(); + public IEnumerable Threads { get; set; } = Enumerable.Empty(); public long? VirtualMemorySize { get; set; } public int? ParentId { get; set; } public long? PrivateMemoryUsage { get; set; } - public string? ProcessStatus { get; set; } = Status.Running.ToStringCached(); + public string? ProcessStatus { get; set; } = Processes.ProcessStatus.Running.ToStringCached(); public float? MemoryUsage { get; set; } public float? ProcessorUsage { get; set; } } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessInfoMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessInfoMonitor.cs new file mode 100644 index 000000000..f4aa91417 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessInfoMonitor.cs @@ -0,0 +1,221 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions.Logging; + +namespace ProcessExplorer.Abstractions.Processes; + +public abstract class ProcessInfoMonitor : IProcessInfoMonitor +{ + private readonly ILogger _logger; + private readonly ObservableCollection _processIds = new(); + private readonly object _processIdsLocker = new(); + private readonly Subject> _processIdsSubject = new(); + + public IObservable> ProcessIds => _processIdsSubject; + + + protected ProcessInfoMonitor(ILogger? logger) + { + _logger = logger ?? NullLogger.Instance; + } + + public bool ContainsId(int processId) + { + lock (_processIdsLocker) + { + return _processIds.Contains(processId); + } + } + + public void AddProcess(int processId) + { + lock (_processIdsLocker) + { + if (processId == 0) return; + + _processIds.Add(processId); + _processIdsSubject.OnNext(new(processId, ProcessStatus.Running)); + } + } + + public void RemoveProcessId(int processId) + { + lock (_processIdsLocker) + { + var removedProcessId = _processIds.Remove(processId); + if (!removedProcessId) return; + + _processIdsSubject.OnNext(new(processId, ProcessStatus.Terminated)); + _logger.ProcessTerminatedInformation(processId); + } + } + + public void SetProcessIds( + int mainProcessId, + ReadOnlySpan processIds) + { + lock (_processIdsLocker) + { + foreach (var id in processIds) + { + try + { + if (_processIds.Contains(id)) continue; + + var process = Process.GetProcessById(id); + + _processIds.Add(id); + + AddChildProcesses(id, process.ProcessName); + } + catch (Exception exception) + { + _logger.ProcessExpected(exception); + } + } + + if (mainProcessId != 0 && !_processIds.Contains(mainProcessId)) + _processIds.Add(mainProcessId); + } + } + + public ReadOnlySpan GetProcessIds() + { + lock (_processIdsLocker) + { + return _processIds.ToArray(); + } + } + + public void ClearProcessIds() + { + lock (_processIdsLocker) + { + _processIds.Clear(); + } + } + + /// + /// Returns the PPID of the given process. + /// + /// + /// + /// + public abstract int? GetParentId(int processId, string processName); + + /// + /// Returns the memory usage (%) of the given process. + /// + /// + public abstract float GetMemoryUsage(int processId, string processName); + + /// + /// Returns the CPU usage (%) of the given process. + /// + /// + public abstract float GetCpuUsage(int processId, string processName); + + /// + /// Continuously watching created processes. + /// + public virtual void WatchProcesses(int mainProcessId) + { + lock (_processIdsLocker) + { + ClearProcessIds(); + if (mainProcessId == 0) return; + AddProcess(mainProcessId); + AddChildProcesses(mainProcessId, Process.GetProcessById(mainProcessId).ProcessName); + } + } + + /// + /// Checks if the given process is related to the main process. + /// + /// + /// + private bool IsComposeProcess(int processId) + { + //snapshot if the process has already exited + if (Process.GetProcessById(processId) == null) return false; + + if (ContainsId(processId)) return true; + + var process = Process.GetProcessById(processId); + if (process.Id == 0) return false; + + var parentProcessId = GetParentId(processId, process.ProcessName); + + if (parentProcessId == null || parentProcessId == 0) return false; + + if (ContainsId((int)parentProcessId)) return true; + + return IsComposeProcess(Convert.ToInt32(parentProcessId)); + } + + /// + /// Searches for child processes to watch. + /// + public abstract ReadOnlySpan AddChildProcesses(int processId, string? processName); + + public abstract void StopWatchingProcesses(); + + /// + /// Checks if a process belongs to the Compose. + /// + /// + public bool CheckIfIsComposeProcess(int processId) + { + try + { + return IsComposeProcess(processId); + } + catch (Exception exception) + { + _logger.ProcessExpected(exception); + return false; + } + } + + /// + /// Sends a modified process information to publish + /// + /// + public void ProcessModifiedUpdate(int processId) + { + lock (_processIdsLocker) + { + if (!_processIds.Contains(processId)) return; + _processIdsSubject.OnNext(new(processId, ProcessStatus.Modified)); + } + } + + ~ProcessInfoMonitor() + { + Dispose(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public virtual void Dispose(bool disposing) { } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessStatus.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessStatus.cs similarity index 88% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessStatus.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessStatus.cs index 08f98893d..f12bea8b6 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessStatus.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Processes/ProcessStatus.cs @@ -10,10 +10,11 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ModuleProcessMonitor.Processes; +namespace ProcessExplorer.Abstractions.Processes; -public enum Status +public enum ProcessStatus { + Modified = 3, Terminated = 2, Running = 1, Stopped = 0 diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/ISubsystemController.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemController.cs similarity index 86% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/ISubsystemController.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemController.cs index ad4466163..8a82ac47e 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/ISubsystemController.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemController.cs @@ -10,18 +10,10 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using ModuleProcessMonitor.Subsystems; -using ProcessExplorer.Infrastructure; - -namespace ProcessExplorer.Subsystems; +namespace ProcessExplorer.Abstractions.Subsystems; public interface ISubsystemController { - /// - /// Communicator interface, which is used to send launch/shutdown and restart commands to the launcher. - /// - ISubsystemLauncherCommunicator SubsystemLauncherCommunicator { get; } - /// /// It gets the subsystems, automatically starts them if their AutomatedStart property set to true, and send the information to the declared UI's /// @@ -104,20 +96,6 @@ public interface ISubsystemController /// Task ShutdownSubsystems(IEnumerable subsystems); - /// - /// Adds a UIConnection to the store, this is a help method to register the UIs and give the IUIHandler an implementation, - /// - /// - /// - Task AddUIConnection(IUIHandler uiHandler); - - /// - /// Removes a UIHandler from the collection. - /// - /// - /// - Task RemoveUIConnection(IUIHandler uiHandler); - /// /// It will register a collection of subsystems, and save it into a list. Sends update to the UIs. /// @@ -138,7 +116,7 @@ public interface ISubsystemController /// /// /// - void RemoveSubsystem(Guid subsystemId); + Task RemoveSubsystem(Guid subsystemId); /// /// Modifies a state of a subsystem with the given data. Send update to the registered UIs. @@ -147,4 +125,10 @@ public interface ISubsystemController /// /// Task ModifySubsystemState(Guid subsystemId, string state); + + /// + /// Returns the initialized subsystems. + /// + /// + IEnumerable> GetSubsystems(); } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/ISubsystemLauncher.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemLauncher.cs similarity index 53% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/ISubsystemLauncher.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemLauncher.cs index 45d0b8365..9004c2de6 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/ISubsystemLauncher.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemLauncher.cs @@ -10,92 +10,61 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ModuleProcessMonitor.Subsystems; +namespace ProcessExplorer.Abstractions.Subsystems; public interface ISubsystemLauncher { - /// - /// Sets the available manifests, which are initialized through ModuleLoader. - /// - /// - void SetSubsystems(string serializedSubsystems); - - /// - /// Initializes all the subsystems, which are communicated via the selected communicated route. - /// - /// - ValueTask InitSubsystems(); - - /// - /// Adds a subsystem to the subsystemController's list. - /// - /// - /// - /// - ValueTask AddSubsystem(Guid subsystemId, SubsystemInfo subsystem); - - /// - /// Modifies a state of a subsystem in the subsystemController's list. - /// - /// - /// - /// - ValueTask ModifySubsystemState(Guid subsystemId, string state); - - /// - /// Removes a subsystem from the subsystemController's list. - /// - /// - /// - ValueTask RemoveSubsystem(Guid subsystemId); - /// /// Sends launch command to the subsystem module via the selected communication route. /// /// + /// /// - ValueTask LaunchSubsystem(Guid subsystemId); + Task LaunchSubsystem(Guid subsystemId, string subsystemName); /// /// Sends launch command (after a timeperiod) to the subsystem module via the selected communication route. /// /// + /// /// /// - ValueTask LaunchSubsystemAfterTime(Guid subsystemId, int periodOfTime); + Task LaunchSubsystemAfterTime(Guid subsystemId, string subsystemName, int periodOfTime); /// /// Sends launch command to the subsystem module via the selected communication route. /// /// /// - ValueTask>> LaunchSubsystems(IEnumerable subsystems); + Task>> LaunchSubsystems(IEnumerable> subsystems); /// /// Sends restart command to the subsystem module via the selected communication route. /// /// + /// /// - ValueTask RestartSubsystem(Guid subsystemId); + Task RestartSubsystem(Guid subsystemId, string subsystemName); /// /// Sends restart command to the subsystem module via the selected communication route. /// /// /// - ValueTask>> RestartSubsystems(IEnumerable subsystems); + Task>> RestartSubsystems(IEnumerable> subsystems); /// /// Sends shutdown command to the subsystem module via the selected communication route. /// /// + /// /// - ValueTask ShutdownSubsystem(Guid subsystemId); + Task ShutdownSubsystem(Guid subsystemId, string subsystemName); /// /// Sends shutdown command to the subsystem module via the selected communication route. /// /// /// - ValueTask>> ShutdownSubsystems(IEnumerable subsystems); + Task>> ShutdownSubsystems(IEnumerable> subsystems); } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/ISubsystemLauncherCommunicator.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemLauncherCommunicator.cs similarity index 78% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/ISubsystemLauncherCommunicator.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemLauncherCommunicator.cs index fa31f6f12..3be0a48e9 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/ISubsystemLauncherCommunicator.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/ISubsystemLauncherCommunicator.cs @@ -10,8 +10,7 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. - -namespace ProcessExplorer.Subsystems; +namespace ProcessExplorer.Abstractions.Subsystems; public interface ISubsystemLauncherCommunicator { @@ -19,34 +18,35 @@ public interface ISubsystemLauncherCommunicator /// Initializes the route of the communication defined by the user. /// /// - ValueTask InitializeCommunicationRoute(); + Task InitializeCommunicationRoute(); /// /// Sends a launch request to the launcher, which will launch the subsystem after the given timeperiod. /// /// + /// /// /// A state of the sent subsystem, regarding the success of the launch. - ValueTask SendLaunchSubsystemAfterTimeRequest(Guid subsystemId, int periodOfTime); + Task SendLaunchSubsystemAfterTimeRequest(Guid subsystemId, string subsystemName, int periodOfTime); /// /// Sends launch requests to the launcher. /// /// /// A list of the states of the sent subsystems, regarding the success of the launches. - ValueTask SendLaunchSubsystemsRequest(IEnumerable subsystems); + Task SendLaunchSubsystemsRequest(IEnumerable> subsystems); /// /// Sends restart requests to the launcher. /// /// /// A list of the states of the sent subsystems, regarding the success of the restarts. - ValueTask SendRestartSubsystemsRequest(IEnumerable subsystems); + Task SendRestartSubsystemsRequest(IEnumerable> subsystems); /// /// Sends shutdown requests to the launcher. /// /// /// A list of the states of the sent subsystems, regarding the success of the shutdowns. - ValueTask SendShutdownSubsystemsRequest(IEnumerable subsystems); + Task SendShutdownSubsystemsRequest(IEnumerable> subsystems); } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/SubsystemInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/SubsystemInfo.cs similarity index 64% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/SubsystemInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/SubsystemInfo.cs index f846f9b67..48c93b64a 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/SubsystemInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/SubsystemInfo.cs @@ -10,13 +10,14 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ModuleProcessMonitor.Subsystems; +namespace ProcessExplorer.Abstractions.Subsystems; +//TODO(Lilla): define ProtoContract to derive it implicitly without protoconverthelper public class SubsystemInfo { public string Name { get; set; } = string.Empty; - public string StartupType { get; set; } - public string UIType { get; set; } + public string StartupType { get; set; } = string.Empty; + public string UIType { get; set; } = string.Empty; public string Path { get; set; } = string.Empty; public string? Url { get; set; } public string[]? Arguments { get; set; } @@ -24,4 +25,16 @@ public class SubsystemInfo public string State { get; set; } = SubsystemState.Stopped; public string? Description { get; set; } public bool AutomatedStart { get; set; } = false; + + public static SubsystemInfo FromModule(Module module) => new() + { + Name = module.Name, + StartupType = module.StartupType, + UIType = module.UIType, + Path = module.Path, + Url = module.Url, + Arguments = module.Arguments, + Port = module.Port, + State = module.State, + }; } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/SubsystemState.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/SubsystemState.cs similarity index 94% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/SubsystemState.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/SubsystemState.cs index 5dfc15409..db9fe4fbd 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/SubsystemState.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Abstractions/Subsystems/SubsystemState.cs @@ -10,7 +10,7 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ModuleProcessMonitor.Subsystems; +namespace ProcessExplorer.Abstractions.Subsystems; public class SubsystemState { diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/DependencyInjection/ServiceCollectionProcessExplorerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/DependencyInjection/ServiceCollectionProcessExplorerExtensions.cs new file mode 100644 index 000000000..76bc51502 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/DependencyInjection/ServiceCollectionProcessExplorerExtensions.cs @@ -0,0 +1,67 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.Processes; +using ProcessExplorer.Core.Subsystems; + +namespace ProcessExplorer.Core.DependencyInjection; + +public static class ServiceCollectionProcessExplorerExtensions +{ + public static IServiceCollection AddProcessExplorerAggregator( + this IServiceCollection serviceCollection) + { + serviceCollection.TryAddSingleton(); + return serviceCollection; + } + + public static IServiceCollection AddProcessMonitorWindows( + this IServiceCollection serviceCollection) + { +#pragma warning disable CA1416 // Validate platform compatibility + serviceCollection.TryAddSingleton(); +#pragma warning restore CA1416 // Validate platform compatibility + return serviceCollection; + } + + public static IServiceCollection ConfigureSubsystemLauncher( + this IServiceCollection serviceCollection, + Action? launchRequest, + Action? stopRequest, + Func? launcRequestCtor, + Func? stopRequestCtor) + { + serviceCollection.TryAddSingleton>(); + + serviceCollection.Configure>(op => + { + op.LaunchRequest = launchRequest; + op.StopRequest = stopRequest; + op.CreateLaunchRequest = launcRequestCtor; + op.CreateStopRequest = stopRequestCtor; + }); + + return serviceCollection; + } + + public static IServiceCollection AddSubsystemController(this IServiceCollection serviceCollection) + { + serviceCollection.TryAddSingleton(); + + return serviceCollection; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/ProxyObjects/ISubsystemServiceObject.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/DependencyInjection/SubsystemLauncherOptions.cs similarity index 51% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/ProxyObjects/ISubsystemServiceObject.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/DependencyInjection/SubsystemLauncherOptions.cs index 0c1ea8db9..8f136afa9 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/ProxyObjects/ISubsystemServiceObject.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/DependencyInjection/SubsystemLauncherOptions.cs @@ -10,14 +10,15 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using ModuleProcessMonitor.Subsystems; +using Microsoft.Extensions.Options; -namespace SuperRPC_POC.Protocol.ProxyObjects; +namespace ProcessExplorer.Core.DependencyInjection; -public interface ISubsystemServiceObject +internal class SubsystemLauncherOptions : IOptions> { - Task AddSubsystemsAsync(IEnumerable> subsystems); - Task AddSubsystemAsync(string subsystemId, SubsystemInfo subsystem); - Task RemoveSubsystemAsync(string subsystemId); - Task UpdateSubsystemInfoAsync(string subsystemId, SubsystemInfo subsystemInfo); + public Action? LaunchRequest { get; set; } + public Action? StopRequest { get; set; } + public Func? CreateLaunchRequest { get; set; } + public Func? CreateStopRequest { get; set; } + public SubsystemLauncherOptions Value => this; } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Factories/ProcessAggregatorFactory.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/ProcessAggregatorFactory.cs similarity index 56% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Factories/ProcessAggregatorFactory.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/ProcessAggregatorFactory.cs index 876385f9e..b83d7aabb 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Factories/ProcessAggregatorFactory.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/ProcessAggregatorFactory.cs @@ -10,26 +10,22 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using LocalCollector.Communicator; using Microsoft.Extensions.Logging; -using ModuleProcessMonitor.Processes; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; -namespace ProcessExplorer.Factories; +namespace ProcessExplorer.Core.Factories; public static class ProcessAggregatorFactory { - public static ICommunicator CreateCommunicator(IProcessInfoAggregator processAggregator) + public static IProcessInfoAggregator CreateProcessInfoAggregator( + ProcessInfoMonitor processInfoMonitor, + IUiHandler handler, + ISubsystemController subsystemController, + ILogger? logger = null) { - return new Infrastructure.Communicator(processAggregator); - } - - public static IProcessInfoAggregator CreateProcessInfoAggregator(ILogger logger, IProcessMonitor? processMonitor) - { - return new ProcessInfoAggregator(logger, processMonitor); - } - - public static IProcessInfoAggregator CreateProcessInfoAggregator(ILogger logger) - { - return CreateProcessInfoAggregator(logger, null); + return new ProcessInfoAggregator(processInfoMonitor, handler, subsystemController, logger); } } diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Factories/SubsystemFactory.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/ProcessMonitorFactory.cs similarity index 60% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Factories/SubsystemFactory.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/ProcessMonitorFactory.cs index 8e0dbabe0..2b43fd174 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Factories/SubsystemFactory.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/ProcessMonitorFactory.cs @@ -11,14 +11,16 @@ // and limitations under the License. using Microsoft.Extensions.Logging; -using ProcessExplorer.Subsystems; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Core.Processes; -namespace ProcessExplorer.Extensions; - -public static class SubsystemFactory +namespace ProcessExplorer.Core.Factories; +public static class ProcessMonitorFactory { - public static ISubsystemController CreateSubsystemController(ISubsystemLauncherCommunicator subsystemCommunicator, ILogger logger) + public static ProcessInfoMonitor CreateProcessInfoMonitorWindows(ILogger logger) { - return new SubsystemController(subsystemCommunicator, logger); +#pragma warning disable CA1416 // Validate platform compatibility + return new WindowsProcessInfoMonitor(logger); +#pragma warning restore CA1416 // Validate platform compatibility } } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/SubsystemFactory.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/SubsystemFactory.cs new file mode 100644 index 000000000..e2a557093 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Factories/SubsystemFactory.cs @@ -0,0 +1,37 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.Logging; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.Subsystems; + +namespace ProcessExplorer.Core.Factories; + +public static class SubsystemFactory +{ + public static ISubsystemController CreateSubsystemController( + ISubsystemLauncherCommunicator subsystemCommunicator, + IUiHandler uiHandler, + ILogger? logger) + { + return new SubsystemController(subsystemCommunicator, uiHandler, logger); + } + + public static ISubsystemController CreateSubsystemController( + ISubsystemLauncher subsystemLauncher, + IUiHandler uiHandler, + ILogger? logger) + { + return new SubsystemController(subsystemLauncher, uiHandler, logger); + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/Communicator.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Infrastructure/Communicator.cs similarity index 60% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/Communicator.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Infrastructure/Communicator.cs index 87f817d82..92dadb80e 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/Communicator.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Infrastructure/Communicator.cs @@ -10,29 +10,26 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -using LocalCollector; -using LocalCollector.Communicator; -using LocalCollector.Connections; -using LocalCollector.Modules; -using LocalCollector.Registrations; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Infrastructure; -namespace ProcessExplorer.Infrastructure; +namespace ProcessExplorer.Core.Infrastructure; +//TODO(Lilla): refactor so it is longer using proxy based callings internal class Communicator : ICommunicator { private IProcessInfoAggregator _aggregator; public Communicator(IProcessInfoAggregator processAggregator) { - this._aggregator = processAggregator; + _aggregator = processAggregator; } - public void SetProcessInfoAggregator(IProcessInfoAggregator aggregator) - { - this._aggregator = aggregator; - } - - public async ValueTask AddRuntimeInfo(IEnumerable> listOfRuntimeInfos) + public async ValueTask AddRuntimeInfo(IEnumerable> listOfRuntimeInfos) { if (listOfRuntimeInfos == null) return; @@ -40,63 +37,63 @@ public async ValueTask AddRuntimeInfo(IEnumerable>> connections) + public async ValueTask AddConnectionCollection(IEnumerable>> connections) { - if(connections == null) return; + if (connections == null) return; - foreach(var connection in connections) + foreach (var connection in connections) { - if(connection.Value == null || connection.Key.Name == string.Empty) continue; + if (connection.Value == null || connection.Key.Name == string.Empty) continue; await _aggregator.AddConnectionCollection(connection.Key.Name, connection.Value); } } - public async ValueTask UpdateConnectionInformation(IEnumerable> connections) + public async ValueTask UpdateConnectionInformation(IEnumerable> connections) { if (connections == null) return; foreach (var connection in connections) { if (connection.Value == null || connection.Key.Name == string.Empty) continue; - await _aggregator.UpdateConnectionInfo(connection.Key.Name, connection.Value); + await _aggregator.UpdateOrAddConnectionInfo(connection.Key.Name, connection.Value); } } - public async ValueTask UpdateEnvironmentVariableInformation(IEnumerable>>> environmentVariables) + public async ValueTask UpdateEnvironmentVariableInformation(IEnumerable>>> environmentVariables) { if (environmentVariables == null) return; foreach (var env in environmentVariables) { if (env.Value == null || env.Key.Name == string.Empty) continue; - await _aggregator.UpdateEnvironmentVariablesInfo(env.Key.Name, env.Value); + await _aggregator.UpdateOrAddEnvironmentVariablesInfo(env.Key.Name, env.Value); } } - public async ValueTask UpdateRegistrationInformation(IEnumerable>> registrations) + public async ValueTask UpdateRegistrationInformation(IEnumerable>> registrations) { if (registrations == null) return; foreach (var registration in registrations) { if (registration.Value == null || registration.Key.Name == string.Empty) continue; - await _aggregator.UpdateRegistrationInfo(registration.Key.Name, registration.Value); + await _aggregator.UpdateRegistrations(registration.Key.Name, registration.Value); } } - public async ValueTask UpdateModuleInformation(IEnumerable>> modules) + public async ValueTask UpdateModuleInformation(IEnumerable>> modules) { if (modules == null) return; foreach (var module in modules) { if (module.Value == null || module.Key.Name == string.Empty) continue; - await _aggregator.UpdateModuleInfo(module.Key.Name, module.Value); + await _aggregator.UpdateOrAddModuleInfo(module.Key.Name, module.Value); } } } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/ProcessExplorer.Core.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/ProcessExplorer.Core.csproj new file mode 100644 index 000000000..9d9664d53 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/ProcessExplorer.Core.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + enable + true + enable + + + + + + + + + + + diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/ProcessInfoAggregator.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/ProcessInfoAggregator.cs new file mode 100644 index 000000000..2b6183e35 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/ProcessInfoAggregator.cs @@ -0,0 +1,319 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Reactive.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Logging; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.Processes; + +namespace ProcessExplorer.Core; + +internal class ProcessInfoAggregator : IProcessInfoAggregator +{ + private readonly ILogger _logger; + private readonly IProcessInfoMonitor _processInfoMonitor; + private readonly IUiHandler _handler; + private readonly ISubsystemController _subsystemController; + + private readonly ConcurrentDictionary _processInformation = new(); + //putting subsystem change messages to the queue and remove it if it has been sent ~ FIFO + private readonly ConcurrentQueue> _subsystemStateChanges = new(); + + public ISubsystemController SubsystemController => _subsystemController; + public IUiHandler UiHandler => _handler; + public int TerminatingProcessDelay { get; private set; } = 1000; + public int MainProcessId { get; set; } + + public ProcessInfoAggregator( + IProcessInfoMonitor processInfoMonitor, + IUiHandler handler, + ISubsystemController subsystemController, + ILogger? logger = null) + { + _logger = logger ?? NullLogger.Instance; + _handler = handler; + _processInfoMonitor = processInfoMonitor; + _subsystemController = subsystemController; + + _processInfoMonitor.ProcessIds + .Select(kvp => Observable.FromAsync(async () => await PushNotification(kvp))) + .Concat() + .Subscribe(); + } + + private async Task PushNotification(KeyValuePair kvp) + { + switch (kvp.Value) + { + case ProcessStatus.Running: + await ProcessCreated(kvp.Key); + break; + + case ProcessStatus.Terminated: + case ProcessStatus.Stopped: + await ProcessTerminated(kvp.Key); + break; + + case ProcessStatus.Modified: + await ProcessModified(kvp.Key); + break; + + default: + return; + } + } + + private void UpdateProcessInfoCollectorData(string assemblyId, ProcessInfoCollectorData data) + { + _processInformation.AddOrUpdate(assemblyId, data, (_, _) => data); + } + + private IEnumerable GetProcesses(ReadOnlySpan processIds) + { + var processes = new List(); + + foreach (var id in processIds) + { + var process = ProcessInformation.GetProcessInfoWithCalculatedData(Process.GetProcessById(id), _processInfoMonitor); + processes.Add(process.ProcessInfo); + } + + return processes; + } + + private async Task ProcessTerminated(int processId) + { + _logger.ProcessTerminatedInformation(processId); + await ProcessStatusChanged(new(processId, ProcessStatus.Terminated)); + + await Task.Run(() => + { + Task.Delay(TerminatingProcessDelay); + }); + + var processes = GetProcesses(_processInfoMonitor.GetProcessIds()); + + await _handler.TerminateProcess(processId); + await _handler.AddProcesses(processes); + } + + private async Task ProcessCreated(int processId) + { + var process = GetProcess(processId); + + if (process == null) return; + + _logger.ProcessCreatedInformation(processId); + + await _handler.AddProcess(process); + } + + private ProcessInfoData? GetProcess(int processId) + { + var process = GetProcesses(_processInfoMonitor.GetProcessIds()).FirstOrDefault(proc => proc.ProcessId == processId); + + return process ?? null; + } + + private async Task ProcessModified(int processId) + { + var process = GetProcess(processId); + if (process == null) return; + + _logger.ProcessModifiedDebug(processId); + + await _handler.UpdateProcess(process); + } + + private async Task ProcessStatusChanged(KeyValuePair process) + { + await _handler.UpdateProcessStatus(process); + } + + public async Task RunSubsystemStateQueue(CancellationToken cancellationToken) + { + //TODO(Lilla): should i send here a warning if cancellationToken is default? + while (!cancellationToken.IsCancellationRequested) + { + var succeed = _subsystemStateChanges.TryDequeue(out var subsystemInfo); + if (succeed) await SubsystemController.ModifySubsystemState(subsystemInfo.Key, subsystemInfo.Value); + } + } + + public IEnumerable GetProcesses() + { + var processIds = _processInfoMonitor.GetProcessIds(); + return GetProcesses(processIds); + } + + public async Task AddRuntimeInformation(string assemblyId, ProcessInfoCollectorData runtimeInfo) + { + _processInformation.AddOrUpdate(assemblyId, runtimeInfo, (_, _) => runtimeInfo); + + await _handler.AddRuntimeInfo(assemblyId, runtimeInfo); + } + + public void RemoveRuntimeInformation(string assembly) + { + if (!_processInformation.TryRemove(assembly, out _)) _logger.UnableToRemoveRuntimeInformationError(assembly); + } + + public void SetDeadProcessRemovalDelay(int delay) + { + TerminatingProcessDelay = delay * 100; + } + + private ProcessInfoCollectorData? GetRuntimeInformation(string assemblyId) + { + _processInformation.TryGetValue(assemblyId, out var data); + + return data; + } + + public async Task AddConnectionCollection(string assemblyId, IEnumerable connections) + { + var runtimeInfoToModify = GetRuntimeInformation(assemblyId); + + if (runtimeInfoToModify == null) return; + + try + { + runtimeInfoToModify.AddOrUpdateConnections(connections); + UpdateProcessInfoCollectorData(assemblyId, runtimeInfoToModify); + } + catch (Exception exception) + { + _logger.ConnectionCollectionCannotBeAddedError(exception); + } + + await _handler.AddConnections(assemblyId, connections); + } + + public async Task UpdateOrAddConnectionInfo(string assemblyId, ConnectionInfo connectionInfo) + { + var runtimeInfoToModify = GetRuntimeInformation(assemblyId); + + if (runtimeInfoToModify == null) return; + + try + { + runtimeInfoToModify.UpdateConnection(connectionInfo); + UpdateProcessInfoCollectorData(assemblyId, runtimeInfoToModify); + } + catch (Exception exception) + { + _logger.ConnectionCannotBeUpdatedError(exception); + } + + await _handler.UpdateConnection(assemblyId, connectionInfo); + } + + public async Task UpdateOrAddEnvironmentVariablesInfo(string assemblyId, IEnumerable> environmentVariables) + { + var runtimeInfoToModify = GetRuntimeInformation(assemblyId); + + if (runtimeInfoToModify == null) return; + + try + { + runtimeInfoToModify.UpdateOrAddEnvironmentVariables(environmentVariables); + UpdateProcessInfoCollectorData(assemblyId, runtimeInfoToModify); + } + catch (Exception exception) + { + _logger.EnvironmentVariablesCannotBeUpdatedError(exception); + } + + await _handler.UpdateEnvironmentVariables(assemblyId, environmentVariables); + } + + public async Task UpdateRegistrations(string assemblyId, IEnumerable registrations) + { + var runtimeInfoToModify = GetRuntimeInformation(assemblyId); + + if (runtimeInfoToModify == null) return; + + try + { + runtimeInfoToModify.UpdateOrAddRegistrations(registrations); + UpdateProcessInfoCollectorData(assemblyId, runtimeInfoToModify); + } + catch (Exception exception) + { + _logger.RegistrationsCannotBeUpdatedError(exception); + } + + await _handler.UpdateRegistrations(assemblyId, registrations); + } + + public async Task UpdateOrAddModuleInfo(string assemblyId, IEnumerable modules) + { + var runtimeInfoToModify = GetRuntimeInformation(assemblyId); + + if (runtimeInfoToModify == null) return; + + try + { + runtimeInfoToModify.UpdateOrAddModules(modules); + UpdateProcessInfoCollectorData(assemblyId, runtimeInfoToModify); + } + catch (Exception exception) + { + _logger.ModulesCannotBeUpdatedError(exception); + } + + await _handler.UpdateModules(assemblyId, modules); + } + + public void EnableWatchingSavedProcesses() + { + _processInfoMonitor.WatchProcesses(MainProcessId); + } + + public void DisableWatchingProcesses() + { + _processInfoMonitor.StopWatchingProcesses(); + } + + public void InitProcesses(ReadOnlySpan processIds) + { + _processInfoMonitor.ClearProcessIds(); + _processInfoMonitor.SetProcessIds(MainProcessId, processIds); + } + + public IEnumerable> GetRuntimeInformation() + { + return _processInformation; + } + + public void ScheduleSubsystemStateChanged(Guid instanceId, string state) + { + _subsystemStateChanges.Enqueue(new(instanceId, state)); + } + + public Task AddProcesses(ReadOnlySpan processes) + { + _processInfoMonitor.SetProcessIds(MainProcessId, processes); + return Task.CompletedTask; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInformation.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Processes/ProcessInformation.cs similarity index 61% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInformation.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Processes/ProcessInformation.cs index 3f747d5d1..fecb50302 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInformation.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Processes/ProcessInformation.cs @@ -12,86 +12,75 @@ using System.ComponentModel; using System.Diagnostics; +using ProcessExplorer.Abstractions.Extensions; +using ProcessExplorer.Abstractions.Processes; -namespace ModuleProcessMonitor.Processes; +namespace ProcessExplorer.Core.Processes; [Serializable] public class ProcessInformation { - private ProcessInfoData _processInfo = new(); + private ProcessInfoData _processInfo; public ProcessInfoData ProcessInfo { get { return _processInfo; } - internal set + private set { _processInfo = value; } } - public ProcessInformation(string name, Guid instanceId, string uiType, string uiHint, int pid) - { - ProcessInfo.InstanceId = instanceId; - ProcessInfo.UiType = uiType; - ProcessInfo.UiHint = uiHint; - ProcessInfo.PID = pid; - ProcessInfo.ProcessName = name; - } - public ProcessInformation(Process process) { - ProcessInfo.PID = process.Id; - ProcessInfo.ProcessName = process.ProcessName; - ProcessInfo.InstanceId = Guid.NewGuid(); + _processInfo = new() + { + ProcessId = process.Id, + ProcessName = process.ProcessName, + }; } - internal static ProcessInformation GetProcessInfoWithCalculatedData(Process process, ProcessInfoManager processInfoManager) + internal static ProcessInformation GetProcessInfoWithCalculatedData(Process process, IProcessInfoMonitor processMonitor) { var processInformation = new ProcessInformation(process); - SetProcessInfoData(processInformation, processInfoManager); + SetProcessInfoData(processInformation, processMonitor); return processInformation; } - internal static void SetProcessInfoData(ProcessInformation processInfo, ProcessInfoManager manager) + internal static void SetProcessInfoData(ProcessInformation processInfo, IProcessInfoMonitor manager) { try { - var process = Process.GetProcessById((int)processInfo.ProcessInfo.PID!); + var process = Process.GetProcessById(processInfo.ProcessInfo.ProcessId); process.Refresh(); processInfo._processInfo.PriorityLevel = process.BasePriority; processInfo._processInfo.PrivateMemoryUsage = process.PrivateMemorySize64; - processInfo._processInfo.ParentId = manager.GetParentId(process); - processInfo._processInfo.MemoryUsage = manager.GetMemoryUsage(process); - processInfo._processInfo.ProcessorUsage = manager.GetCpuUsage(process); + processInfo._processInfo.ParentId = manager.GetParentId(process.Id, process.ProcessName); + processInfo._processInfo.MemoryUsage = manager.GetMemoryUsage(process.Id, process.ProcessName); + processInfo._processInfo.ProcessorUsage = manager.GetCpuUsage(process.Id, process.ProcessName); processInfo._processInfo.StartTime = process.StartTime.ToString("yyyy.MM.dd. hh:mm:s"); processInfo._processInfo.ProcessorUsageTime = process.TotalProcessorTime; processInfo._processInfo.PhysicalMemoryUsageBit = process.WorkingSet64; processInfo._processInfo.ProcessPriorityClass = process.PriorityClass.ToStringCached(); processInfo._processInfo.VirtualMemorySize = process.VirtualMemorySize64; - var list = new SynchronizedCollection(); - - for (int i = 0; i < process.Threads.Count; i++) - { - var thread = ProcessThreadInfo.FromProcessThread(process.Threads[i]); - if (thread == null) continue; - list.Add(thread); - } + var array = new ProcessThread[process.Threads.Count]; + process.Threads.CopyTo(array, 0); - processInfo._processInfo.Threads = list; + processInfo._processInfo.Threads = array; processInfo._processInfo.ProcessStatus = process.HasExited == false ? - Status.Running.ToStringCached() - : Status.Stopped.ToStringCached(); + ProcessStatus.Running.ToStringCached() + : ProcessStatus.Stopped.ToStringCached(); } catch (Exception exception) { if (exception is Win32Exception || exception is NotSupportedException) return; - processInfo._processInfo.ProcessStatus = Status.Terminated.ToStringCached(); + processInfo._processInfo.ProcessStatus = ProcessStatus.Terminated.ToStringCached(); } } } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Processes/WindowsProcessMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Processes/WindowsProcessMonitor.cs new file mode 100644 index 000000000..0bc750b2c --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Processes/WindowsProcessMonitor.cs @@ -0,0 +1,367 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Management; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions.Logging; +using ProcessExplorer.Abstractions.Processes; + +namespace ProcessExplorer.Core.Processes; + +[System.Runtime.Versioning.SupportedOSPlatform("windows")] +internal class WindowsProcessInfoMonitor : ProcessInfoMonitor +{ + private readonly ILogger _logger; + private readonly ConcurrentDictionary _cpuPerformanceCounters; + private readonly ConcurrentDictionary _memoryPerformanceCounters; + private readonly ConcurrentDictionary _managementPidObjectSearchers; + private readonly ConcurrentDictionary _managementPPidObjectSearchers; + + private ManagementEventWatcher? _watcher; + private bool _disposed = false; + private readonly object _lock = new(); + public WindowsProcessInfoMonitor(ILogger? logger) + :base(logger) + { + _logger = logger ?? NullLogger.Instance; + _cpuPerformanceCounters = new(); + _memoryPerformanceCounters = new(); + _managementPidObjectSearchers = new(); + _managementPPidObjectSearchers = new(); + } + + public override void StopWatchingProcesses() + { + if (_watcher == null) return; + _watcher.Stop(); + } + + public override int? GetParentId(int processId, string processName) + { + var parentProcessId = 0; + + try + { + if (Process.GetProcessById(processId) == null) return null; + + var managementObjectSearcher = _managementPPidObjectSearchers.GetOrAdd(processId, _ => new ManagementObjectSearcher( + $"Select ParentProcessId From Win32_Process Where ProcessID={processId}")); + + + using var mo = managementObjectSearcher.Get(); + var deviceArray = new ManagementBaseObject[mo.Count]; + + mo.CopyTo(deviceArray, 0); + + if (deviceArray.Length <= 0) return null; + + parentProcessId = Convert.ToInt32(deviceArray.First()["ParentProcessId"]); + } + catch (Exception exception) + { + _logger.ManagementObjectPpidExpected(processId, exception); + return null; + } + + return parentProcessId; + } + + public override float GetMemoryUsage(int processId, string? processName) + { + int memsize; + + if (processName == null) return default; + + using var memoryPerformanceCounter = _memoryPerformanceCounters.GetOrAdd(processId, _ => new PerformanceCounter() + { + CategoryName = "Process", + CounterName = "Working Set - Private", + InstanceName = processName, + }); + + memsize = Convert.ToInt32(memoryPerformanceCounter.NextValue()) / Convert.ToInt32(1024) / Convert.ToInt32(1024); + + return (float)(memsize / GetTotalMemoryInMb() * 100); + } + + private static double GetTotalMemoryInMb() + { + var gcMemoryInfo = GC.GetGCMemoryInfo(); + var installedMemory = gcMemoryInfo.TotalAvailableMemoryBytes; + return Convert.ToDouble(installedMemory) / 1048576.0; + } + + public override float GetCpuUsage(int processId, string? processName) + { + if (processName == null) return default; + + using var cpuPerformanceCounter = _memoryPerformanceCounters.GetOrAdd( + processId, _ => + { + return new PerformanceCounter( + "Process", + "% Processor Time", + processName, + true); + }); + + + cpuPerformanceCounter.NextValue(); + + var processCpuUsage = cpuPerformanceCounter.NextValue(); + + return processCpuUsage / Environment.ProcessorCount; + } + + private ReadOnlySpan GetChildProcesses(int processId, string processName) + { + if (processName == null) return default; + + using var managementObjectSearcher = _managementPidObjectSearchers.GetOrAdd(processId, _ => new ManagementObjectSearcher( + string.Format("Select ProcessId From Win32_Process Where ParentProcessID={0} Or ProcessID={0}", processId))); + + var managementCollection = managementObjectSearcher.Get(); + var children = new int[managementCollection.Count]; + + var i = 0; + + foreach (var managementBaseObject in managementCollection) + { + using var managementObject = (ManagementObject)managementBaseObject; + + try + { + var childProcessId = Convert.ToInt32(managementObject["ProcessId"]); + children[i] = childProcessId; + i++; + + managementCollection = managementObjectSearcher.Get(); + } + catch (Exception exception) + { + _logger.ChildProcessExpected(exception); + } + } + + return children; + } + + public override void WatchProcesses(int mainProcessId) + { + _logger.ProcessMonitorEnabledDebug(); + + base.WatchProcesses(mainProcessId); + + const string wmiQuery = +"SELECT TargetInstance.ProcessId " + +"FROM __InstanceOperationEvent WITHIN 3 " + +"WHERE TargetInstance ISA 'Win32_Process'"; + + try + { + if(_watcher == null) + { + var scope = new ManagementScope(@"\\.\root\CIMV2"); + scope.Connect(); + + _watcher = new ManagementEventWatcher(scope, new EventQuery(wmiQuery)); + _watcher.EventArrived += WmiEventHandler; + } + + _watcher.Start(); + } + catch (Exception exception) + { + _logger.WatcherInitializationError(exception); + } + } + + public override ReadOnlySpan AddChildProcesses(int processId, string? processName) + { + lock (_lock) + { + if (!ContainsId(processId)) + { + AddProcess(processId); + } + } + + var processes = new List() { processId }; + + try + { + var childrenProcessIds = GetChildProcesses(processId, processName ?? string.Empty); + + foreach (var childProcessId in childrenProcessIds) + { + if (childProcessId == processId) continue; + + processes.Add(childProcessId); + + AddIfComposeProcess(childProcessId); + + var childrenOfChildIds = AddChildProcesses( + childProcessId, + GetProcessIfProcessIdExists(childProcessId)?.ProcessName ?? null); + + foreach (var childOfChildId in childrenOfChildIds) + { + if (processes.Contains(childOfChildId)) continue; + + processes.Add(childOfChildId); + AddIfComposeProcess(childOfChildId); + } + } + } + catch (Exception exception) + { + _logger.PpidExpected(processId, exception); + } + + return processes.ToArray(); + } + + private void AddIfComposeProcess(int processId) + { + lock (_lock) + { + if (!CheckIfIsComposeProcess(processId)) return; + + var alreadyAdded = ContainsId(processId); + if (alreadyAdded) return; + + AddProcess(processId); + } + } + + private void WmiEventHandler(object sender, EventArrivedEventArgs e) + { + var processId = Convert.ToInt32( + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["ProcessId"]); + + var eventDefinition = e.NewEvent.SystemProperties["__Class"] + .Value + .ToString(); + + if (eventDefinition == null) return; + + try + { + switch (eventDefinition) + { + case "__InstanceCreationEvent": + InstanceCreated(processId); + break; + + case "__InstanceDeletionEvent": + InstanceDeleted(processId); + break; + + case "__InstanceModificationEvent": + InstanceModified(processId); + break; + } + } + catch (Exception exception) + { + _logger.InstanceEventExpected(exception); + } + } + + private void InstanceModified(int processId) + { + lock (_lock) + { + if (ContainsId(processId)) + { + ProcessModifiedUpdate(processId); + } + } + } + + private void InstanceCreated(int processId) + { + var process = GetProcessIfProcessIdExists(processId); + + if (process == null) return; + + lock (_lock) + { + if (!CheckIfIsComposeProcess(processId)) return; + + AddProcess(processId); + } + } + + private void InstanceDeleted(int processId) + { + var _cpuPerformanceCounterRemoved = _cpuPerformanceCounters.TryRemove(processId, out var cpuPerf); + if (_cpuPerformanceCounterRemoved && cpuPerf != null) + { + cpuPerf.Close(); + cpuPerf.Dispose(); + } + + var memoryPerformanceCounterRemoved = _memoryPerformanceCounters.TryRemove(processId, out var memoryPerf); + if (memoryPerformanceCounterRemoved && memoryPerf != null) + { + memoryPerf.Close(); + memoryPerf.Dispose(); + } + + var managementPidSearcherRemoved = _managementPidObjectSearchers.TryRemove(processId, out var objectSearcher); + if (managementPidSearcherRemoved && objectSearcher != null) objectSearcher.Dispose(); + + lock (_lock) + { + RemoveProcessId(processId); + } + } + + private static Process? GetProcessIfProcessIdExists(int processId) + { + try + { + var process = Process.GetProcessById(processId); + process.Refresh(); + return process.Id == 0 ? null : process; + } + catch (Exception) + { + return null; + } + } + + public override void Dispose(bool disposing) + { + ReleaseWatcher(true); + base.Dispose(disposing); + } + + protected virtual void ReleaseWatcher(bool disposing) + { + if (_disposed) return; + + if (disposing) + { + if (_watcher == null) return; + + _watcher.EventArrived -= WmiEventHandler; + _watcher.Stop(); + _watcher.Dispose(); + } + _disposed = true; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Subsystems/SubsystemController.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Subsystems/SubsystemController.cs new file mode 100644 index 000000000..86ed702c5 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Subsystems/SubsystemController.cs @@ -0,0 +1,439 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.Concurrent; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Logging; +using ProcessExplorer.Abstractions.Subsystems; + +namespace ProcessExplorer.Core.Subsystems; + +/// +/// Gets the messages from the UI and sends command to the subsystemHandler (proxy object) +/// +internal class SubsystemController : ISubsystemController +{ + private readonly ConcurrentDictionary _subsystems = new(); + private readonly object _subsystemLock = new(); + private readonly ILogger _logger; + + //We are allowing that to users to create their own backend server or their own SubsystemLauncher, without depending on certain types and without circular dependency. + //We are using the _subsystemLauncher in the Server project. + private readonly ISubsystemLauncherCommunicator? _subsystemLauncherCommunicator; + private readonly IUiHandler _handler; + private readonly ISubsystemLauncher? _subsystemLauncher; + + public SubsystemController(IUiHandler handler, ILogger? logger = null) + { + _handler = handler; + _logger = logger ?? NullLogger.Instance; + } + + public SubsystemController( + ISubsystemLauncher subsystemLauncher, + IUiHandler uiHandler, + ILogger? logger = null) + :this(uiHandler, logger) + { + _subsystemLauncher = subsystemLauncher; + } + + public SubsystemController( + ISubsystemLauncherCommunicator subsystemLauncherCommunicator, + IUiHandler uiHandler, + ILogger? logger = null) + :this(uiHandler, logger) + { + _subsystemLauncherCommunicator = subsystemLauncherCommunicator; + } + + public async Task InitializeSubsystems(IEnumerable> subsystems) + { + if (subsystems == null || !subsystems.Any()) return; + + UpdateOrAddElements(subsystems); + + await SendModifiedSubsystems(); + await LaunchSubsystemsAutomatically(); + } + + public async Task LaunchAllRegisteredSubsystem() + { + try + { + var subsystemIds = Enumerable.Empty>(); + + lock (_subsystemLock) + { + if (_subsystems.Any()) + { + subsystemIds = _subsystems + .Select(subsystem => new KeyValuePair(subsystem.Key, subsystem.Value.Name)); + } + + if (!subsystemIds.Any()) return; + } + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendLaunchSubsystemsRequest(subsystemIds), + launcherTask: _subsystemLauncher?.LaunchSubsystems(subsystemIds)); + + } + catch (Exception exception) + { + _logger.CannotSendLaunchRequestError(exception); + } + } + + public async Task LaunchSubsystemAfterTime(Guid subsystemId, int periodOfTime) + { + SubsystemInfo? subsystem; + + lock (_subsystemLock) + if(!_subsystems.TryGetValue(subsystemId, out subsystem)) return; + + if (subsystem == null) return; + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendLaunchSubsystemAfterTimeRequest(subsystemId, subsystem.Name, periodOfTime), + launcherTask: _subsystemLauncher?.LaunchSubsystemAfterTime(subsystemId, subsystem.Name, periodOfTime)); + } + + private Task SendRequest( + Task? communicatorTask, + Task? launcherTask) + { + if (_subsystemLauncherCommunicator == null && _subsystemLauncher == null) return Task.CompletedTask; + + return _subsystemLauncherCommunicator == null + ? launcherTask + : communicatorTask; + } + + public async Task LaunchSubsystemAutomatically(Guid subsystemId) + { + lock (_subsystemLock) + { + var succeed = _subsystems.TryGetValue(subsystemId, out var subsystem); + if (!succeed || subsystem == null) return; + subsystem.AutomatedStart = true; + } + + await LaunchSubsystem(subsystemId.ToString()); + } + + public async Task LaunchSubsystemsAutomatically() + { + var subsystemIds = new SynchronizedCollection(); + + lock (_subsystemLock) + { + if (_subsystems.Any()) + { + foreach (var subsystem in _subsystems) + { + if (subsystem.Value.AutomatedStart == true && subsystem.Value.State == SubsystemState.Stopped) + { + subsystemIds.Add(subsystem.Key.ToString()); + } + } + } + } + + await LaunchSubsystems(subsystemIds); + } + + public async Task LaunchSubsystems(IEnumerable subsystems) + { + try + { + var subsystemIds = new Dictionary(); + + if (subsystems == null || !subsystems.Any()) return; + + lock (_subsystemLock) + { + foreach (var id in subsystems) + { + var subsystemState = GetSubsystemState(id); + + if (subsystemState != SubsystemState.Stopped) continue; + + var guidId = Guid.Parse(id); + + if(!_subsystems.TryGetValue(guidId, out var subsystem)) continue; + + subsystemIds.Add(guidId, subsystem.Name); + } + } + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendLaunchSubsystemsRequest(subsystemIds), + launcherTask: _subsystemLauncher?.LaunchSubsystems(subsystemIds)); + } + catch (Exception exception) + { + _logger.CannotSendLaunchRequestError(exception); + } + } + + private KeyValuePair GetSubsystemIdAndName(string subsystemId) + { + SubsystemInfo? subsystem; + var guidId = Guid.Parse(subsystemId); + + lock (_subsystemLock) + { + if (!_subsystems.TryGetValue(guidId, out subsystem)) return default; + } + + return new(guidId, subsystem.Name); + } + + public async Task LaunchSubsystem(string subsystemId) + { + var subsystemState = GetSubsystemState(subsystemId); + + if (subsystemState != SubsystemState.Stopped) return; + + var subsystem = GetSubsystemIdAndName(subsystemId); + if(subsystem.Value == null) return; + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendLaunchSubsystemsRequest(new Dictionary { { subsystem.Key, subsystem.Value } }), + launcherTask: _subsystemLauncher?.LaunchSubsystem(subsystem.Key, subsystem.Value)); + } + + public async Task RestartSubsystems(IEnumerable subsystems) + { + if (subsystems == null || !subsystems.Any()) return; + + var subsystemIds = new Dictionary(); + foreach (var subsystemId in subsystems) + { + var subsystemState = GetSubsystemState(subsystemId); + + if (subsystemState != SubsystemState.Started && subsystemState != SubsystemState.Running) continue; + + var subsystem = GetSubsystemIdAndName(subsystemId); + + subsystemIds.TryAdd(subsystem.Key, subsystem.Value!); + } + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendRestartSubsystemsRequest( subsystemIds ), + launcherTask: _subsystemLauncher?.RestartSubsystems(subsystemIds)); + } + + public async Task RestartSubsystem(string subsystemId) + { + var subsystemState = GetSubsystemState(subsystemId); + + if (subsystemState != SubsystemState.Started && subsystemState != SubsystemState.Running) return; + + var subsystem = GetSubsystemIdAndName(subsystemId); + if (subsystem.Value == null) return; + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendRestartSubsystemsRequest(new Dictionary { { subsystem.Key, subsystem.Value } }), + launcherTask: _subsystemLauncher?.RestartSubsystem(subsystem.Key, subsystem.Value)); + } + + public async Task ShutdownAllRegisteredSubsystem() + { + try + { + var copySubsystems = Enumerable.Empty>(); + + lock (_subsystemLock) + { + copySubsystems = _subsystems + .Where(subsystem => subsystem.Value.State == SubsystemState.Started || subsystem.Value.State == SubsystemState.Running) + .Select(subsystem => new KeyValuePair(subsystem.Key, subsystem.Value.Name)); + } + + if (copySubsystems.Any()) + { + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendShutdownSubsystemsRequest(copySubsystems), + launcherTask: _subsystemLauncher?.ShutdownSubsystems(copySubsystems)); + } + } + catch (Exception exception) + { + _logger.CannotTerminateSubsystemError(exception); + } + } + + private IEnumerable> GetCopySubsystems() + { + var copySubsystems = Enumerable.Empty>(); + + lock (_subsystemLock) + { + copySubsystems = _subsystems.Select(subsystem => new KeyValuePair(subsystem.Key, subsystem.Value.Name)); + } + + return copySubsystems; + } + + public async Task ShutdownSubsystem(string subsystemId) + { + var subsystemState = GetSubsystemState(subsystemId); + + if (subsystemState != SubsystemState.Started && subsystemState != SubsystemState.Running) return; + + var subsystem = GetSubsystemIdAndName(subsystemId); + if (subsystem.Value == null) return; + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendShutdownSubsystemsRequest(new Dictionary() { { subsystem.Key, subsystem.Value } }), + launcherTask: _subsystemLauncher?.ShutdownSubsystem(subsystem.Key, subsystem.Value)); + } + + private string GetSubsystemState(string subsystemId) + { + var result = string.Empty; + + lock (_subsystemLock) + { + if (_subsystems.Any()) + result = _subsystems + .First(subsystem => subsystem.Key == Guid.Parse(subsystemId)) + .Value + .State; + } + + return result; + } + + public async Task ShutdownSubsystems(IEnumerable subsystems) + { + try + { + var copySubsystems = GetCopySubsystems(); + + var subsystemsToTerminate = new Dictionary(); + + foreach (var subsystemId in subsystems) + { + var subsystemKvp = copySubsystems + .First(sub => sub.Key == Guid.Parse(subsystemId)); + + if (!subsystemsToTerminate.TryAdd(subsystemKvp.Key, subsystemKvp.Value)) _logger.SubsystemTerminationAddWarning(subsystemKvp.Key.ToString(), subsystemKvp.Value); + } + + await SendRequest( + communicatorTask: _subsystemLauncherCommunicator?.SendShutdownSubsystemsRequest(copySubsystems), + launcherTask: _subsystemLauncher?.ShutdownSubsystems(copySubsystems)); + } + catch (Exception exception) + { + _logger.CannotTerminateSubsystemError(exception); + } + } + + public async Task ModifySubsystemState(Guid subsystemId, string state) + { + KeyValuePair subsystem; + + lock (_subsystemLock) + { + subsystem = _subsystems.FirstOrDefault(sub => sub.Key.Equals(subsystemId)); + + if (subsystem.Value == null || subsystem.Value.State == state) return; + + try + { + subsystem.Value.State = state; + } + catch (Exception exception) + { + _logger.ModifyingSubsystemsStateError(subsystemId, exception); + } + } + + await _handler.UpdateSubsystemInfo(subsystemId, subsystem.Value); + } + + public async Task AddSubsystems(IEnumerable> subsystems) + { + if (subsystems == null || !subsystems.Any()) return; + + UpdateOrAddElements(subsystems); + + foreach (var subsystem in subsystems) + { + if (subsystem.Value.AutomatedStart) await Task.Run(async () => await LaunchSubsystem(subsystem.Key.ToString())); + } + + await _handler.AddSubsystems(subsystems); + } + + public void AddSubsystem(Guid subsystemId, SubsystemInfo subsystem) + { + lock (_subsystemLock) + { + var succeed = _subsystems.TryAdd(subsystemId, subsystem); + if (!succeed) _logger.SubsystemAddError(subsystemId.ToString(), subsystem.Name); + } + } + + public async Task RemoveSubsystem(Guid subsystemId) + { + var subsystem = _subsystems.First(subsystem => subsystem.Key == subsystemId); + + if (subsystem.Key == default) return; + + if (subsystem.Value.State == SubsystemState.Started || subsystem.Value.State == SubsystemState.Running) + await ShutdownSubsystem(subsystemId.ToString()); + + lock (_subsystemLock) + { + var succeed = _subsystems.TryRemove(subsystemId, out _); + + if (!succeed) return; + + Task.Run(async () => await SendModifiedSubsystems()); + } + } + + private async Task SendModifiedSubsystems() + { + var subsystemsCopy = Enumerable.Empty>(); + lock (_subsystemLock) + { + subsystemsCopy = _subsystems.ToList(); + } + + await _handler.AddSubsystems(subsystemsCopy); + } + + private void UpdateOrAddElements(IEnumerable> subsystems) + { + lock (_subsystemLock) + { + foreach (var subsystem in subsystems) + { + _subsystems.AddOrUpdate(subsystem.Key, subsystem.Value, (key, value) => value = subsystem.Value); + } + } + } + + public IEnumerable> GetSubsystems() + { + lock (_subsystemLock) + return _subsystems; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Subsystems/SubsystemLauncher.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Subsystems/SubsystemLauncher.cs new file mode 100644 index 000000000..2861fad2c --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Core/Subsystems/SubsystemLauncher.cs @@ -0,0 +1,149 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.Concurrent; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using ProcessExplorer.Abstractions.Logging; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.DependencyInjection; + +namespace ProcessExplorer.Core.Subsystems; + +internal class SubsystemLauncher : ISubsystemLauncher +{ + private delegate Task RequestSubsystemAction(Guid subsystemId, string subsystemName); + private readonly ILogger _logger; + private Action? _launchRequest; + private Action? _stopRequest; + private Func? _createLaunchRequest; + private Func? _createStopRequest; + + public SubsystemLauncher( + ILogger? logger = null, + IOptions>? options = null) + { + _logger = logger ?? NullLogger.Instance; + _launchRequest = options?.Value.LaunchRequest; + _stopRequest= options?.Value.StopRequest; + _createLaunchRequest = options?.Value.CreateLaunchRequest; + _createStopRequest = options?.Value.CreateStopRequest; + } + + public void SetHandlers( + Action launchRequest, + Action stopRequest, + Func launchRequestCreator, + Func stopRequestCreator) + { + _launchRequest = launchRequest; + _stopRequest = stopRequest; + _createLaunchRequest = launchRequestCreator; + _createStopRequest = stopRequestCreator; + } + + public Task LaunchSubsystem(Guid subsystemId, string subsystemName) + { + try + { + if (_launchRequest == null || _createLaunchRequest == null) return Task.FromResult(SubsystemState.Stopped); + + _launchRequest.Invoke(_createLaunchRequest.Invoke(subsystemId, subsystemName)); + _logger.SubsystemStartedDebug(subsystemId.ToString()); + + return Task.FromResult(SubsystemState.Started); + } + catch (Exception exception) + { + _logger.SubsystemStartError(subsystemId.ToString(), exception); + } + + return Task.FromResult(SubsystemState.Stopped); + } + + public Task LaunchSubsystemAfterTime(Guid subsystemId, string subsystemName, int periodOfTime) + { + Thread.Sleep(periodOfTime); + return LaunchSubsystem(subsystemId, subsystemName); + } + + public Task>> LaunchSubsystems(IEnumerable> subsystems) + { + return HandleSubsystemAction(subsystems, LaunchSubsystem); + } + + public async Task RestartSubsystem(Guid subsystemId, string subsystemName) + { + var stopResult = await ShutdownSubsystem(subsystemId, subsystemName); + + if (stopResult == SubsystemState.Running + || stopResult == SubsystemState.Started) + { + _logger.SubsystemRestartError(subsystemId.ToString()); + return stopResult; + } + + var startedStateResult = await LaunchSubsystem(subsystemId, subsystemName); + if (startedStateResult == SubsystemState.Stopped) + { + _logger.SubsystemRestartError(subsystemId.ToString()); + } + + return startedStateResult; + } + + public Task>> RestartSubsystems(IEnumerable> subsystems) + { + return HandleSubsystemAction(subsystems, RestartSubsystem); + } + + public Task ShutdownSubsystem(Guid subsystemId, string subsystemName) + { + try + { + _logger.SubsystemStoppingDebug(subsystemId.ToString()); + + if (_stopRequest == null || _createStopRequest == null) return Task.FromResult(SubsystemState.Running); + + _stopRequest.Invoke(_createStopRequest.Invoke(subsystemId)); + + return Task.FromResult(SubsystemState.Stopped); + } + catch (Exception exception) + { + _logger.SubsystemStopError(subsystemId.ToString(), exception); + return Task.FromResult(SubsystemState.Running); + } + } + + public Task>> ShutdownSubsystems(IEnumerable> subsystems) + { + return HandleSubsystemAction(subsystems, ShutdownSubsystem); + } + + private async Task>> HandleSubsystemAction( + IEnumerable> subsystems, + RequestSubsystemAction action) + { + var result = new Dictionary(); + + foreach (var subsystem in subsystems) + { + var resultSubsystemState = await action(subsystem.Key, subsystem.Value); + + result.Add(subsystem.Key, resultSubsystemState); + } + + return result; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/DependencyInjection/ProcessExplorerBuilder.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/DependencyInjection/ProcessExplorerBuilder.cs new file mode 100644 index 000000000..a2fb42255 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/DependencyInjection/ProcessExplorerBuilder.cs @@ -0,0 +1,25 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.DependencyInjection; + +namespace ProcessExplorer.Server.DependencyInjection; + +public sealed class ProcessExplorerBuilder +{ + internal IServiceCollection ServiceCollection { get; } + + public ProcessExplorerBuilder(IServiceCollection serviceCollection) + { + this.ServiceCollection = serviceCollection; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/DependencyInjection/ServiceCollectionProcessExplorerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/DependencyInjection/ServiceCollectionProcessExplorerExtensions.cs new file mode 100644 index 000000000..18d14af9c --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/DependencyInjection/ServiceCollectionProcessExplorerExtensions.cs @@ -0,0 +1,37 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Core.DependencyInjection; +using ProcessExplorer.Server.Server.Infrastructure.Grpc; + +namespace ProcessExplorer.Server.DependencyInjection; + +public static class ServiceCollectionProcessExplorerExtensions +{ + public static IServiceCollection AddProcessExplorerWindowsServerWithGrpc( + this IServiceCollection serviceCollection, + Action builderAction) + { + serviceCollection.TryAddSingleton(); + serviceCollection.AddProcessMonitorWindows(); + serviceCollection.AddSubsystemController(); + serviceCollection.AddProcessExplorerAggregator(); + + var builder = new ProcessExplorerBuilder(serviceCollection); + builderAction(builder); + + return serviceCollection; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Logging/SourceGeneratedLoggerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Logging/SourceGeneratedLoggerExtensions.cs new file mode 100644 index 000000000..6d198076b --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Logging/SourceGeneratedLoggerExtensions.cs @@ -0,0 +1,112 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.Logging; + +namespace ProcessExplorer.Server.Logging; + +internal static partial class SourceGeneratedLoggerExtensions +{ + //Debugs + [LoggerMessage(Level = LogLevel.Debug, Message = "The Process Explorer list is initialized", SkipEnabledCheck = false)] + public static partial void ProcessListIsInitializedDebug(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Debug, Message = "The Process Explorer gRPC server has been started...", SkipEnabledCheck = false)] + public static partial void GrpcServerStartedDebug(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Debug, Message = "The Process Explorer gRPC server has been stopped...", SkipEnabledCheck = false)] + public static partial void GrpcServerStoppedDebug(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Debug, Message = "A gRPC client subscribed with id: {id}.", SkipEnabledCheck = false)] + public static partial void GrpcClientSubscribedDebug(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Debug, Message = "A gRPC client sent a message with topic: {topic}.", SkipEnabledCheck = false)] + public static partial void GrpcClientMessageReceivedDebug(this ILogger logger, string topic); + + //Errors + [LoggerMessage(Level = LogLevel.Error, Message = "Sending connection information to the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void AddConnectionsError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Adding UIHandler was unsuccessful. Id: `{id}`", SkipEnabledCheck = false)] + public static partial void UIHandlerConnectionAddingError(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Removing UIHandler was unsuccessful. Id: `{id}`", SkipEnabledCheck = false)] + public static partial void UIHandlerConnectionRemoveError(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Sending a process information to the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void AddProcessError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Sending process information to the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void AddProcessesError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Sending a runtime information to the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void AddRuntimeError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Sending a process information to the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void AddRuntimesError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Removing a process by id command on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void RemoveProcessByIdError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating a connection information on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateConnectionError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating a environment variables on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateEnvironmentVariablesError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating modules information on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateModulesError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating a process information on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateProcessError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating registrations information on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateRegistrationsError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Adding subsystems on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void AddSubsystemsError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating subsystem information on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateSubsystemError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Updating the status of the process: `{pid}` on the UI(s) was unsuccessful. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void UpdateProcessStatusError(this ILogger logger, int pid, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error occurred while subscribing as a gRPC client: {id}. Detailed axception: `{exception}`", SkipEnabledCheck = false)] + public static partial void GrpcSubscribeError(this ILogger logger, string id, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error occurred while starting a subsystem with id: {id}.", SkipEnabledCheck = false)] + public static partial void StartSubsystemError(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error occurred while restarting a subsystem with id: {id}.", SkipEnabledCheck = false)] + public static partial void RestartSubsystemError(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error occurred while termianting a subsystem with id: {id}.", SkipEnabledCheck = false)] + public static partial void ShutdownSubsystemError(this ILogger logger, string id); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while reading, deserializing gRPC message: {exception}...", SkipEnabledCheck = false)] + public static partial void GrpcMessageReadingError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while handling WebSocket message for subsystem handling: {exception}...", SkipEnabledCheck = false)] + public static partial void GrpcMessageHandlingError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while setting up process explorer server. Detailed exception: {exception}...", SkipEnabledCheck = false)] + public static partial void ProcessExplorerSetupError(this ILogger logger, Exception ex, Exception exception); + + [LoggerMessage(Level = LogLevel.Error, Message = "Error while setting up process explorer server-client subsription. Detailed exception: {exception}...", SkipEnabledCheck = false)] + public static partial void SubscriptionError(this ILogger logger, Exception ex, Exception exception); + + //Warnings + [LoggerMessage(Level = LogLevel.Warning, Message = "No timeout was declared while using CancellationToken for gRPC server...", SkipEnabledCheck = false)] + public static partial void GrpcCancellationTokenWarning(this ILogger logger); +} + diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/ProcessExplorer.Server.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/ProcessExplorer.Server.csproj new file mode 100644 index 000000000..145ead4db --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/ProcessExplorer.Server.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerBuilderExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerBuilderExtensions.cs new file mode 100644 index 000000000..10a8e6c15 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerBuilderExtensions.cs @@ -0,0 +1,37 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using ProcessExplorer.Server.DependencyInjection; +using ProcessExplorer.Server.Server.GrpcServer; + +namespace ProcessExplorer.Server.Server.Abstractions; + +public static class ProcessExplorerBuilderExtensions +{ + public static ProcessExplorerBuilder UseGrpc( + this ProcessExplorerBuilder builder, + Action? options = null) + { + if (options != null) builder.ServiceCollection.Configure(options); + + builder.ServiceCollection.AddGrpc(); + + builder.ServiceCollection.AddSingleton(); + builder.ServiceCollection.AddSingleton(provider => provider.GetRequiredService()); + builder.ServiceCollection.AddSingleton(provider => provider.GetRequiredService()); + + return builder; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerServer.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerServer.cs new file mode 100644 index 000000000..af846f2be --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerServer.cs @@ -0,0 +1,75 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Server.Logging; + +namespace ProcessExplorer.Server.Server.Abstractions; + +internal abstract class ProcessExplorerServer +{ + private readonly ILogger _logger; + public int Port { get; } + public string Host { get; } + + public ProcessExplorerServer( + int port, + string host, + ILogger? logger = null) + { + _logger = logger ?? NullLogger.Instance; + Host = host; + Port = port; + } + + public async void SetupProcessExplorer( + IOptions options, + IProcessInfoAggregator processInfoAggregator) + { + try + { + if (options.Value.Processes != null) + { + var processes = options.Value.Processes + .Select(process => process.ProcessInfo.ProcessId) + .ToArray(); + + if (processes != null) processInfoAggregator.InitProcesses(processes); + } + + if (options.Value.Modules != null) + { + var subsystems = new Dictionary(); + foreach (var module in options.Value.Modules) + { + subsystems.TryAdd(module.Key, SubsystemInfo.FromModule(module.Value)); + } + + await processInfoAggregator.SubsystemController.InitializeSubsystems(subsystems); + } + + if(options.Value.MainProcessId != null) + processInfoAggregator.MainProcessId = (int)options.Value.MainProcessId; + + if (options.Value.EnableProcessExplorer) + processInfoAggregator.EnableWatchingSavedProcesses(); + } + catch (Exception exception) + { + _logger.ProcessExplorerSetupError(exception, exception); + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/WebSocketService.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerServerOptions.cs similarity index 51% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/WebSocketService.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerServerOptions.cs index d01b486fd..ff66fbf49 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/WebSocketService.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Abstractions/ProcessExplorerServerOptions.cs @@ -10,21 +10,19 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace SuperRPC_POC; +using Microsoft.Extensions.Options; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Core.Processes; -public class WebSocketService -{ - public Task Start() - { - return Task.Run(() => CreateHostBuilder(Array.Empty()).Build().Run()); - } +namespace ProcessExplorer.Server.Server.Abstractions; - public IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(_ => new Startup()).UseUrls("http://localhost:5056"); - webBuilder.ConfigureLogging(logging => - logging.AddConsole()); - }); +public class ProcessExplorerServerOptions : IOptions +{ + public bool EnableProcessExplorer { get; set; } + public IEnumerable>? Modules { get; set; } + public IEnumerable? Processes { get; set; } + public int? MainProcessId { get; set; } + public int? Port { get; set; } + public string? Host { get; set; } + public ProcessExplorerServerOptions Value => this; } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/GrpcServer/GrpcListenerService.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/GrpcServer/GrpcListenerService.cs new file mode 100644 index 000000000..0414a76e2 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/GrpcServer/GrpcListenerService.cs @@ -0,0 +1,104 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Grpc.Core; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Infrastructure.Protos; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.Factories; +using ProcessExplorer.Server.Logging; +using ProcessExplorer.Server.Server.Abstractions; +using ProcessExplorer.Server.Server.Infrastructure.Grpc; +using GRPCServer = Grpc.Core.Server; + +namespace ProcessExplorer.Server.Server.GrpcServer; + +internal class GrpcListenerService : ProcessExplorerServer, IHostedService +{ + private readonly CancellationTokenSource _stopTokenSource = new(); + private readonly TaskCompletionSource _startTaskSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _stopTaskSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly IProcessInfoAggregator _processInfoAggregator; + private readonly ProcessExplorerServerOptions _options; + private readonly ILogger _logger; + private GRPCServer? _grpcServer; + + public GrpcListenerService( + IProcessInfoAggregator processInfoAggregator, + IOptions options, + ILogger? logger = null) + :base( + options.Value.Port ?? 5056, + options.Value.Host ?? "localhost", + logger) + { + _processInfoAggregator = processInfoAggregator; + _options = options.Value; + _logger = logger ?? NullLogger.Instance; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + if (cancellationToken == CancellationToken.None) _logger.GrpcCancellationTokenWarning(); + + Task.Run(() => StartAsyncCore(), _stopTokenSource.Token); + Task.Run(() => _processInfoAggregator.RunSubsystemStateQueue(_stopTokenSource.Token), _stopTokenSource.Token); + + return _startTaskSource.Task; + } + + private void StartAsyncCore() + { + _logger.GrpcServerStartedDebug(); + _startTaskSource.SetResult(); + + SetupGrpcServer(); + + if (_grpcServer == null) return; + + try + { + _grpcServer.Start(); + SetupProcessExplorer(_options, _processInfoAggregator); + } + catch (Exception) + { + _logger.GrpcServerStoppedDebug(); + } + } + + private void SetupGrpcServer() + { + _grpcServer = new GRPCServer + { + Services = { ProcessExplorerMessageHandler.BindService(new ProcessExplorerMessageHandlerService(_processInfoAggregator, _logger)) }, + Ports = { new ServerPort(Host, Port, ServerCredentials.Insecure) }, + }; + } + + public async Task StopAsync(CancellationToken cancellationToken) + { + _stopTaskSource.SetResult(); + _stopTokenSource.Cancel(); + + if (_grpcServer == null) return; + + var shutdown = _grpcServer.ShutdownAsync(); + _logger.GrpcServerStoppedDebug(); + + await Task.WhenAll(shutdown, _stopTaskSource.Task); + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Helper/ProtoConvertHelper.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Helper/ProtoConvertHelper.cs new file mode 100644 index 000000000..82dcaacff --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Helper/ProtoConvertHelper.cs @@ -0,0 +1,190 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Google.Protobuf; +using Google.Protobuf.Collections; +using Google.Protobuf.WellKnownTypes; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Extensions; +using ProcessExplorer.Abstractions.Infrastructure.Protos; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; +using Process = ProcessExplorer.Abstractions.Infrastructure.Protos.Process; + +namespace ProcessExplorer.Server.Server.Helper; + +internal static class ProtoConvertHelper +{ + //n Proto3, all fields are optional and have a default value. For example, a string field has a default value of empty string ("") and an int field has a default value of zero (0). + //If you want to create a proto message without a certain field, you have to set its value to the default value. + + public static Process DeriveProtoProcessType(this ProcessInfoData process) + { + List threads = new(); + + if (process.Threads != null && !process.Threads.Equals(default)) + foreach (var thread in process.Threads) + { + if (thread.Id == 0) continue; + if (thread.ThreadState == System.Diagnostics.ThreadState.Terminated) continue; + + GetStartTime(thread, out string startTime); + //we should add the try catch block because the thread might exit during the excution so the information won't be available + try + { + threads.Add(new ProcessThreadInfo() + { + Id = thread.Id, + StartTime = startTime, + PriorityLevel = thread.CurrentPriority, + Status = thread.ThreadState.ToStringCached() ?? string.Empty, + WaitReason = thread.ThreadState == System.Diagnostics.ThreadState.Wait ? thread.WaitReason.ToStringCached() : string.Empty, + ProcessorUsageTime = Duration.FromTimeSpan(thread.TotalProcessorTime) + }); + } + catch (Exception) + { + continue; + } + } + + return new() + { + StartTime = process.StartTime ?? string.Empty, + ProcessorUsageTime = process.ProcessorUsageTime != null ? + Duration.FromTimeSpan((TimeSpan)process.ProcessorUsageTime) + : Duration.FromTimeSpan(TimeSpan.Zero), + PhysicalMemoryUsageBit = process.PhysicalMemoryUsageBit ?? 0, + ProcessName = process.ProcessName ?? string.Empty, + ProcessId = process.ProcessId, + ProcessPriorityClass = process.ProcessPriorityClass ?? string.Empty, + Threads = { threads }, + VirtualMemorySize = process.VirtualMemorySize ?? 0, + ParentId = process.ParentId ?? 0, + PrivateMemoryUsage = process.PrivateMemoryUsage ?? 0, + ProcessStatus = process.ProcessStatus ?? string.Empty, + MemoryUsage = process.MemoryUsage ?? 0, + ProcessorUsage = process.ProcessorUsage ?? 0, + }; + } + + private static bool GetStartTime(System.Diagnostics.ProcessThread thread, out string startTime) + { + startTime = string.Empty; + + try + { + startTime = thread.StartTime.ToString(); + } + catch (Exception) { } + + return startTime == string.Empty; + } + + public static Connection DeriveProtoConnectionType(this ConnectionInfo connection) + { + return new() + { + Id = connection.Id.ToString(), + Name = connection.Name, + LocalEndpoint = connection.LocalEndpoint ?? string.Empty, + RemoteEndpoint = connection.RemoteEndpoint ?? string.Empty, + RemoteApplication = connection.RemoteApplication ?? string.Empty, + ConnectionInformation = { connection.ConnectionInformation?.DeriveProtoDictionaryType() ?? new MapField() }, + Status = connection.Status + }; + } + + public static ProcessInfoCollectorData DeriveProtoRuntimeInfoType(this ProcessExplorer.Abstractions.Entities.ProcessInfoCollectorData runtimeInfo) + { + return new() + { + Id = runtimeInfo.Id, + Registrations = { runtimeInfo.Registrations.Select(reg => reg.DeriveProtoRegistrationType()) }, + EnvironmentVariables = { runtimeInfo.EnvironmentVariables.DeriveProtoDictionaryType() }, + Connections = { runtimeInfo.Connections.Select(conn => conn.DeriveProtoConnectionType()) }, + Modules = { runtimeInfo.Modules.Select(mod => mod.DeriveProtoModuleType()) } + }; + } + + public static Registration DeriveProtoRegistrationType(this RegistrationInfo registration) + { + return new() + { + ServiceType = registration.ServiceType, + ImplementationType = registration.ImplementationType, + LifeTime = registration.LifeTime + }; + } + + public static Module DeriveProtoModuleType(this ModuleInfo module) + { + return new() + { + Name = module.Name, + Location = module.Location, + Version = module.Version.ToString(), + VersionRedirectedFrom = module.VersionRedirectedFrom, + PublicKeyToken = ByteString.CopyFrom(module.PublicKeyToken) + }; + } + + public static Subsystem DeriveProtoSubsystemType(this SubsystemInfo subsystem) + { + return new() + { + Name = subsystem.Name, + Path = subsystem.Path ?? string.Empty, + Port = subsystem.Port ?? 0, + UiType = subsystem.UIType ?? string.Empty, + Url = subsystem.Url ?? string.Empty, + StartupType = subsystem.StartupType ?? string.Empty, + State = subsystem.State ?? SubsystemState.Stopped, + AutomatedStart = subsystem.AutomatedStart, + Arguments = { subsystem.Arguments?.ToList() ?? new List() }, + Description = subsystem.Description ?? string.Empty, + }; + } + + public static MapField DeriveProtoDictionaryType( + this IEnumerable> dict) + { + var map = new MapField(); + + if (dict != null && dict.Any()) + foreach (var kvp in dict) + map.Add(kvp.Key, kvp.Value); + + return map; + } + + public static MapField DeriveProtoDictionaryType( + this IEnumerable> dict, + Func converter) + { + var map = new MapField(); + + if (dict != null && dict.Any()) + { + foreach (var kvp in dict) + { + var key = kvp.Key?.ToString(); + if (key == null || kvp.Value == null) continue; + map.Add(key, converter.Invoke(kvp.Value)); + } + } + + return map; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/GrpcClientConnection.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/GrpcClientConnection.cs new file mode 100644 index 000000000..cf8181282 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/GrpcClientConnection.cs @@ -0,0 +1,39 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Grpc.Core; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Infrastructure.Protos; + +namespace ProcessExplorer.Server.Server.Infrastructure.Grpc; + +internal class GrpcClientConnection : IClientConnection +{ + private readonly KeyValuePair> _stream; + private readonly object _streamLock = new(); + + public GrpcClientConnection( + IServerStreamWriter responseStream, + Guid id) + { + _stream = new(id, responseStream); + } + + public Task SendMessage(Message message) + { + lock (_streamLock) + { + return _stream.Value.WriteAsync(message); + } + } +} + diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/GrpcUIHandler.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/GrpcUIHandler.cs new file mode 100644 index 000000000..b105a6726 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/GrpcUIHandler.cs @@ -0,0 +1,522 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.Concurrent; +using Google.Protobuf.Collections; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Infrastructure.Protos; +using ProcessExplorer.Abstractions.Logging; +using ProcessExplorer.Server.Logging; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Server.Server.Helper; + +namespace ProcessExplorer.Server.Server.Infrastructure.Grpc; + +internal class GrpcUiHandler : IUiHandler +{ + private readonly object _uiHandlersLock = new(); + private readonly ILogger _logger; + private readonly ConcurrentDictionary> _uiHandlers; + + public GrpcUiHandler( + ILogger? logger = null) + { + _logger = logger ?? NullLogger.Instance; + _uiHandlers = new (); + } + + public Task AddConnections(string assemblyId, IEnumerable connections) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || connections == null || !connections.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.AddConnectionListAction, + AssemblyId = assemblyId, + Connections = { connections.Select(conn => conn.DeriveProtoConnectionType()) } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddConnectionsError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task AddProcess(ProcessInfoData process) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || process == null) return Task.CompletedTask; + } + + try + { + var list = new List + { + process.DeriveProtoProcessType() + }; + + var message = new Message() + { + Action = ActionType.AddProcessAction, + Processes = { list } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddProcessError(exception, exception); + } + + return Task.CompletedTask; + } + + public void AddClientConnection(Guid id, IClientConnection connection) + { + if (typeof(T) == typeof(Message)) + { + lock (_uiHandlersLock) + { + if (connection is not IClientConnection clientConnection) return; + if (!_uiHandlers.TryAdd(id, clientConnection)) _logger.UIHandlerConnectionAddingError(id.ToString()); + } + } + } + + public void RemoveClientConnection(Guid id) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.TryRemove(id, out _)) _logger.UIHandlerConnectionRemoveError(id.ToString()); + } + } + + public Task AddProcesses(IEnumerable processes) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || processes == null || !processes.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.AddProcessListAction, + Processes = { processes.Select(proc => proc.DeriveProtoProcessType()) } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddProcessesError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task AddRuntimeInfo(string assemblyId, ProcessExplorer.Abstractions.Entities.ProcessInfoCollectorData dataObject) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || dataObject == null) return Task.CompletedTask; + } + + try + { + var list = new List() + { + dataObject.DeriveProtoRuntimeInfoType() + }; + + var message = new Message() + { + Action = ActionType.AddRuntimeInfoAction, + AssemblyId = assemblyId, + RuntimeInfo = { list } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddRuntimeError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task AddRuntimeInfo(IEnumerable> runtimeInfo) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || !runtimeInfo.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.AddMultipleRuntimeInfoAction, + MultipleRuntimeInfo = { runtimeInfo.DeriveProtoDictionaryType(ProtoConvertHelper.DeriveProtoRuntimeInfoType) } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddRuntimesError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task TerminateProcess(int pid) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.RemoveProcessByIdAction, + ProcessId = pid + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.RemoveProcessByIdError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateConnection(string assemblyId, ConnectionInfo connection) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + try + { + var list = new List() + { + connection.DeriveProtoConnectionType() + }; + + var message = new Message() + { + Action = ActionType.UpdateConnectionAction, + Connections = { list } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateConnectionError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateEnvironmentVariables(string assemblyId, IEnumerable> environmentVariables) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || !environmentVariables.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.UpdateEnvironmentVariablesAction, + AssemblyId = assemblyId, + EnvironmentVariables = { environmentVariables.DeriveProtoDictionaryType() } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateEnvironmentVariablesError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateModules(string assemblyId, IEnumerable modules) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || !modules.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.UpdateModulesAction, + AssemblyId = assemblyId, + Modules = { modules.Select(module => module.DeriveProtoModuleType()) } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateModulesError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateProcess(ProcessInfoData process) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + try + { + var list = new List() + { + process.DeriveProtoProcessType() + }; + + var message = new Message() + { + Action = ActionType.UpdateProcessAction, + Processes = { list } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateProcessError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateRegistrations(string assemblyId, IEnumerable registrations) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || !registrations.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.UpdateRegistrationsAction, + AssemblyId = assemblyId, + Registrations = { registrations.Select(registration => registration.DeriveProtoRegistrationType()) } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateRegistrationsError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task AddSubsystem(Guid subsystemId, SubsystemInfo subsystem) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + try + { + var map = new MapField + { + { subsystemId.ToString(), subsystem.DeriveProtoSubsystemType() } + }; + + var message = new Message() + { + Action = ActionType.AddSubsystemAction, + Subsystems = { map } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddSubsystemsError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task AddSubsystems(IEnumerable> subsystems) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any() || !subsystems.Any()) return Task.CompletedTask; + } + + try + { + var message = new Message() + { + Action = ActionType.AddSubsystemsAction, + Subsystems = { subsystems.DeriveProtoDictionaryType(ProtoConvertHelper.DeriveProtoSubsystemType) } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.AddSubsystemsError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateSubsystemInfo(Guid subsystemId, SubsystemInfo subsystem) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + try + { + var map = new MapField() + { + { subsystemId.ToString(), subsystem.DeriveProtoSubsystemType() } + }; + + var message = new Message() + { + Action = ActionType.UpdateSubsystemAction, + Subsystems = { map } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateSubsystemError(exception, exception); + } + + return Task.CompletedTask; + } + + public Task UpdateProcessStatus(KeyValuePair process) + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + try + { + var map = new MapField + { + { process.Key, process.Value.ToString() } + }; + + var message = new Message() + { + Action = ActionType.UpdateProcessStatusAction, + ProcessStatusChanges = { map } + }; + + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch (Exception exception) + { + _logger.UpdateProcessStatusError(process.Key, exception, exception); + } + + return Task.CompletedTask; + } + + public Task SubscriptionIsAliveUpdate() + { + lock (_uiHandlersLock) + { + if (!_uiHandlers.Any()) return Task.CompletedTask; + } + + var message = new Message() + { + Action = ActionType.SubscriptionAliveAction + }; + + try + { + return UpdateInfoOnUI(handler => handler.SendMessage(message)); + } + catch(Exception exception) + { + _logger.SubscriptionError(exception, exception); + } + + return Task.CompletedTask; + } + + private IEnumerable> CreateCopyOfClients() + { + lock (_uiHandlersLock) + { + return _uiHandlers.Select(kvp => kvp.Value); + } + } + + private Task UpdateInfoOnUI(Func, Task> handlerAction) + { + try + { + return Task.WhenAll(CreateCopyOfClients().Select(handlerAction)); + } + catch (Exception exception) + { + _logger.UiInformationCannotBeUpdatedError(exception); + return Task.CompletedTask; + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/ProcessExplorerMessageHandlerService.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/ProcessExplorerMessageHandlerService.cs new file mode 100644 index 000000000..aaa91e164 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/Infrastructure/Grpc/ProcessExplorerMessageHandlerService.cs @@ -0,0 +1,82 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Google.Protobuf.WellKnownTypes; +using Grpc.Core; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Infrastructure.Protos; +using ProcessExplorer.Server.Logging; + +namespace ProcessExplorer.Server.Server.Infrastructure.Grpc; + +internal class ProcessExplorerMessageHandlerService : ProcessExplorerMessageHandler.ProcessExplorerMessageHandlerBase +{ + private readonly IProcessInfoAggregator _processInfoAggregator; + private readonly ILogger _logger; + + public ProcessExplorerMessageHandlerService( + IProcessInfoAggregator processInfoAggregator, + ILogger? logger = null) + { + _processInfoAggregator = processInfoAggregator; + _logger = logger ?? NullLogger.Instance; + } + + public override async Task Subscribe(Empty request, IServerStreamWriter responseStream, ServerCallContext context) + { + var id = Guid.NewGuid(); + _logger.GrpcClientSubscribedDebug(id.ToString()); + + //we will pass the IStreamWriter, which is the stream we can respond to per client + var connection = new GrpcClientConnection(responseStream, id); + + try + { + _processInfoAggregator.UiHandler.AddClientConnection(id, connection); + await _processInfoAggregator.UiHandler.SubscriptionIsAliveUpdate(); + await _processInfoAggregator.UiHandler.AddProcesses(_processInfoAggregator.GetProcesses()); + await _processInfoAggregator.UiHandler.AddRuntimeInfo(_processInfoAggregator.GetRuntimeInformation()); + await _processInfoAggregator.UiHandler.AddSubsystems( + _processInfoAggregator.SubsystemController.GetSubsystems()); + + //wait here until the user is connected to the service + while (!context.CancellationToken.IsCancellationRequested) + continue; + } + catch (Exception exception) + { + _logger.GrpcSubscribeError(id.ToString(), exception, exception); + } + finally + { + _processInfoAggregator.UiHandler.RemoveClientConnection(id); + } + } + + public override Task Send(Message request, ServerCallContext context) + { + //handle here the incoming messages from the clients. + _logger.GrpcClientMessageReceivedDebug(request.Action.ToString()); + + Task.Run(() => + { + MessageHandler.HandleIncomingGrpcMessages( + request, + _processInfoAggregator, + context.CancellationToken); + }, context.CancellationToken); + + return Task.FromResult(new Empty()); + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/MessageHandler.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/MessageHandler.cs new file mode 100644 index 000000000..4b6efb5d5 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/src/ProcessExplorer.Server/Server/MessageHandler.cs @@ -0,0 +1,76 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Microsoft.Extensions.Logging; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Infrastructure.Protos; +using ProcessExplorer.Server.Logging; + +namespace ProcessExplorer.Server.Server; + +internal static class MessageHandler +{ + public static async void HandleIncomingGrpcMessages( + Message message, + IProcessInfoAggregator processInfoAggregator, + CancellationToken cancellationToken, + ILogger? logger = null) + { + try + { + while (!cancellationToken.IsCancellationRequested) + { + var ids = message.Subsystems.Select(subsystem => subsystem.Key); + + switch (message.Action) + { + case ActionType.TerminateSubsystemsAction: + await processInfoAggregator.SubsystemController.ShutdownSubsystems(ids); + + break; + + case ActionType.RestartSubsystemsAction: + await processInfoAggregator.SubsystemController.RestartSubsystems(ids); + + break; + + case ActionType.LaunchSubsystemsAction: + await processInfoAggregator.SubsystemController.LaunchSubsystems(ids); + + break; + + case ActionType.LaunchSubsystemsWithDelayAction: + try + { + if (ids.ElementAt(0) == null) continue; + + var id = Guid.Parse(ids.ElementAt(0)); + await processInfoAggregator.SubsystemController.LaunchSubsystemAfterTime(id, message.PeriodOfDelay); + } + catch(Exception exception) + { + logger?.GrpcMessageReadingError(exception, exception); + } + + break; + } + + if (cancellationToken.IsCancellationRequested) + break; + } + } + catch(Exception exception) + { + logger?.GrpcMessageHandlingError(exception, exception); + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/ProcessExplorer.Core.Tests.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/ProcessExplorer.Core.Tests.csproj new file mode 100644 index 000000000..3ffbc0004 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/ProcessExplorer.Core.Tests.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + enable + false + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/ProcessInfoAggregator.Tests.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/ProcessInfoAggregator.Tests.cs new file mode 100644 index 000000000..95cfe6e71 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/ProcessInfoAggregator.Tests.cs @@ -0,0 +1,499 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Entities; +using ProcessExplorer.Abstractions.Entities.Connections; +using ProcessExplorer.Abstractions.Entities.Modules; +using ProcessExplorer.Abstractions.Entities.Registrations; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.Processes; +using ProcessExplorer.Core.Tests.Subsystems; +using Xunit; + +namespace ProcessExplorer.Core.Tests; + +public class ProcessInfoAggregatorTests +{ + [Fact] + public async Task RunSubsystemQueue_will_cancel_after_timeout() + { + //Creating a token to cancel after 3 seconds + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(3)); + + //Creating mocks to handle method + var mockUiHandler = new Mock(); + var mockSubsystemController = new Mock(); + var mockProcessInfoMonitor = new Mock(NullLogger.Instance); + var clientMock = new Mock>(); + var processInfoAggregator = new ProcessInfoAggregator( + mockProcessInfoMonitor.Object, + mockUiHandler.Object, + mockSubsystemController.Object, + NullLogger.Instance); + + //Run in the background + var task = Task.Run(() => processInfoAggregator.RunSubsystemStateQueue(cancellationTokenSource.Token)); + + //Schedule a modification + var id = Guid.NewGuid(); + processInfoAggregator.ScheduleSubsystemStateChanged(id, SubsystemState.Started); + + //Add a mock ui connection to send to. + processInfoAggregator.UiHandler.AddClientConnection(id, clientMock.Object); + + //Wait for the task to finish + await task; + + Assert.True(cancellationTokenSource.IsCancellationRequested); + } + + [Fact] + public void SetDeadProcessRemovalDelay_will_set_the_delay_of_process_deleting_from_the_collection() + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var dummyDelay = 0; + processInfoAggregator.SetDeadProcessRemovalDelay(dummyDelay); + + var result = processInfoAggregator.TerminatingProcessDelay; + + Assert.Equal(dummyDelay, result); + } + + [Fact] + public async Task RemoveRuntimeInformation_will_remove_item_from_collection() + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var dummyRuntimeInfo = new ProcessInfoCollectorData() + { + Id = 2, + Connections = new() + { + new() { Id = Guid.NewGuid(), Name = "dummy" }, new() { Id = Guid.NewGuid(), Name = "dummy2" }, + new() { Id = Guid.NewGuid(), Name = "dummy3" } + }, + Registrations = new() + { + new() { ImplementationType = "dummyImpl", LifeTime = "dummyLT", ServiceType = "dummyST" }, + new() { ImplementationType = "dummyImpl", LifeTime = "dummyLT", ServiceType = "dummyST" }, + new() { ImplementationType = "dummyImpl", LifeTime = "dummyLT", ServiceType = "dummyST" } + } + }; + + var id = "dummyId"; + var id2 = "dummyId2"; + + await processInfoAggregator.AddRuntimeInformation(id, dummyRuntimeInfo); + await processInfoAggregator.AddRuntimeInformation(id2, dummyRuntimeInfo); + + var collection = processInfoAggregator.GetRuntimeInformation(); + + Assert.NotNull(collection); + Assert.Equal(2, collection.Count()); + Assert.Contains(new KeyValuePair(id, dummyRuntimeInfo), collection); + Assert.Contains(new KeyValuePair(id2, dummyRuntimeInfo), collection); + + processInfoAggregator.RemoveRuntimeInformation(id); + Assert.NotNull(collection); + Assert.Single(collection); + Assert.DoesNotContain(new KeyValuePair(id, dummyRuntimeInfo), collection); + Assert.Contains(new KeyValuePair(id2, dummyRuntimeInfo), collection); + } + + [Theory] + [ClassData(typeof(ConnectionTheoryData))] + public async Task AddConnectionCollection_will_add_a_new_connection_collection_information(string id, IEnumerable connections) + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + //Add dummy data + await processInfoAggregator.AddRuntimeInformation(id, new ProcessInfoCollectorData()); + await processInfoAggregator.AddConnectionCollection(id, connections); + + var collection = processInfoAggregator.GetRuntimeInformation(); + + Assert.NotNull(collection); + Assert.Single(collection); + + var result = collection.First(); + + Assert.Equal(id, result.Key); + Assert.Equal(connections, result.Value.Connections); + } + + [Fact] + public async Task UpdateConnectionInfo_will_update_a_connection_information() + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var connectionId = Guid.NewGuid(); + var wrongConnectionInfo = new ConnectionInfo { Id = connectionId, Name = "dummyName", LocalEndpoint = "http://dummyLocalEndpontWrong.com" }; + var id = "dummyId"; + + await processInfoAggregator.AddRuntimeInformation(id, new ProcessInfoCollectorData() + { + Connections = new() { wrongConnectionInfo } + }); + + var collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + + var result = collection.First().Value; + Assert.Single(result.Connections); + Assert.Contains(wrongConnectionInfo, result.Connections); + + //updating + var dummyConnectionInfo = new ConnectionInfo { Id = connectionId, Name = "dummyName", LocalEndpoint = "https://dummyLocalEndpoint.com" }; + await processInfoAggregator.UpdateOrAddConnectionInfo(id, dummyConnectionInfo); + + collection = processInfoAggregator.GetRuntimeInformation(); + result = collection.First().Value; + + Assert.Single(collection); + Assert.Single(result.Connections); + Assert.DoesNotContain(wrongConnectionInfo, result.Connections); + Assert.Contains(dummyConnectionInfo, result.Connections); + } + + [Fact] + public async Task UpdateEnvironmentVariablesInfo_will_update_environment_variables() + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var id = "dummyId"; + var envs = new ConcurrentDictionary(); + + envs.TryAdd("dummyKey", "dummyValue"); + envs.TryAdd("wrongEnv", "wrongValue"); + + await processInfoAggregator.AddRuntimeInformation(id, new() + { + EnvironmentVariables = envs, + }); + + var collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + Assert.Contains(id, collection.Select(x => x.Key)); + + var result = collection.First().Value; + Assert.NotNull(result); + Assert.Equal(2, result.EnvironmentVariables.Count); + Assert.Equal(envs, result.EnvironmentVariables); + + var updatedEnvs = new Dictionary() + { + { "wrongEnv", "newValue" }, + { "newKey", "value" } + }; + + var expectedResult = new Dictionary() + { + { "dummyKey", "dummyValue" }, + { "wrongEnv", "newValue" }, + { "newKey", "value" } + }; + + await processInfoAggregator.UpdateOrAddEnvironmentVariablesInfo(id, updatedEnvs); + collection = processInfoAggregator.GetRuntimeInformation(); + + Assert.Single(collection); + Assert.Contains(id, collection.Select(x => x.Key)); + + result = collection.First().Value; + Assert.Equal(3, result.EnvironmentVariables.Count); + Assert.Equal(expectedResult, result.EnvironmentVariables); + } + + [Fact] + public async Task UpdateRegistrationInfo_will_update_registrations() + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var id = "dummyId"; + var registrations = new SynchronizedCollection() + { + new RegistrationInfo() + { + ImplementationType = "dummyImplementation", + LifeTime = "dummyLifetime", + ServiceType = "dummyServiceType" + } + }; + + await processInfoAggregator.AddRuntimeInformation(id, new() + { + Registrations = registrations + }); + + var collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + Assert.Equal(id, collection.First().Key); + + var result = collection.First().Value; + Assert.Single(collection); + Assert.Equal(registrations, result.Registrations); + + var update = new SynchronizedCollection() + { + new() { ServiceType = "dummyImplementation", ImplementationType = "dummyNewImplementationType", LifeTime = "dummyLifeTime" }, + new() { ServiceType = "dummyImplementation2", ImplementationType = "dummyImplementationType2", LifeTime = "dummyLifeTime2" } + }; + + await processInfoAggregator.UpdateRegistrations(id, update); + + collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + + result = collection.First().Value; + Assert.Equal(3, result.Registrations.Count); + + var expected = new SynchronizedCollection() + { + new() { ImplementationType = "dummyImplementation", LifeTime = "dummyLifetime", ServiceType = "dummyServiceType" }, + new() { ServiceType = "dummyImplementation", ImplementationType = "dummyNewImplementationType", LifeTime = "dummyLifeTime" }, + new() { ServiceType = "dummyImplementation2", ImplementationType = "dummyImplementationType2", LifeTime = "dummyLifeTime2" } + }; + + Assert.Equal(expected.Count, result.Registrations.Count); + Assert.NotStrictEqual(expected, result.Registrations); + } + + [Fact] + public async Task UpdateModuleInfo_will_update_modules() + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var id = "dummyId"; + + var modules = new SynchronizedCollection() + { + new() { Name = "dummyModule", Location = "dummyLocation" } + }; + + await processInfoAggregator.AddRuntimeInformation(id, new() + { + Modules = modules + }); + + var update = new List() { new() { Name = "dummyModule", Location = "newDummyLocation" } }; + + await processInfoAggregator.UpdateOrAddModuleInfo(id, update); + + var collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + Assert.Contains(id, collection.Select(x => x.Key)); + + var result = collection.First().Value; + Assert.Single(result.Modules); + Assert.Equal(update, result.Modules); + } + + + [Fact] + public void EnableWatchingSavedProcesses_will_begin_to_watch_processes() + { + var mockSubsystemController = new Mock(); + var loggerMock = CreateProcessMonitorLoggerMock(); + +#pragma warning disable CA1416 // Validate platform compatibility + var processInfoMonitor = new WindowsProcessInfoMonitor(loggerMock.Object); +#pragma warning restore CA1416 // Validate platform compatibility + var mockUiHandler = new Mock(); + var processInfoAggregator = new ProcessInfoAggregator( + processInfoMonitor, + mockUiHandler.Object, + mockSubsystemController.Object, + NullLogger.Instance); + + processInfoAggregator.EnableWatchingSavedProcesses(); + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Starting to watch processes, due it is enabled by the user.")), + It.IsAny(), + It.IsAny>()), + Times.Once); + } + + [Fact] + public void ScheduleSubsystemStateChanged_will_put_items_to_the_queue() + { + var id = Guid.NewGuid(); + var state = SubsystemState.Running; + + var processInfoAggregator = CreateProcessInfoAggregator(); + processInfoAggregator.ScheduleSubsystemStateChanged(id, state); + + var field = typeof(ProcessInfoAggregator).GetField("_subsystemStateChanges", BindingFlags.NonPublic | BindingFlags.Instance); + if (field == null) throw new ArgumentNullException(nameof(field)); + + var queue = (ConcurrentQueue>)field.GetValue(processInfoAggregator); + if (queue == null) throw new ArgumentNullException(nameof(queue)); + + var succeed = queue.TryDequeue(out var result); + Assert.True(succeed); + + Assert.Equal(id, result.Key); + Assert.Equal(state, result.Value); + } + + [Theory] + [ClassData(typeof(RuntimeInfoTheoryData))] + public async Task AddRuntimeInformation_will_add_a_new_info(string id, ProcessInfoCollectorData data) + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + await processInfoAggregator.AddRuntimeInformation(id, data); + + var collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + Assert.Contains(new KeyValuePair(id, data), collection); + + var result = collection.First().Value; + + Assert.NotNull(result); + Assert.Equal(data.Connections.Count, result.Connections.Count); + Assert.Equal(data.EnvironmentVariables.Count, result.EnvironmentVariables.Count); + Assert.Equal(data.Modules.Count, result.Modules.Count); + Assert.Equal(data.Registrations.Count, result.Registrations.Count); + Assert.Equal(data.Connections, result.Connections); + Assert.Equal(data.EnvironmentVariables, result.EnvironmentVariables); + Assert.Equal(data.Modules, result.Modules); + Assert.Equal(data.Registrations, result.Registrations); + } + + + [Theory] + [ClassData(typeof(RuntimeInfoTheoryData))] + public async Task AddRuntimeInformation_will_update_an_info(string id, ProcessInfoCollectorData data) + { + var processInfoAggregator = CreateProcessInfoAggregator(); + + var dummyRuntimeInfo = new ProcessInfoCollectorData() + { + Id = 2, + Connections = new() + { + new() { Id = Guid.NewGuid(), Name = "dummy" }, + new() { Id = Guid.NewGuid(), Name = "dummy2" }, + new() { Id = Guid.NewGuid(), Name = "dummy3" } + }, + Registrations = new() + { + new() { ImplementationType = "dummyImpl", LifeTime = "dummyLT", ServiceType = "dummyST" }, + new() { ImplementationType = "dummyImpl", LifeTime = "dummyLT", ServiceType = "dummyST" }, + new() { ImplementationType = "dummyImpl", LifeTime = "dummyLT", ServiceType = "dummyST" } + } + }; + + await processInfoAggregator.AddRuntimeInformation(id, dummyRuntimeInfo); + + //modifying the existing one + await processInfoAggregator.AddRuntimeInformation(id, data); + + var collection = processInfoAggregator.GetRuntimeInformation(); + Assert.Single(collection); + Assert.Contains(new KeyValuePair(id, data), collection); + + var result = collection.First().Value; + + Assert.NotNull(result); + Assert.Equal(data.Connections.Count, result.Connections.Count); + Assert.Equal(data.EnvironmentVariables.Count, result.EnvironmentVariables.Count); + Assert.Equal(data.Modules.Count, result.Modules.Count); + Assert.Equal(data.Registrations.Count, result.Registrations.Count); + Assert.Equal(data.Connections, result.Connections); + Assert.Equal(data.EnvironmentVariables, result.EnvironmentVariables); + Assert.Equal(data.Modules, result.Modules); + Assert.Equal(data.Registrations, result.Registrations); + } + + private static Mock> CreateProcessMonitorLoggerMock() + { + var loggerMock = new Mock>(); + + var loggerFilterOptions = new LoggerFilterOptions(); + + loggerFilterOptions.AddFilter("", LogLevel.Debug); + + loggerMock + .Setup(x => x.IsEnabled(It.IsAny())) + .Returns(level => loggerFilterOptions.MinLevel <= level); + + return loggerMock; + } + + private static IProcessInfoAggregator CreateProcessInfoAggregator() + { + var mockSubsystemController = new Mock(); + var mockLogger = CreateProcessMonitorLoggerMock(); + + //TODO(later): should create an if statement regarding to the OS +#pragma warning disable CA1416 // Validate platform compatibility + var processMonitor = new WindowsProcessInfoMonitor(mockLogger.Object); +#pragma warning restore CA1416 // Validate platform compatibility + + var mockUiHandler = new Mock(); + var processInfoAggregator = new ProcessInfoAggregator( + processMonitor, + mockUiHandler.Object, + mockSubsystemController.Object, + NullLogger.Instance); + + return processInfoAggregator; + } + + private class RuntimeInfoTheoryData : TheoryData + { + public RuntimeInfoTheoryData() + { + AddRow("dummyId", new ProcessInfoCollectorData() + { + Id = 1, + Connections = new() { new() { Id = Guid.NewGuid(), Name = "dummyConnection" } }, + Registrations = new() { new() { ImplementationType = "dummyImplementation", LifeTime = "dummyLifeTime", ServiceType = "dummyServiceType" } } + }); + AddRow("dummyId2", new ProcessInfoCollectorData() + { + Id = 1, + Connections = new() { new() { Id = Guid.NewGuid(), Name = "dummyConnection2" } }, + Registrations = new() { new() { ImplementationType = "dummyImplementation2", LifeTime = "dummyLifeTime2", ServiceType = "dummyServiceType2" }, new() { ImplementationType = "dummyImplementation1", LifeTime = "dummyLifeTime1", ServiceType = "dummyServiceType1" } } + }); + } + } + + private class ConnectionTheoryData : TheoryData + { + public ConnectionTheoryData() + { + AddRow("dummyId", new List() + { + new() { Id = Guid.NewGuid(), Name = "dummyConnection", LocalEndpoint = "dummyEndpoint" } + }); + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Processes/WindowsProcessInfoManager.Tests.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Processes/WindowsProcessInfoManager.Tests.cs new file mode 100644 index 000000000..3035f042e --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Processes/WindowsProcessInfoManager.Tests.cs @@ -0,0 +1,278 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Diagnostics; +using System.Threading; +using Microsoft.Extensions.Logging; +using Moq; +using ProcessExplorer.Abstractions.Processes; +using ProcessExplorer.Core.Processes; +using Xunit; + +namespace ProcessExplorer.Core.Tests.Processes; + +public class WindowsProcessInfoManagerTests +{ + [Fact] + public void AddChildProcesses_will_add_child_processes_to_the_list() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + + var testApplication = Process.Start(GetTestApplicationPath()); //It will start an another child process + + // Waiting for the child process to start + Thread.Sleep(100); + + processMonitor.AddChildProcesses(testApplication.Id, testApplication.ProcessName); + + var result = processMonitor.GetProcessIds().ToArray(); + + Assert.NotEmpty(result); + Assert.Equal(2, result.Length); + Assert.Contains(testApplication.Id, result); + + processMonitor.Dispose(); + } + + [Fact] + public void AddProcess_will_add_process_to_the_watchable_list() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + + var process = Process.Start(GetSimpleTestApplicationPath()); + + processMonitor.AddProcess(process.Id); + var result = processMonitor.GetProcessIds().ToArray(); + + Assert.NotEmpty(result); + Assert.Single(result); + Assert.Contains(process.Id, result); + + process.Kill(); + processMonitor.Dispose(); + } + + [Fact] + public void CheckIfIsComposeProcess_will_check_if_it_is_contained_by_the_list_and_return_true() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + var process = Process.Start(GetSimpleTestApplicationPath()); + processMonitor.AddProcess(process.Id); + + var result = processMonitor.CheckIfIsComposeProcess(process.Id); + + Assert.True(result); + + process.Kill(); + processMonitor.Dispose(); + } + + [Fact] + public void CheckIfIsComposeProcess_will_check_if_it_is_contained_by_the_list_and_return_false() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + var process = Process.Start(GetSimpleTestApplicationPath()); + + var result = processMonitor.CheckIfIsComposeProcess(process.Id); + + Assert.False(result); + + process.Kill(); + processMonitor.Dispose(); + } + + [Fact] + public void ClearProcessIds_will_remove_all_the_elements() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + var process = Process.Start(GetSimpleTestApplicationPath()); + processMonitor.AddProcess(process.Id); + + processMonitor.ClearProcessIds(); + var result = processMonitor.GetProcessIds().ToArray(); + + Assert.Empty(result); + + process.Kill(); + processMonitor.Dispose(); + } + + [Fact] //It is hard to reproduce a process which ses cpu in a time that is being measured in percentage + public void GetCpuUsage_will_return_with_some_value() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + var process = Process.Start(GetSimpleTestApplicationPath()); + + var cpuUsageResult = processMonitor.GetCpuUsage( + process.Id, + process.ProcessName); + + Assert.True(cpuUsageResult >= 0); + + process.Kill(); + processMonitor.Dispose(); + } + + [Fact] + public void GetMemoryUsage_will_return_with_some_value() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + + var memoryUsageResult = processMonitor.GetMemoryUsage( + Environment.ProcessId, + Process.GetProcessById(Environment.ProcessId).ProcessName); + + Assert.True(memoryUsageResult > 0); + + processMonitor.Dispose(); + } + + [Fact] + public void GetParentId_will_return_the_parent_id_of_the_process() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + + var process = Process.Start(GetSimpleTestApplicationPath()); + + //Expected parentid should be the current process id, as we are starting this process from the code. + var parentId = processMonitor.GetParentId(process.Id, process.ProcessName); + + Assert.NotNull(parentId); + Assert.Equal(Environment.ProcessId, parentId); + + process.Kill(); + processMonitor.Dispose(); + } + + [Fact] + public void GetParentId_will_return_null() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + + var parentId = processMonitor.GetParentId(666666, string.Empty); + + Assert.Null(parentId); + + processMonitor.Dispose(); + } + + [Fact] + public void SetProcessIds_will_set_the_ids_and_its_child_process_ids() + { + var loggerMock = CreateLoggerMock(); + var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + + var testApplication = Process.Start(GetTestApplicationPath()); //It will start a process + + var processes = new[] { testApplication.Id }; + + // Waiting for the test process to start + Thread.Sleep(1000); + processMonitor.SetProcessIds(Environment.ProcessId, processes); + + var result = processMonitor.GetProcessIds().ToArray(); + + Assert.NotStrictEqual(processes, result); + Assert.Equal(3, result.Length); + + processMonitor.Dispose(); + } + + //[Fact] + //public void WatchProcesses_will_begin_to_watch_all_the_processes_in_windows() + //{ + // var loggerMock = CreateLoggerMock(); + // var processMonitor = CreateWindowsProcessMonitor(loggerMock.Object); + // var modifiedProcessActionMock = new Mock(); + // var terminatedProcessActionMock = new Mock(); + // var createdProcessActionMock = new Mock(); + // var modifiedProcessesActionMock = new Mock(); + // var statusModifiedProcessActionMock = new Mock(); + + // var testApplication = Process.Start(GetTestApplicationPath()); //It will start a child process + + // processMonitor.SetHandlers( + // modifiedProcessActionMock.Object, + // terminatedProcessActionMock.Object, + // createdProcessActionMock.Object, + // modifiedProcessesActionMock.Object, + // statusModifiedProcessActionMock.Object); + + // processMonitor.WatchProcesses(Environment.ProcessId); + + // var result = processMonitor.GetProcessIds().ToArray(); + + // Assert.True(result.Length >= 3); + + // createdProcessActionMock.Verify(x => x.Invoke(It.IsAny()), Times.AtLeast(3)); + + // processMonitor.Dispose(); + //} + + [Conditional("DEBUG")] + private static void IsDebug(ref bool isDebug) => isDebug = true; + + private static Mock> CreateLoggerMock() + { + var loggerMock = new Mock>(); + + var loggerFilterOptions = new LoggerFilterOptions(); + + loggerFilterOptions.AddFilter("", LogLevel.Debug); + + loggerMock + .Setup(x => x.IsEnabled(It.IsAny())) + .Returns(level => loggerFilterOptions.MinLevel <= level); + + return loggerMock; + } + + private static ProcessInfoMonitor CreateWindowsProcessMonitor(ILogger logger) + { + var processMonitor = new WindowsProcessInfoMonitor(logger); + return processMonitor; + } + + private static string GetTestApplicationPath() + { + var folder = GetEnvironmentFolder(); + + return $"../../../../TestConsoleApp/bin/{folder}/net6.0/TestConsoleApp.exe"; + } + + private static string GetSimpleTestApplicationPath() + { + var folder = GetEnvironmentFolder(); + + return $"../../../../TestConsoleApp2/bin/{folder}/net6.0/TestConsoleApp2.exe"; + } + + private static string GetEnvironmentFolder() + { + var isDebug = false; + IsDebug(ref isDebug); + + var folder = isDebug ? "Debug" : "Release"; + + return folder; + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Subsystems/SubsystemController.Tests.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Subsystems/SubsystemController.Tests.cs new file mode 100644 index 000000000..c9ab0519d --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Subsystems/SubsystemController.Tests.cs @@ -0,0 +1,809 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Moq; +using ProcessExplorer.Abstractions.Infrastructure; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.Subsystems; +using Xunit; + +namespace ProcessExplorer.Core.Tests.Subsystems; + +public class SubsystemControllerTests +{ + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task InitializeSubsystems_will_add_elements_trigger_automated_start_and_update_to_the_ui(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystems(It.IsAny>()), Times.Once); + + uiDelegateMock.Verify(x => x.AddSubsystems(It.IsAny>>())); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchAllRegisteredSubsystem_will_use_subsystemLauncher_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + await subsystemController.LaunchAllRegisteredSubsystem(); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystems(It.IsAny>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchAllRegisteredSubsystem_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + await subsystemController.LaunchAllRegisteredSubsystem(); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystems(It.IsAny>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystemAfterTime_will_use_subsystemLauncher_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppedSubsystems = subsystems.Where(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + var random = new Random().Next(0, stoppedSubsystems.Count()); + + var subsystem = stoppedSubsystems.ElementAt(random); + var time = 100; + + await subsystemController.LaunchSubsystemAfterTime(subsystem.Key, time); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystemAfterTime(It.IsAny(), It.IsAny(), time), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystemAfterTime_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppedSubsystems = subsystems.Where(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + var random = new Random().Next(0, stoppedSubsystems.Count()); + + var subsystem = stoppedSubsystems.ElementAt(random); + var time = 100; + + await subsystemController.LaunchSubsystemAfterTime(subsystem.Key, time); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemAfterTimeRequest(It.IsAny(), It.IsAny(), time), Times.Once); + } + + [Fact] + public async Task LaunchSubsystemAfterTime_will_return_without_triggering_anything() + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + var subsystems = new Dictionary(); + await subsystemController.InitializeSubsystems(subsystems); + + var time = 100; + + await subsystemController.LaunchSubsystemAfterTime(Guid.NewGuid(), time); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemAfterTimeRequest(It.IsAny(), It.IsAny(), time), Times.Never); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystemAutomatically_will_use_subsystemLauncher_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsystem = subsystems.First(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + + await subsystemController.LaunchSubsystemAutomatically(subsystem.Key); + + Assert.True(subsystem.Value.AutomatedStart); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystem(It.IsAny(), It.IsAny())); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystemAutomatically_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsystem = subsystems.First(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + + await subsystemController.LaunchSubsystemAutomatically(subsystem.Key); + + Assert.True(subsystem.Value.AutomatedStart); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemsRequest(It.IsAny>()), Times.Exactly(2)); + } + + [Fact] + public async Task LaunchSubsystemAutomatically_will_return_without_triggering_anything() + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.LaunchSubsystemAutomatically(Guid.Empty); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemsRequest(It.IsAny>()), Times.Never); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystemsAutomatically_will_use_subsystemLauncher_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + await subsystemController.LaunchSubsystemsAutomatically(); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystems(It.IsAny>()), Times.Exactly(2)); // due the initialization method would actually trigger this method + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystemsAutomatically_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + await subsystemController.LaunchSubsystemsAutomatically(); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemsRequest(It.IsAny>()), Times.Exactly(2)); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystem_will_use_subsystemLauncher_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppedSubsystems = subsystems.Where(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + var subsystem = stoppedSubsystems.ElementAt(new Random().Next(0, stoppedSubsystems.Count())); + + await subsystemController.LaunchSubsystem(subsystem.Key.ToString()); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystem(subsystem.Key, subsystem.Value.Name)); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystem_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppedSubsystems = subsystems.Where(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + var subsystem = stoppedSubsystems.ElementAt(new Random().Next(0, stoppedSubsystems.Count())); + + await subsystemController.LaunchSubsystem(subsystem.Key.ToString()); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemsRequest(It.IsAny>())); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystems_will_use_subsystemLauncher_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsToLaunch = subsystems + .Where(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart) + .Select(x => x.Key.ToString()); + + await subsystemController.LaunchSubsystems(subsToLaunch); + + subsystemLauncherMock.Verify(x => x.LaunchSubsystems(It.IsAny>()), Times.Exactly(2)); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task LaunchSubsystems_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsToLaunch = subsystems + .Where(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart) + .Select(x => x.Key.ToString()); + + await subsystemController.LaunchSubsystems(subsToLaunch); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendLaunchSubsystemsRequest(It.IsAny>()), Times.Exactly(2)); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task RestartSubsystem_will_use_subsystemLauncher_to_restart_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsToRestart = subsystems.Where(x => x.Value.State == SubsystemState.Started || x.Value.State == SubsystemState.Running); + var subsystem = subsToRestart.ElementAt(new Random().Next(0, subsToRestart.Count())); + + await subsystemController.RestartSubsystem(subsystem.Key.ToString()); + + subsystemLauncherMock.Verify(x => x.RestartSubsystem(subsystem.Key, subsystem.Value.Name), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task RestartSubsystem_will_use_subsystemCommunicator_to_restart_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsToRestart = subsystems.Where(x => x.Value.State == SubsystemState.Started || x.Value.State == SubsystemState.Running); + var subsystem = subsToRestart.ElementAt(new Random().Next(0, subsToRestart.Count())); + + await subsystemController.RestartSubsystem(subsystem.Key.ToString()); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendRestartSubsystemsRequest(It.IsAny>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task RestartSubsystems_will_use_subsystemLauncher_to_restart_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsToRestart = subsystems + .Where(x => x.Value.State == SubsystemState.Started || x.Value.State == SubsystemState.Running) + .Select(x => x.Key.ToString()); + + await subsystemController.RestartSubsystems(subsToRestart); + + subsystemLauncherMock.Verify(x => x.RestartSubsystems(It.IsAny>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task RestartSubsystems_will_use_subsystemCommunicator_to_restart_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsToRestart = subsystems + .Where(x => x.Value.State == SubsystemState.Started || x.Value.State == SubsystemState.Running) + .Select(x => x.Key.ToString()); + + await subsystemController.RestartSubsystems(subsToRestart); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendRestartSubsystemsRequest(It.IsAny>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ShutdownAllRegisteredSubsystem_will_use_subsystemLauncher_to_shutdown_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + await subsystemController.ShutdownAllRegisteredSubsystem(); + + subsystemLauncherMock.Verify(x => x.ShutdownSubsystems(It.IsAny>>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ShutdownAllRegisteredSubsystem_will_use_subsystemCommunicator_to_shutdown_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + await subsystemController.ShutdownAllRegisteredSubsystem(); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendShutdownSubsystemsRequest(It.IsAny>>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ShutdownSubsystem_will_use_subsystemLauncher_to_shutdown_subsystem(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppableSubsystems = subsystems.Where(x => + x.Value.State == SubsystemState.Running || x.Value.State == SubsystemState.Started); + + var subsystem = stoppableSubsystems.ElementAt(new Random().Next(0, stoppableSubsystems.Count())); + await subsystemController.ShutdownSubsystem(subsystem.Key.ToString()); + + subsystemLauncherMock.Verify(x => x.ShutdownSubsystem(subsystem.Key, subsystem.Value.Name), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ShutdownSubsystem_will_use_subsystemCommunicator_to_shutdown_subsystem(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppableSubsystems = subsystems.Where(x => + x.Value.State == SubsystemState.Running || x.Value.State == SubsystemState.Started); + + var subsystem = stoppableSubsystems.ElementAt(new Random().Next(0, stoppableSubsystems.Count())); + await subsystemController.ShutdownSubsystem(subsystem.Key.ToString()); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendShutdownSubsystemsRequest(It.IsAny>()), Times.Once); + } + + [Fact] + public async Task ShutdownSubsystem_will_do_nothing() + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(new List>()); + + await subsystemController.ShutdownSubsystem(Guid.NewGuid().ToString()); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendShutdownSubsystemsRequest(It.IsAny>()), Times.Never); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ShutdownSubsystems_will_use_subsystemLauncher_to_shutdown_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppableSubsystems = subsystems + .Where(x => x.Value.State == SubsystemState.Running || x.Value.State == SubsystemState.Started && x.Value.AutomatedStart); + + await subsystemController.ShutdownSubsystems(stoppableSubsystems.Select(x => x.Key.ToString())); + + subsystemLauncherMock.Verify(x => x.ShutdownSubsystems(It.IsAny>>()), Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ShutdownSubsystems_will_use_subsystemCommunicator_to_launch_subsystems(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppableSubsystems = subsystems + .Where(x => x.Value.State == SubsystemState.Running || x.Value.State == SubsystemState.Started && x.Value.AutomatedStart); + + await subsystemController.ShutdownSubsystems(stoppableSubsystems.Select(x => x.Key.ToString())); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendShutdownSubsystemsRequest(It.IsAny>>()), Times.Once); + } + + [Fact] + public async Task ShutdownSubsystems_will_return_without_triggering_anything() + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(new List>()); + + await subsystemController.ShutdownSubsystems(new List()); + + subsystemLauncherCommunicatorMock.Verify(x => x.SendShutdownSubsystemsRequest(Enumerable.Empty>()), Times.Once); + } + + [Fact] + public async Task ShutdownSubsystems_will_log_exception() + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherCommunicatorMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncherCommunicator: subsystemLauncherCommunicatorMock.Object); + + await subsystemController.InitializeSubsystems(new List>()); + + await subsystemController.ShutdownSubsystems(null!); + + loggerMock.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Cannot terminate a subsystem/subsystems.")), + It.IsAny(), + It.IsAny>()), + Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task ModifySubsystemState_will_modify_the_state_and_trigger_UI_update(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var stoppableSubsystems = subsystems.Where(x => x.Value.State == SubsystemState.Started); + var subsystem = stoppableSubsystems.ElementAt(new Random().Next(0, stoppableSubsystems.Count())); + + await subsystemController.ModifySubsystemState(subsystem.Key, "DummyState"); + + Assert.Equal("DummyState", subsystem.Value.State); + + uiDelegateMock.Verify(x => x.AddSubsystems(It.IsAny>>()), Times.Once); // due IUiHandler function will be called twice as per after initialization of the subsystems we are pushing data to the uis. + uiDelegateMock.Verify(x => x.UpdateSubsystemInfo(It.IsAny(), It.IsAny()), Times.Once); + } + + [Fact] + public async Task ModifySubsystemState_will_return_and_wont_trigger_update() + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(null); + await subsystemController.ModifySubsystemState(Guid.NewGuid(), "DummyState"); + uiDelegateMock.Verify(x => x.AddSubsystems(It.IsAny>()), Times.Never); + uiDelegateMock.Verify(x => x.UpdateSubsystemInfo(It.IsAny(), It.IsAny()), Times.Never); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task AddSubsystems_will_add_elements_and_update_to_the_ui(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var newElements = new List> + { + new KeyValuePair( + Guid.NewGuid(), new SubsystemInfo() + { + State = SubsystemState.Stopped, + Name = "DummySubsystemNew" + }) + }; + + await subsystemController.AddSubsystems(newElements); + + var result = subsystemController.GetSubsystems(); + Assert.NotStrictEqual(subsystems, result); + Assert.NotStrictEqual(newElements, result); + + uiDelegateMock.Verify(x => x.AddSubsystems(It.IsAny>>()), Times.Exactly(2)); // due IUiHandler function will be called twice as per after initialization of the subsystems we are pushing data to the uis. + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task RemoveSubsystem_will_remove_element_without_triggering_shutdown(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsystemtoDelete = + subsystems.First(x => x.Value.State == SubsystemState.Stopped && !x.Value.AutomatedStart); + + await subsystemController.RemoveSubsystem(subsystemtoDelete.Key); + + var result = subsystemController.GetSubsystems(); + + Assert.DoesNotContain(subsystemtoDelete, result); + + subsystemLauncherMock.Verify(x => x.ShutdownSubsystem(It.IsAny(), It.IsAny()), Times.Never); + } + + [Theory] + [ClassData(typeof(SubsystemControllerTheoryData))] + public async Task RemoveSubsystem_will_remove_element_wit_triggering_shutdown(IEnumerable> subsystems) + { + var loggerMock = CreateLoggerMock(); + var uiDelegateMock = new Mock(); + var subsystemLauncherMock = new Mock(); + var subsystemController = CreateSubsystemController( + logger: loggerMock.Object, + uiHandler: uiDelegateMock.Object, + dummySubsystemLauncher: subsystemLauncherMock.Object); + + await subsystemController.InitializeSubsystems(subsystems); + + var subsystemtoDelete = + subsystems.First(x => x.Value.State == SubsystemState.Started); + + await subsystemController.RemoveSubsystem(subsystemtoDelete.Key); + + var result = subsystemController.GetSubsystems(); + + Assert.DoesNotContain(subsystemtoDelete, result); + + subsystemLauncherMock.Verify(x => x.ShutdownSubsystem(It.IsAny(), It.IsAny()), Times.Once); + } + + private static Mock CreateLoggerMock() + { + var loggerMock = new Mock(); + + var loggerFilterOptions = new LoggerFilterOptions(); + + loggerFilterOptions.AddFilter("", LogLevel.Debug); + + loggerMock + .Setup(x => x.IsEnabled(It.IsAny())) + .Returns(level => loggerFilterOptions.MinLevel <= level); + + return loggerMock; + } + + private static ISubsystemController CreateSubsystemController( + ILogger logger, + IUiHandler uiHandler, + ISubsystemLauncher? dummySubsystemLauncher = null, + ISubsystemLauncherCommunicator? dummySubsystemLauncherCommunicator = null) + { + ISubsystemController subsystemController = null; + if (dummySubsystemLauncher != null) + subsystemController = new SubsystemController( + subsystemLauncher: dummySubsystemLauncher, + uiHandler: uiHandler, + logger: logger); + else if (dummySubsystemLauncherCommunicator != null) + subsystemController = new SubsystemController( + subsystemLauncherCommunicator: dummySubsystemLauncherCommunicator, + uiHandler: uiHandler, + logger: logger); + + return subsystemController; + } + + private class SubsystemControllerTheoryData : TheoryData + { + private readonly Dictionary _subsystems = new() + { + { Guid.NewGuid(), new(){ State = SubsystemState.Started, Name = "DummySubsystem1" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Started, Name = "DummySubsystem2" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Running, Name = "DummySubsystem3" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Running, Name = "DummySubsystem4" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Stopped, Name = "DummySubsystem5" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Stopped, Name = "DummySubsystem6" , AutomatedStart = true }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Stopped, Name = "DummySubsystem7" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Stopped, Name = "DummySubsystem8" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Stopped, Name = "DummySubsystem9" }}, + { Guid.NewGuid(), new(){ State = SubsystemState.Stopped, Name = "DummySubsystem10" }}, + }; + + public SubsystemControllerTheoryData() + { + AddRow(_subsystems); + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Subsystems/SubsystemLauncher.Tests.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Subsystems/SubsystemLauncher.Tests.cs new file mode 100644 index 000000000..52da3d1ef --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Core.Tests/Subsystems/SubsystemLauncher.Tests.cs @@ -0,0 +1,521 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Moq; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Core.DependencyInjection; +using ProcessExplorer.Core.Subsystems; +using Xunit; + +namespace ProcessExplorer.Core.Tests.Subsystems; + +public class SubsystemLauncherTests +{ + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task LaunchSubsystem_will_invoke_dummy_launch_request(TestInformation testInformation) + { + // Arrange + var launchRequestMock = new Mock>(); + var createLaunchRequestMock = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStartType: createLaunchRequestMock.Object, + dummyStartRequest: launchRequestMock.Object); + + // Act + var result = await subsystemLauncher.LaunchSubsystem(testInformation.LaunchRequestId, testInformation.LaunchRequestSubsystemName); + + // Assert + Assert.Equal(testInformation.ExpectedLaunchStateResult, result); + + var element = testInformation.Subsystems.FirstOrDefault(x => x.Key == testInformation.LaunchRequestId); + + if (element.Value.State != SubsystemState.Started && element.Value.State != SubsystemState.Running) + launchRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Once); + + if(testInformation.ExpectedLogMessage != string.Empty) + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains(testInformation.LaunchRequestId.ToString()) && v.ToString()!.Contains(testInformation.ExpectedLogMessage)), + It.IsAny(), + It.IsAny>()), + Times.Once); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task LauchSubsystem_will_return_stopped_when_no_launchType_added(TestInformation testInformation) + { + //Arrange + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object); + + // Act + var result = await subsystemLauncher.LaunchSubsystem(testInformation.LaunchRequestId, testInformation.LaunchRequestSubsystemName); + + //Assert + Assert.Equal(SubsystemState.Stopped, result); //That is the default value + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task LaunchSubsystemAfterTime_will_wait_before_launching_a_subsystem(TestInformation testInformation) + { + // Arrange + var loggerMock = CreateLoggerMock(); + var periodOfTime = 150; + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object); + + // Act + var stopwatch = Stopwatch.StartNew(); + await subsystemLauncher.LaunchSubsystemAfterTime(testInformation.LaunchRequestId, testInformation.LaunchRequestSubsystemName, periodOfTime); + stopwatch.Stop(); + + // Assert + Assert.True(stopwatch.ElapsedMilliseconds >= periodOfTime); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task LaunchSubsystems_will_launch_subsystems(TestInformation testInformation) + { + // Arrange + var launchRequestMock = new Mock>(); + var createLaunchRequestMock = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStartType: createLaunchRequestMock.Object, + dummyStartRequest: launchRequestMock.Object); + + // Act + var result = await subsystemLauncher.LaunchSubsystems(testInformation.LaunchRequestIds); + + // Assert + Assert.Equal(testInformation.ExpectedLaunchStateResults, result); + + launchRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Exactly(testInformation.ExpectedLaunchStateResults.Count())); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task ShutdownSubsytem_will_trigger_the_shutdown_command(TestInformation testInformation) + { + // Arrange + var stopRequestMock = new Mock>(); + var createStopRequest = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStopType: createStopRequest.Object, + dummyStopRequest: stopRequestMock.Object); + + // Act + var result = await subsystemLauncher.ShutdownSubsystem(testInformation.StopRequestId, testInformation.StopRequestSubsystemName); + + // Assert + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Stopping a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + Assert.Equal(SubsystemState.Stopped, result); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task ShutdownSubsytem_will_return_running_state_if_no_stop_request_behavior_is_added(TestInformation testInformation) + { + // Arrange + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object); + + // Act + var result = await subsystemLauncher.ShutdownSubsystem(testInformation.StopRequestId, testInformation.StopRequestSubsystemName); + + // Assert + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Stopping a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + Assert.Equal(SubsystemState.Running, result); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task StopSubsystems_will_trigger_stop_request(TestInformation testInformation) + { + // Arrange + var stopRequestMock = new Mock>(); + var createStopRequest = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStopType: createStopRequest.Object, + dummyStopRequest: stopRequestMock.Object); + + // Act + var result = await subsystemLauncher.ShutdownSubsystems(testInformation.StopRequestIds); + + // Assert + Assert.Equal(testInformation.ExpectedStopStateResults, result); + + stopRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Exactly(testInformation.ExpectedStopStateResults.Count())); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task RestartSubsystem_will_return_started_state_and_trigger_launch_and_stop_request(TestInformation testInformation) + { + // Arrange + var launchRequestMock = new Mock>(); + var createLaunchRequestMock = new Mock>(); + var stopRequestMock = new Mock>(); + var createStopRequest = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStartType: createLaunchRequestMock.Object, + dummyStartRequest: launchRequestMock.Object, + createDummyStopType: createStopRequest.Object, + dummyStopRequest: stopRequestMock.Object); + + // Act + var result = await subsystemLauncher.RestartSubsystem(testInformation.StopRequestId, testInformation.StopRequestSubsystemName); + + // Assert + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Stopping a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + stopRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Once); + + launchRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Once); + + Assert.Equal(SubsystemState.Started, result); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task RestartSubsystem_will_log_subsystem_stop_debugerror_if_no_stop_request_is_defined(TestInformation testInformation) + { + // Arrange + var launchRequestMock = new Mock>(); + var createLaunchRequestMock = new Mock>(); + + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStartType: createLaunchRequestMock.Object, + dummyStartRequest: launchRequestMock.Object); + + // Act + var result = await subsystemLauncher.RestartSubsystem(testInformation.StopRequestId, testInformation.StopRequestSubsystemName); + + // Assert + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Stopping a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + loggerMock.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Error while restarting a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + launchRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Never); + + Assert.Equal(SubsystemState.Running, result); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task RestartSubsytem_will_log_subsystem_restart_error_if_no_launch_request_is_defined(TestInformation testInformation) + { + // Arrange + var stopRequestMock = new Mock>(); + var createStopRequest = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStopType: createStopRequest.Object, + dummyStopRequest: stopRequestMock.Object); + + // Act + var result = await subsystemLauncher.RestartSubsystem(testInformation.StopRequestId, testInformation.StopRequestSubsystemName); + + // Assert + loggerMock.Verify( + x => x.Log( + LogLevel.Debug, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Stopping a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + loggerMock.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Error while restarting a subsystem with id:") && v.ToString()!.Contains(testInformation.StopRequestId.ToString())), + It.IsAny(), + It.IsAny>()), + Times.Once); + + stopRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Once); + + Assert.Equal(SubsystemState.Stopped, result); + } + + [Theory] + [ClassData(typeof(SubsystemLauncherTheoryData))] + public async Task RestartSubsystems_will_return_started_state_and_trigger_launch_and_stop_request(TestInformation testInformation) + { + // Arrange + var launchRequestMock = new Mock>(); + var createLaunchRequestMock = new Mock>(); + var stopRequestMock = new Mock>(); + var createStopRequest = new Mock>(); + var loggerMock = CreateLoggerMock(); + + var subsystemLauncher = CreateSubsystemLauncher( + logger: loggerMock.Object, + createDummyStartType: createLaunchRequestMock.Object, + dummyStartRequest: launchRequestMock.Object, + createDummyStopType: createStopRequest.Object, + dummyStopRequest: stopRequestMock.Object); + + // Act + var result = await subsystemLauncher.RestartSubsystems(testInformation.StopRequestIds); + + // Assert + stopRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Exactly(testInformation.ExpectedStopStateResults.Count())); + + launchRequestMock.Verify(x => x.Invoke(It.IsAny()), Times.Exactly(testInformation.ExpectedStopStateResults.Count())); + } + + private Mock CreateLoggerMock() + { + var loggerMock = new Mock(); + + var loggerFilterOptions = new LoggerFilterOptions(); + + loggerFilterOptions.AddFilter("", LogLevel.Debug); + + loggerMock + .Setup(x => x.IsEnabled(It.IsAny())) + .Returns(level => loggerFilterOptions.MinLevel <= level); + + return loggerMock; + } + + private ISubsystemLauncher CreateSubsystemLauncher( + ILogger logger, + Action? dummyStartRequest = null, + Action? dummyStopRequest = null, + Func? createDummyStartType = null, + Func? createDummyStopType = null) + { + var subsystemLauncher = new SubsystemLauncher( + logger, + new SubsystemLauncherOptions() + { + CreateLaunchRequest = createDummyStartType, + CreateStopRequest = createDummyStopType, + LaunchRequest = dummyStartRequest, + StopRequest = dummyStopRequest, + }); + + return subsystemLauncher; + } + + private class SubsystemLauncherTheoryData : TheoryData + { + private readonly KeyValuePair[] _subsystems = + { + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Started, Name = "TestSubsystem1" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Stopped, Name = "TestSubsystem2" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Stopped, Name = "TestSubsystem3" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Running, Name = "TestSubsystem3" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Stopped, Name = "TestSubsystem5" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Stopped, Name = "TestSubsystem6" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Started, Name = "TestSubsystem7" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Started, Name = "TestSubsystem8" }), + new(Guid.NewGuid(), new SubsystemInfo { State = SubsystemState.Started, Name = "TestSubsystem9" }), + }; + + public SubsystemLauncherTheoryData() + { + AddRow(CreateTestInformation()); + } + + //Generating random data and its preferably expected value + private TestInformation CreateTestInformation() + { + var stopppableSubsystems = + _subsystems + .Where(subsystem => subsystem.Value.State != SubsystemState.Stopped); + + var launchableSubsystems = + _subsystems + .Where(subsystem => subsystem.Value.State == SubsystemState.Stopped); + + var launchedSubsystemsCount = stopppableSubsystems.Count(); + var stoppedSubsystemsCount = _subsystems.Length - launchedSubsystemsCount; + + var randomLaunchableSubsystem = GetRandomSubsystem(launchableSubsystems); + var randomStoppableSubsystem = GetRandomSubsystem(stopppableSubsystems); + + //Because the SubsystemLauncher does not search for the expectedState its just executing the gotten command from the UI. + var expectedLaunchState = + randomLaunchableSubsystem.Value.State == SubsystemState.Stopped || randomLaunchableSubsystem.Value.State == SubsystemState.Running + ? SubsystemState.Started + : randomLaunchableSubsystem.Value.State; + + var expectedLaunchLogMessage = randomLaunchableSubsystem.Value.State == SubsystemState.Stopped + ? "Starting" + : ""; + + var expectedStopState = + randomLaunchableSubsystem.Value.State == SubsystemState.Started || randomLaunchableSubsystem.Value.State == SubsystemState.Running + ? SubsystemState.Stopped + : randomLaunchableSubsystem.Value.State; + + var launchRequestIds = new Dictionary(); + var expectedLaunchStateResults = new Dictionary(); + + // Fill LaunchRequestIds and ExpectedLaunchStateResults when LaunchSubsystems will be tested + if (_subsystems.Length > launchedSubsystemsCount) + { + var random = new Random().Next(1, stoppedSubsystemsCount); + for (int i = 0; i < random; i++) + { + var subsystem = GetRandomSubsystemAndItsExpectedResult(launchableSubsystems, SubsystemState.Started); + if (launchRequestIds.ContainsKey(subsystem.Key)) continue; + launchRequestIds.Add(subsystem.Key, subsystem.Value.Key); + expectedLaunchStateResults.Add(subsystem.Key, subsystem.Value.Value); + } + } + + var stopRequestIds = new Dictionary(); + var expectedStopStateResults = new Dictionary(); + + // Checking if there is subsystems which can be stopped + if (_subsystems.Length > stoppedSubsystemsCount) + { + var random = new Random().Next(1, launchedSubsystemsCount); + for (int i = 0; i < random; i++) + { + var subsystem = GetRandomSubsystemAndItsExpectedResult(stopppableSubsystems, SubsystemState.Stopped); + if (stopRequestIds.ContainsKey(subsystem.Key)) continue; + stopRequestIds.Add(subsystem.Key, subsystem.Value.Key); + expectedStopStateResults.Add(subsystem.Key, subsystem.Value.Value); + } + } + + var info = new TestInformation + { + Subsystems = _subsystems, + LaunchRequestSubsystemName = randomLaunchableSubsystem.Value.Name, + LaunchRequestId = randomLaunchableSubsystem.Key, + StopRequestId = randomStoppableSubsystem.Key, + StopRequestSubsystemName = randomStoppableSubsystem.Value.Name, + ExpectedLaunchStateResult = expectedLaunchState, + ExpectedStopStateResult = expectedStopState, + ExpectedLogMessage = expectedLaunchLogMessage, + LaunchRequestIds = launchRequestIds, + StopRequestIds = stopRequestIds, + ExpectedLaunchStateResults = expectedLaunchStateResults, + ExpectedStopStateResults = expectedStopStateResults + }; + + return info; + } + + private static KeyValuePair GetRandomSubsystem(IEnumerable> subsystems) + { + var random = new Random().Next(0, subsystems.Count()); + return subsystems.ElementAt(random); + } + + private KeyValuePair> GetRandomSubsystemAndItsExpectedResult(IEnumerable> subsystems, string expectedStateResult) + { + var subsystem = GetRandomSubsystem(subsystems); + return new(subsystem.Key, new(subsystem.Value.Name, expectedStateResult)); + } + } + + public class TestInformation + { + public Guid LaunchRequestId { get; set; } + public Guid StopRequestId { get; set; } + public string LaunchRequestSubsystemName { get; set; } + public string StopRequestSubsystemName { get; set; } + public IEnumerable> LaunchRequestIds { get; set; } = Enumerable.Empty>(); + public IEnumerable> StopRequestIds { get; set; } = Enumerable.Empty>(); + public KeyValuePair[] Subsystems { get; set; } + public string ExpectedLaunchStateResult { get; set; } + public string ExpectedStopStateResult { get; set; } + public IEnumerable> ExpectedLaunchStateResults { get; set; } = Enumerable.Empty>(); + public IEnumerable> ExpectedStopStateResults { get; set; } = Enumerable.Empty>(); + public string ExpectedLogMessage { get; set; } + } + + public record DummyStartType(Guid id, string name); + public record DummyStopType(Guid id); +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Server.EndToEndTests/EndToEndTests.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Server.EndToEndTests/EndToEndTests.cs new file mode 100644 index 000000000..db6b18f7a --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Server.EndToEndTests/EndToEndTests.cs @@ -0,0 +1,209 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf.WellKnownTypes; +using Grpc.Core; +using Grpc.Net.Client; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Abstractions.Infrastructure.Protos; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Server.DependencyInjection; +using ProcessExplorer.Server.Server.Abstractions; +using Xunit; +using ProcessExplorer.Core.DependencyInjection; + +namespace ProcessExplorer.Server.IntegrationTests; + +public class EndToEndTests : IAsyncLifetime +{ + private IHost? _host; + public readonly string Host = "localhost"; + public readonly int Port = 5056; + + public async Task DisposeAsync() + { + if (_host != null) + await _host.StopAsync(); + } + + [SkippableFact] + public async Task Client_can_connect() + { + var client = CreateGrpcClient(); + + using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); + + var messages = new List(); + + using var call = client.Subscribe(new Empty(), cancellationToken: cancellationTokenSource.Token); + + // We want to receive the message, that the subscription is established, and we do not want to wait. + // Due to that no processes/subsystems/runtime information have not been declared it will just receive the subscription alive notification + + try + { + await foreach (var message in call.ResponseStream.ReadAllAsync()) + { + messages.Add(message); + } + } + catch (RpcException) { } + + //TODO(Lilla): investigate why the integrationtests are keeping to fail on CI, but works everytime locally. + Skip.If(messages.Count < 1, "Error while running on CI..."); + + Assert.Single(messages); + Assert.Equal(ActionType.SubscriptionAliveAction, messages[0].Action); + } + + [SkippableFact] + public async Task Client_can_subscribe_and_receive_messages() + { + // defining here some dummy subsystems to trigger the ProcessExplorer backend to send information about it to the defined ui connections. (not just the subscription alive notification) + var aggregator = _host?.Services.GetRequiredService(); + if (aggregator == null) throw new ArgumentNullException(nameof(aggregator)); + + var dummyId = Guid.NewGuid(); + + var dummySubsystemInfo = new SubsystemInfo() + { + State = SubsystemState.Running, + Name = "DummySubsystem", + UIType = "dummyUiType", + StartupType = "dummyStartUpType", + Path = "dummyPath", + AutomatedStart = false, + }; + + var subsystems = new Dictionary() + { + { dummyId, dummySubsystemInfo } + }; + + await aggregator.SubsystemController.InitializeSubsystems(subsystems); + + var client = CreateGrpcClient(); + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); + var messages = new List(); + + using var call = client.Subscribe(new Empty(), cancellationToken: cancellationTokenSource.Token); + + //try catch block to avoid OperationCanceledException due to that we are just waiting for 2 seconds + try + { + await foreach (var message in call.ResponseStream.ReadAllAsync()) + { + messages.Add(message); + } + } + catch(RpcException) { } + + // We just need to receive SubscriptionAlive and a subsystems collection, skipping if that some error occurred + + //TODO(Lilla): investigate why the integrationtests are keeping to fail on CI, but works everytime locally. + Skip.If(messages.Count < 2, "Local testing does not throws error"); + + Assert.Equal(2, messages.Count); + Assert.Equal(ActionType.SubscriptionAliveAction, messages[0].Action); + Assert.Equal(ActionType.AddSubsystemsAction, messages[1].Action); + Assert.Single(messages[1].Subsystems); + Assert.Contains(dummyId.ToString(), messages[1].Subsystems.Keys); + + //In Proto3, all fields are optional and have a default value. For example, a string field has a default value of empty string ("") and an int field has a default value of zero (0). + //If you want to create a proto message without a certain field, you have to set its value to the default value. + var result = messages[1].Subsystems[dummyId.ToString()]; + + Assert.NotNull(result); + Assert.Equal(dummySubsystemInfo.Name, result.Name); + Assert.Equal(dummySubsystemInfo.State, result.State); + Assert.Equal(dummySubsystemInfo.UIType, result.UiType); + Assert.Equal(dummySubsystemInfo.StartupType, result.StartupType); + Assert.Equal(dummySubsystemInfo.Path, result.Path); + Assert.Equal(dummySubsystemInfo.AutomatedStart, result.AutomatedStart); + Assert.Empty(result.Arguments); + Assert.Empty(result.Url); + Assert.Empty(result.Description); + } + + [SkippableFact] + public void Client_can_send_message() + { + var client = CreateGrpcClient(); + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); + + var message = new Message() + { + Action = ActionType.SubscriptionAliveAction, + Description = "dummy message" + }; + + Empty? result = null; + try + { + result = client.Send(message, cancellationToken: cancellationTokenSource.Token); + } + catch (RpcException) { } + + //TODO(Lilla): investigate why the integrationtests are keeping to fail on CI, but works everytime locally. + Skip.If(result == null, "Error while running on CI..."); + Assert.NotNull(result); + Assert.IsType(result); + } + + public async Task InitializeAsync() + { + IHostBuilder builder = new HostBuilder(); + + builder.ConfigureServices( + (context, services) => services + .AddProcessExplorerWindowsServerWithGrpc(pe => pe.UseGrpc()) + .ConfigureSubsystemLauncher(Start, Stop, CreateDummyStartType, CreateDummyStopType) + .Configure(op => + { + op.Host = Host; + op.Port = Port; + })); + + _host = builder.Build(); + await _host.StartAsync(); + } + + private ProcessExplorerMessageHandler.ProcessExplorerMessageHandlerClient CreateGrpcClient() + { + var channel = GrpcChannel.ForAddress($"http://{Host}:{Port}/"); + var client = new ProcessExplorerMessageHandler.ProcessExplorerMessageHandlerClient(channel); + + return client; + } + + private static DummyStartType CreateDummyStartType(Guid id, string name) + { + return new DummyStartType(id, name); + } + + private static DummyStopType CreateDummyStopType(Guid id) + { + return new DummyStopType(id); + } + + private static void Start(DummyStartType dummy) { } + private static void Stop(DummyStopType dummy) { } + + private record DummyStartType(Guid id, string name); + private record DummyStopType(Guid id); +} diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Server.EndToEndTests/ProcessExplorer.Server.IntegrationTests.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Server.EndToEndTests/ProcessExplorer.Server.IntegrationTests.csproj new file mode 100644 index 000000000..0b2636693 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/ProcessExplorer.Server.EndToEndTests/ProcessExplorer.Server.IntegrationTests.csproj @@ -0,0 +1,31 @@ + + + + net6.0 + enable + false + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Program.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/Helper.cs similarity index 76% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Program.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/Helper.cs index 0ef7b0f3e..e09c6b9d5 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Program.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/Helper.cs @@ -10,13 +10,12 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace SuperRPC_POC; +using System.Diagnostics; -public class Program +namespace TestConsoleApp; + +internal static class Helper { - public static async Task Main(string[] args) - { - var webSocketService = new WebSocketService(); - await webSocketService.Start(); - } + [Conditional("DEBUG")] + public static void IsDebug(ref bool isDebug) => isDebug = true; } diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/Program.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/Program.cs new file mode 100644 index 000000000..de5eb0725 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/Program.cs @@ -0,0 +1,40 @@ +// Morgan Stanley makes this available to you under the Apache License, +// Version 2.0 (the "License"). You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0. +// +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. Unless required by applicable law or agreed +// to in writing, software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Diagnostics; +using TestConsoleApp; + +Console.WriteLine("Hello, World!"); +var stopwatch = Stopwatch.StartNew(); +Console.WriteLine("This is a test application to test the ProcessMonitor..."); + +Console.WriteLine("Starting a process..."); + +var isDebug = false; +Helper.IsDebug(ref isDebug); + +var folder = isDebug ? "Debug" : "Release"; +Console.WriteLine(folder); + +var childProcess = Process.Start($"../../../../TestConsoleApp2/bin/{folder}/net6.0/TestConsoleApp2.exe"); + +var sum = 0; +for (int i = 0; i < 50000000; i++) +{ + sum += i; +} +Thread.Sleep(10000); + +Console.WriteLine("Terminating a process...."); +childProcess.Kill(); +stopwatch.Stop(); +Console.WriteLine("ChildProcess is terminated"); diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ProcessExplorerMessageRouterTopics/ProcessExplorerMessageRouterTopics.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/TestConsoleApp.csproj similarity index 86% rename from prototypes/multi-module-prototype/examples/multi-module-example/ProcessExplorerMessageRouterTopics/ProcessExplorerMessageRouterTopics.csproj rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/TestConsoleApp.csproj index 132c02c59..74abf5c97 100644 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ProcessExplorerMessageRouterTopics/ProcessExplorerMessageRouterTopics.csproj +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp/TestConsoleApp.csproj @@ -1,6 +1,7 @@ + Exe net6.0 enable enable diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/User/AppUserInfo.cs b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp2/Program.cs similarity index 69% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/User/AppUserInfo.cs rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp2/Program.cs index a03569845..40232a4c9 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/User/AppUserInfo.cs +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp2/Program.cs @@ -10,13 +10,9 @@ // or implied. See the License for the specific language governing permissions // and limitations under the License. -namespace ProcessExplorer.Processes.User; - -public class AppUserInfo -{ - #region Properties - public string? UserName { get; internal set; } - public bool? IsAdmin { get; internal set; } - public MachineInfo? MachineInfo { get; internal set; } = default; - #endregion -} +Console.WriteLine("Hello, World!"); +Console.WriteLine("Doing some stuff"); +var dummy = new object(); +var dummyString = string.Empty; +Thread.Sleep(15000); +Console.WriteLine("Exiting..."); diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/ProcessExplorer.csproj b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp2/TestConsoleApp2.csproj similarity index 51% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/ProcessExplorer.csproj rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp2/TestConsoleApp2.csproj index 6d0f619b7..74abf5c97 100644 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/ProcessExplorer.csproj +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/dotnet/test/TestConsoleApp2/TestConsoleApp2.csproj @@ -1,14 +1,10 @@ + Exe net6.0 enable enable - - - - - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/.browserslistrc b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/.browserslistrc similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/.browserslistrc rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/.browserslistrc diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/.editorconfig b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/.editorconfig similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/.editorconfig rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/.editorconfig diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/.eslintrc.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/.eslintrc.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/.eslintrc.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/.eslintrc.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/README.md b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/README.md similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/README.md rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/README.md diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/angular.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/angular.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/angular.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/angular.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/ignite-ui-cli.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/ignite-ui-cli.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/ignite-ui-cli.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/ignite-ui-cli.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/karma.conf.js b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/karma.conf.js similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/karma.conf.js rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/karma.conf.js diff --git a/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/package-lock.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/package-lock.json new file mode 100644 index 000000000..cce8aac73 --- /dev/null +++ b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/package-lock.json @@ -0,0 +1,14080 @@ +{ + "name": "@morgan-stanley/composeui-process-explorer-frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@morgan-stanley/composeui-process-explorer-frontend", + "version": "0.1.0", + "dependencies": { + "@angular/animations": "^15.1.0", + "@angular/common": "^15.1.0", + "@angular/compiler": "^15.1.0", + "@angular/core": "^15.1.0", + "@angular/forms": "^15.1.0", + "@angular/platform-browser": "^15.1.0", + "@angular/platform-browser-dynamic": "^15.1.0", + "@angular/router": "^15.1.0", + "core-js": "^3.6.5", + "hammerjs": "^2.0.8", + "igniteui-angular": "^15.0.9", + "igniteui-angular-charts": "^15.0.0", + "igniteui-angular-core": "^15.0.0", + "jszip": "^3.5.0", + "material-icons": "1.13.1", + "minireset.css": "~0.0.4", + "rxjs": "~7.8.0", + "super-rpc": "^1.0.1", + "throttle-typescript": "^1.1.0", + "tslib": "^2.3.0", + "web-animations-js": "^2.3.2", + "zone.js": "~0.13.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^15.2.4", + "@angular-eslint/builder": "^15.2.0", + "@angular-eslint/eslint-plugin": "^15.2.0", + "@angular-eslint/eslint-plugin-template": "^15.2.0", + "@angular-eslint/schematics": "^15.2.0", + "@angular-eslint/template-parser": "^15.2.0", + "@angular/cli": "15.2.4", + "@angular/compiler-cli": "^15.1.0", + "@babel/runtime": "7.21.0", + "@igniteui/angular-schematics": "^15.0.1101", + "@types/jasmine": "~4.3.0", + "@types/node": "^12.11.1", + "@typescript-eslint/eslint-plugin": "^5.51.0", + "@typescript-eslint/parser": "^5.51.0", + "eslint": "^7.26.0", + "jasmine-core": "~4.6.0", + "jasmine-spec-reporter": "~7.0.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "^3.1.1", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.0.0", + "typescript": "~4.9.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1502.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1502.6.tgz", + "integrity": "sha512-n4oJ9vzFWwabf+AfgqqevVzdJhNKNCav7ytefjD/Y01vkNwlXqWnHcvyyHCLkVibJ6WR8J9lK4t77j/HFlDvWQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "15.2.6", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular": { + "version": "15.2.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-15.2.6.tgz", + "integrity": "sha512-OmMcdXXUrAdZNxwxDE8SUx1FMcq9FyMnrSv1PmP9sHPBoxAdBVc/qNdGA9V7C5yHvWHGgzsx7ZK5TDuvifzS5g==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.2.0", + "@angular-devkit/architect": "0.1502.6", + "@angular-devkit/build-webpack": "0.1502.6", + "@angular-devkit/core": "15.2.6", + "@babel/core": "7.20.12", + "@babel/generator": "7.20.14", + "@babel/helper-annotate-as-pure": "7.18.6", + "@babel/helper-split-export-declaration": "7.18.6", + "@babel/plugin-proposal-async-generator-functions": "7.20.7", + "@babel/plugin-transform-async-to-generator": "7.20.7", + "@babel/plugin-transform-runtime": "7.19.6", + "@babel/preset-env": "7.20.2", + "@babel/runtime": "7.20.13", + "@babel/template": "7.20.7", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "15.2.6", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.13", + "babel-loader": "9.1.2", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "4.21.5", + "cacache": "17.0.4", + "chokidar": "3.5.3", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.16", + "css-loader": "6.7.3", + "esbuild-wasm": "0.17.8", + "glob": "8.1.0", + "https-proxy-agent": "5.0.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "karma-source-map-support": "1.4.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.29.0", + "mini-css-extract-plugin": "2.7.2", + "open": "8.4.1", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "piscina": "3.2.0", + "postcss": "8.4.21", + "postcss-loader": "7.0.2", + "resolve-url-loader": "5.0.0", + "rxjs": "6.6.7", + "sass": "1.58.1", + "sass-loader": "13.2.0", + "semver": "7.3.8", + "source-map-loader": "4.0.1", + "source-map-support": "0.5.21", + "terser": "5.16.3", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.5.0", + "webpack": "5.76.1", + "webpack-dev-middleware": "6.0.1", + "webpack-dev-server": "4.11.1", + "webpack-merge": "5.8.0", + "webpack-subresource-integrity": "5.1.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "esbuild": "0.17.8" + }, + "peerDependencies": { + "@angular/compiler-cli": "^15.0.0", + "@angular/localize": "^15.0.0", + "@angular/platform-server": "^15.0.0", + "@angular/service-worker": "^15.0.0", + "karma": "^6.3.0", + "ng-packagr": "^15.0.0", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=4.8.2 <5.0" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1502.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1502.6.tgz", + "integrity": "sha512-X7XQ11QDz2Bs5qpJ3a5glIytvI+S74ORQxdzvT6a6KB8ayW0SgZEhTwD+GF7pa5My8draIaXBGzzQR1qmpWK5Q==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1502.6", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^5.30.0", + "webpack-dev-server": "^4.0.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/core": { + "version": "15.2.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.6.tgz", + "integrity": "sha512-YVTWZ+M+xNKdFX4EnY9QX49PZraawiaA0iTd2CUW8ZoTUvU7yOGMKZLSdz6aokTMRVfm0449wt6YL994ibOo1g==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "6.6.7", + "source-map": "0.7.4" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/schematics": { + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-15.2.4.tgz", + "integrity": "sha512-/W7/vvn59PAVLzhcvD4/N/E8RDhub8ny1A7I96LTRjC5o+yvVV16YJ4YJzolrRrIEN01KmLVQJ9A58VCaweMgw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "15.2.4", + "jsonc-parser": "3.2.0", + "magic-string": "0.29.0", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.4.tgz", + "integrity": "sha512-yl+0j1bMwJLKShsyCXw77tbJG8Sd21+itisPLL2MgEpLNAO252kr9zG4TLlFRJyKVftm2l1h78KjqvM5nbOXNg==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "6.6.7", + "source-map": "0.7.4" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-eslint/builder": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-15.2.1.tgz", + "integrity": "sha512-7x2DANebLRl997Mj4DhZrnz5+vnSjavGGveJ0mBuU7CEsL0ZYLftdRqL0e0HtU3ksseS7xpchD6OM08nkNgySw==", + "dev": true, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-15.2.1.tgz", + "integrity": "sha512-LO7Am8eVCr7oh6a0VmKSL7K03CnQEQhFO7Wt/YtbfYOxVjrbwmYLwJn+wZPOT7A02t/BttOD/WXuDrOWtSMQ/Q==", + "dev": true + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-15.2.1.tgz", + "integrity": "sha512-OM7b1kS4E4CkXjkaWN+lEzawh4VxY6l7FO1Cuk4s7iv3/YpZG3rJxIZBqnFLTixwrBuqw8y4FNBzF3eDgmFAUw==", + "dev": true, + "dependencies": { + "@angular-eslint/utils": "15.2.1", + "@typescript-eslint/utils": "5.48.2" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-15.2.1.tgz", + "integrity": "sha512-IeiSLk6YxapFdH2z5o/O3R7VwtBd2T6fWmhLFPwDYMDknrwegnOjwswCdBplOccpUp0wqlCeGUx7LTsuzwaz7w==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "15.2.1", + "@angular-eslint/utils": "15.2.1", + "@typescript-eslint/type-utils": "5.48.2", + "@typescript-eslint/utils": "5.48.2", + "aria-query": "5.1.3", + "axobject-query": "3.1.1" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/schematics": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-15.2.1.tgz", + "integrity": "sha512-0ZfBCejHWIcgy3J5kFs9sS/jqi8i5AptxggOwFySOlCLJ+CzNrktjD4jff1Zy8K/VLzY0Ci0BSZXvgWfP0k9Rg==", + "dev": true, + "dependencies": { + "@angular-eslint/eslint-plugin": "15.2.1", + "@angular-eslint/eslint-plugin-template": "15.2.1", + "ignore": "5.2.4", + "strip-json-comments": "3.1.1", + "tmp": "0.2.1" + }, + "peerDependencies": { + "@angular/cli": ">= 15.0.0 < 16.0.0" + } + }, + "node_modules/@angular-eslint/template-parser": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-15.2.1.tgz", + "integrity": "sha512-ViCi79gC2aKJecmYLkOT+QlT5WMRNXeYz0Dr9Pr8qXzIbY0oAWE7nOT5jkXwQ9oUk+ybtGCWHma5JVJWVJsIog==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "15.2.1", + "eslint-scope": "^7.0.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/utils": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-15.2.1.tgz", + "integrity": "sha512-++FneAJHxJqcSu0igVN6uOkSoHxlzgLoMBswuovYJy3UKwm33/T6WFku8++753Ca/JucIoR1gdUfO7SoSspMDg==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "15.2.1", + "@typescript-eslint/utils": "5.48.2" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular/animations": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-15.2.8.tgz", + "integrity": "sha512-I3xh8EASQ04s3qXQYpIORI0jFiFmvBQERBqS70TieTCIML7banOf9R3K7sAWB9frG5J0CEUwr+wtF47DCs/7eQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "15.2.8" + } + }, + "node_modules/@angular/cli": { + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-15.2.4.tgz", + "integrity": "sha512-nQFnrt9aWwqkyhJMaZvjHXXuxeR1pZNcpZEzTA5nXtpVeNs8U7EBFCyJ+cYecFX0LHe36SoxXcbfnNEKHt3NVQ==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1502.4", + "@angular-devkit/core": "15.2.4", + "@angular-devkit/schematics": "15.2.4", + "@schematics/angular": "15.2.4", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "3.0.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "npm-package-arg": "10.1.0", + "npm-pick-manifest": "8.0.1", + "open": "8.4.1", + "ora": "5.4.1", + "pacote": "15.1.0", + "resolve": "1.22.1", + "semver": "7.3.8", + "symbol-observable": "4.0.0", + "yargs": "17.6.2" + }, + "bin": { + "ng": "bin/ng.js" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { + "version": "0.1502.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1502.4.tgz", + "integrity": "sha512-bDBcaRMBfXFfK9MpvfNO926F1rL0PEw+mveXxq3/SSql+1XP/hrc5TVGwnoim4g6DqsGmu9upS5DyJ6PnL/hHA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "15.2.4", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.4.tgz", + "integrity": "sha512-yl+0j1bMwJLKShsyCXw77tbJG8Sd21+itisPLL2MgEpLNAO252kr9zG4TLlFRJyKVftm2l1h78KjqvM5nbOXNg==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "6.6.7", + "source-map": "0.7.4" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular/cli/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular/common": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-15.2.8.tgz", + "integrity": "sha512-yLDQihiRcVl38HrWMPbqgzOaSUw85AQH5BsGdjbS6BpoBQj3EXOpccCMFsuxOKxPG4toatgawNqrEnK0Jpv9Mw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "15.2.8", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-15.2.8.tgz", + "integrity": "sha512-+dvspIDvuGoYqdL7r/3o9ojkR3fH1zevgC0ISJivcIrMi+WcJ0FV2JmJdnm8V52oNsHy+sMF9eEZGEbCbACE/A==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "15.2.8" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/compiler-cli": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-15.2.8.tgz", + "integrity": "sha512-fFxaDlbILo0t2t662qA0cjgn+kWItGlc1tFYKU6X7bvYb3t2e0cd9FzrFPLXUQVboGis83ULcJ2zkDxScnuPuQ==", + "dev": true, + "dependencies": { + "@babel/core": "7.19.3", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.11.0", + "magic-string": "^0.27.0", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/main-ngcc.js" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/compiler": "15.2.8", + "typescript": ">=4.8.2 <5.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/compiler-cli/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular/core": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-15.2.8.tgz", + "integrity": "sha512-NDs+g4uM4EhyCvluf8a0YBCFXsDAEfCMHOD5cS00Bl+liTQ7JwtmepkWXMyjLB92irC9JaR79kdy4BoIKOh8WA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.11.4 || ~0.12.0 || ~0.13.0" + } + }, + "node_modules/@angular/forms": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-15.2.8.tgz", + "integrity": "sha512-VyevVj20DdQWjAQUyiFTe+DAzqG9GqfAOWn376Y/lhPcwxAojXePTGNgtQud566/urDrNrP5haaLD6O36/3n+w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "15.2.8", + "@angular/core": "15.2.8", + "@angular/platform-browser": "15.2.8", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/platform-browser": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.8.tgz", + "integrity": "sha512-8sKFUld54inj0FnQ1ydhFxnDgsbbf43W9FALye/5uEtLgwwE/ZvkNYMaQ7hq1JPuQRMDj3gJkFqaLeFjplpHDA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/animations": "15.2.8", + "@angular/common": "15.2.8", + "@angular/core": "15.2.8" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.8.tgz", + "integrity": "sha512-75HyoZNibA3u/FvdK4Aw5KMzUmS/nDk5N8s7gfM09fe1resSPgFiW8JJEkr1xiUdA2WtSRbHs34y5rHLDe7n1Q==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "15.2.8", + "@angular/compiler": "15.2.8", + "@angular/core": "15.2.8", + "@angular/platform-browser": "15.2.8" + } + }, + "node_modules/@angular/router": { + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-15.2.8.tgz", + "integrity": "sha512-C62QBEeJSBTNTrQHZiklPrxwJwuENoZzWX22MMJ7dxl+7VjRgnmj8J7mcX9fLjHlL+mC3RvesMlX7sGZRQV1cg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "15.2.8", + "@angular/core": "15.2.8", + "@angular/platform-browser": "15.2.8", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "node_modules/@babel/code-frame": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", + "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.12", + "@babel/types": "^7.20.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.20.14", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", + "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz", + "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.4.tgz", + "integrity": "sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", + "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", + "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", + "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", + "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", + "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", + "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", + "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", + "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", + "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", + "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", + "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", + "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", + "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", + "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", + "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", + "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-simple-access": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", + "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-identifier": "^7.19.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", + "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.19.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz", + "integrity": "sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.19.0", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", + "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.20.2", + "@babel/plugin-transform-classes": "^7.20.2", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.19.6", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.4", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz", + "integrity": "sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz", + "integrity": "sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz", + "integrity": "sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz", + "integrity": "sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz", + "integrity": "sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz", + "integrity": "sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz", + "integrity": "sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz", + "integrity": "sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz", + "integrity": "sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz", + "integrity": "sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz", + "integrity": "sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz", + "integrity": "sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz", + "integrity": "sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz", + "integrity": "sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz", + "integrity": "sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz", + "integrity": "sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz", + "integrity": "sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz", + "integrity": "sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz", + "integrity": "sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz", + "integrity": "sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz", + "integrity": "sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz", + "integrity": "sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@igniteui/angular-schematics": { + "version": "15.0.1103", + "resolved": "https://registry.npmjs.org/@igniteui/angular-schematics/-/angular-schematics-15.0.1103.tgz", + "integrity": "sha512-ndxyGRRzOWUn03D+fCcVmNOyMfZ3ag6epc8Y66SiIA/5G02Cp5YPW8nIHxdJXjpRLi7wlR36GIVFTGXk01QqxA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@angular-devkit/core": "~14.0.0", + "@angular-devkit/schematics": "~14.0.0", + "@igniteui/angular-templates": "~15.0.1103", + "@igniteui/cli-core": "~11.0.3", + "@schematics/angular": "~14.0.0", + "rxjs": "^6.6.3" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/@angular-devkit/core": { + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", + "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", + "dev": true, + "dependencies": { + "ajv": "8.11.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.0.0", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/@angular-devkit/schematics": { + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-14.0.7.tgz", + "integrity": "sha512-nJUJXCBQr7rmVn6IXFAXMCWAB1w6JQmFGuFVW0G3GH/A0e+A3ttzJc6qVLYluqaFoafw394cZu24YJo55E/+Zg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "14.0.7", + "jsonc-parser": "3.0.0", + "magic-string": "0.26.1", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/@schematics/angular": { + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-14.0.7.tgz", + "integrity": "sha512-I0v1gNFpm9ReL/hUzwjjOa+hk0qvlXv/vjITAWnlUV5dba6FZxzwsrTGsGO6t5XMNsm6QtwpDYDRdy9uy/n/1g==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "14.0.7", + "@angular-devkit/schematics": "14.0.7", + "jsonc-parser": "3.0.0" + }, + "engines": { + "node": "^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "node_modules/@igniteui/angular-schematics/node_modules/magic-string": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz", + "integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@igniteui/angular-schematics/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@igniteui/angular-templates": { + "version": "15.0.1103", + "resolved": "https://registry.npmjs.org/@igniteui/angular-templates/-/angular-templates-15.0.1103.tgz", + "integrity": "sha512-iHQM5vLxUThfF0NJpaC0d3/wvZIAsGaYI/4in/IjJTZw3C0aqiD+yxYrPKvMFTelbZkw+VnYo6BRdY7KI0fTvA==", + "dev": true, + "dependencies": { + "@igniteui/cli-core": "~11.0.3", + "typescript": "~4.7.2" + } + }, + "node_modules/@igniteui/angular-templates/node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@igniteui/cli-core": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@igniteui/cli-core/-/cli-core-11.0.3.tgz", + "integrity": "sha512-FTo9XkxebFVIca5yghOCNk9z6Ivr/4pTgQFfQL/56upgtCn/wiYkmkFOsKQsso8f7AV4biOfoS4liH0ZSIsoqA==", + "dev": true, + "dependencies": { + "chalk": "^2.3.2", + "glob": "^7.1.2", + "inquirer": "^6.2.2", + "through2": "^2.0.3", + "typescript": "~4.5.2" + } + }, + "node_modules/@igniteui/cli-core/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@igniteui/cli-core/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dev": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "node_modules/@igniteui/cli-core/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@igniteui/cli-core/node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@igniteui/cli-core/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==", + "dev": true + }, + "node_modules/@igniteui/cli-core/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dev": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@igniteui/cli-core/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@igniteui/cli-core/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@igniteui/cli-core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@igniteui/cli-core/node_modules/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@igniteui/material-icons-extended": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@igniteui/material-icons-extended/-/material-icons-extended-2.11.0.tgz", + "integrity": "sha512-lhNBCsFqYWowhrfuhqFx/gfX8G6hGOLNSaDZju7OaDuGyIc9Nsu8/qmZrkoVe1IVKet3Hr09k92Vq4zo3iSxHA==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", + "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, + "node_modules/@ngtools/webpack": { + "version": "15.2.6", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.6.tgz", + "integrity": "sha512-I+kekKItfsCLdX+ZjjmsWqd0AyoYGTQPjlbQAiPtmdH73/rfPOF4Q/3AU4tzTdn0n0GXqZWv6VOs91w99ydi0A==", + "dev": true, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^15.0.0", + "typescript": ">=4.8.2 <5.0", + "webpack": "^5.54.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.0.4.tgz", + "integrity": "sha512-5yZghx+u5M47LghaybLCkdSyFzV/w4OuH12d96HO389Ik9CDsLaDZJVynSGGVJOLn6gy/k7Dz5XYcplM3uxXRg==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.0.tgz", + "integrity": "sha512-ql+AbRur1TeOdl1FY+RAwGW9fcr4ZwiVKabdvm93mujGREVuVLbdkXRJDrkTXSdCjaxYydr1wlA2v67jxWG5BQ==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@schematics/angular": { + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-15.2.4.tgz", + "integrity": "sha512-P9axwKDXEDrGXYcoCuhwv4guhvtIjDCvyZMsQw8IMpfAacTYajka+T3mZrzyTe96Uhu0JwcAW5iUlOZAJhPEdQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "15.2.4", + "@angular-devkit/schematics": "15.2.4", + "jsonc-parser": "3.2.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.4.tgz", + "integrity": "sha512-yl+0j1bMwJLKShsyCXw77tbJG8Sd21+itisPLL2MgEpLNAO252kr9zG4TLlFRJyKVftm2l1h78KjqvM5nbOXNg==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "6.6.7", + "source-map": "0.7.4" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@schematics/angular/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", + "integrity": "sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.3.tgz", + "integrity": "sha512-mkFEqqRisi13DmR5pX4x+Zk97EiU8djTtpNW1GeuX410y/raAsq/T3ZCjwoRIZ8/cIBfW0olK/sywlAiWevDVw==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^7.4.6" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.33", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", + "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/hammerjs": { + "version": "2.0.41", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz", + "integrity": "sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.10", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.10.tgz", + "integrity": "sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.1.tgz", + "integrity": "sha512-Vu8l+UGcshYmV1VWwULgnV/2RDbBaO6i2Ptx7nd//oJPIZGhoI1YLST4VKagD2Pq/Bc2/7zvtvhM7F3p4SN7kQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "dev": true, + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", + "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/type-utils": "5.59.0", + "@typescript-eslint/utils": "5.59.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", + "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/utils": "5.59.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", + "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", + "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.2.tgz", + "integrity": "sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.48.2", + "@typescript-eslint/utils": "5.48.2", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", + "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.2.tgz", + "integrity": "sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", + "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", + "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.13", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", + "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-lite": "^1.0.30001426", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-loader": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.2.tgz", + "integrity": "sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.2", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", + "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", + "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", + "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz", + "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^8.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001481", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", + "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz", + "integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/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==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", + "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.1.tgz", + "integrity": "sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.1.tgz", + "integrity": "sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/critters": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.16.tgz", + "integrity": "sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^4.2.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "postcss": "^8.3.7", + "pretty-bytes": "^5.3.0" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/critters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/critters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/critters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", + "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.19", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "dev": true + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, + "node_modules/dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.368", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.368.tgz", + "integrity": "sha512-e2aeCAixCj9M7nJxdB/wDjO6mbYX+lJJxSJCXDzlr5YPGYVofuJwGN9nKg2o6wWInjX6XmxRinn3AeJMK81ltw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/engine.io": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz", + "integrity": "sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", + "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "dev": true + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz", + "integrity": "sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.8", + "@esbuild/android-arm64": "0.17.8", + "@esbuild/android-x64": "0.17.8", + "@esbuild/darwin-arm64": "0.17.8", + "@esbuild/darwin-x64": "0.17.8", + "@esbuild/freebsd-arm64": "0.17.8", + "@esbuild/freebsd-x64": "0.17.8", + "@esbuild/linux-arm": "0.17.8", + "@esbuild/linux-arm64": "0.17.8", + "@esbuild/linux-ia32": "0.17.8", + "@esbuild/linux-loong64": "0.17.8", + "@esbuild/linux-mips64el": "0.17.8", + "@esbuild/linux-ppc64": "0.17.8", + "@esbuild/linux-riscv64": "0.17.8", + "@esbuild/linux-s390x": "0.17.8", + "@esbuild/linux-x64": "0.17.8", + "@esbuild/netbsd-x64": "0.17.8", + "@esbuild/openbsd-x64": "0.17.8", + "@esbuild/sunos-x64": "0.17.8", + "@esbuild/win32-arm64": "0.17.8", + "@esbuild/win32-ia32": "0.17.8", + "@esbuild/win32-x64": "0.17.8" + } + }, + "node_modules/esbuild-wasm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.17.8.tgz", + "integrity": "sha512-zCmpxv95E0FuCmvdw1K836UHnj4EdiQnFfjTby35y3LAjRPtXMj3sbHDRHjbD8Mqg5lTwq3knacr/1qIFU51CQ==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fflate": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", + "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.1.tgz", + "integrity": "sha512-MhaJDcFRTuLidHrIttu0RDGyyXs/IYHVmlcxfLAEFIWjc1vdLAkdwT7Ace2u7DbitWC0toKMl5eJZRYNVreIMw==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "dependencies": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "node_modules/hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/igniteui-angular": { + "version": "15.1.3", + "resolved": "https://registry.npmjs.org/igniteui-angular/-/igniteui-angular-15.1.3.tgz", + "integrity": "sha512-I4qL+EJLiVuGETENj6+TXp1PTj1svSYvfnpMaOZMEw9CxXPUjTPw+g/MahXT66yMv+l7xSLVwCifvfcZI0QZRA==", + "dependencies": { + "@igniteui/material-icons-extended": "^2.10.0", + "@types/hammerjs": "^2.0.40", + "fflate": "^0.7.3", + "hammerjs": "^2.0.8", + "igniteui-theming": "^1.4.1", + "igniteui-trial-watermark": "^1.0.3", + "lodash-es": "^4.17.21", + "tslib": "^2.3.0", + "uuid": "^8.3.0" + }, + "peerDependencies": { + "@angular/animations": "^15.0.0", + "@angular/common": "^15.0.0", + "@angular/core": "^15.0.0", + "@angular/forms": "^15.0.0" + } + }, + "node_modules/igniteui-angular-charts": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/igniteui-angular-charts/-/igniteui-angular-charts-15.0.1.tgz", + "integrity": "sha512-FaE5sG6yZxQMnRzXlWSt1TQURD6NrGhAgYAVaFx9nYzp0OZbSJTY907IkwQ8EW5RbLVii50IgChKc3/Lnw0/rQ==", + "dependencies": { + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@angular/common": "^15.0.0", + "@angular/compiler": "^15.0.0", + "@angular/core": "^15.0.0", + "igniteui-angular-core": "15.0.1" + } + }, + "node_modules/igniteui-angular-core": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/igniteui-angular-core/-/igniteui-angular-core-15.0.1.tgz", + "integrity": "sha512-s0KogwZYeV2XUGsr2hvrVIoxsHEXrw0w4s8uB8tZOOt355XsywXbf2yqYvbx5cJOGSi64SywUz7UswT57UB0Mg==", + "dependencies": { + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@angular/common": "^15.0.0", + "@angular/compiler": "^15.0.0", + "@angular/core": "^15.0.0" + } + }, + "node_modules/igniteui-theming": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-1.4.2.tgz", + "integrity": "sha512-XuKQFLl4aoRj74fXRVWfznLyVrRfAHb0pft4NyCAF+x58+5C0SXlOz8asbjtPEMw6jAPK4P3tq4mWtjHJrTCww==", + "peerDependencies": { + "sass": "^1.53.0" + } + }, + "node_modules/igniteui-trial-watermark": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/igniteui-trial-watermark/-/igniteui-trial-watermark-1.0.3.tgz", + "integrity": "sha512-q6thtu+7R6MOB+i9GorFPCcWeOImW43BzCAtKnDAYWwaoueb8Lg1EhBkIhAyfEIH+yZ/9c5lnZdU61/GRPoP+g==" + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.2.tgz", + "integrity": "sha512-ezmQ1Dg2b3jVZh2Dh+ar6Eu2MqNSTkyb32HU2MAQQQX9tKM3q/UQ/9lf03lQ5hW+fOeoMnwxwkleZ0xcNp0/qg==", + "dev": true, + "dependencies": { + "minimatch": "^7.4.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", + "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jasmine-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", + "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", + "dev": true + }, + "node_modules/jasmine-spec-reporter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-7.0.0.tgz", + "integrity": "sha512-OtC7JRasiTcjsaCBPtMO0Tl8glCejM4J4/dNuOJdA8lBjz4PmWjYQ6pzb0uzpBNAWJMDudYuj9OdXJWqM2QTJg==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/karma": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", + "integrity": "sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", + "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-chrome-launcher/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/karma-coverage": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.0.tgz", + "integrity": "sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.0.5", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "dev": true, + "dependencies": { + "jasmine-core": "^4.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "karma": "^6.0.0" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.0.0.tgz", + "integrity": "sha512-SB8HNNiazAHXM1vGEzf8/tSyEhkfxuDdhYdPBX2Mwgzt0OuF2gicApQ+uvXLID/gXyJQgvrM9+1/2SxZFUUDIA==", + "dev": true, + "peerDependencies": { + "jasmine-core": "^4.0.0", + "karma": "^6.0.0", + "karma-jasmine": "^5.0.0" + } + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/karma/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "dependencies": { + "klona": "^2.0.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/less/node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", + "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/material-icons": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/material-icons/-/material-icons-1.13.1.tgz", + "integrity": "sha512-6EwhlEa4rwydNSWw11ig1oz/h/KcarJXn4n50Wd69v5Eh026Y6xBo9zLPeX4iF8+qUZV862X0AUUA0m0VaihWg==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.1.tgz", + "integrity": "sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", + "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minireset.css": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/minireset.css/-/minireset.css-0.0.7.tgz", + "integrity": "sha512-raWKK2aHP/MI4Yu72dU6hade1YFuoyDQtSUi/FiIZfeRHjgL81uN/nFvG2aoAr+mseRc3jpg47jQqx1/+6w+kQ==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/needle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/needle/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "dev": true, + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.1.1.tgz", + "integrity": "sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz", + "integrity": "sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "dependencies": { + "ignore-walk": "^6.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.4.tgz", + "integrity": "sha512-pMS2DRkwg+M44ct65zrN/Cr9IHK1+n6weuefAo6Er4lc+/8YBCU0Czq04H3ZiSigluh7pb2rMM5JpgcytctB+Q==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^11.0.0", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.0.tgz", + "integrity": "sha512-7ChuOzCb1LzdQZrTy0ky6RsCoMYeM+Fh4cY0+4zsJVhNcH5Q3OJojLY1mGkD0xAhWB29lskECVb6ZopofwjldA==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.2.tgz", + "integrity": "sha512-/ZpF1CQaWYqjbhfFgKNt3azxztEpc/JUPuMkqOgrnMQqcU8CbE409AUdJYTIWryl3PP5CBaTJZT71N49MXP/YA==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.1.tgz", + "integrity": "sha512-/4b7qZNhv6Uhd7jjnREh1NjnPxlTq+XNWPG88Ydkj5AILcA5m3ajvcg57pB24EQjKv0dK62XnDqk9c/hkIG5Kg==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.1.0.tgz", + "integrity": "sha512-FFcjtIl+BQNfeliSm7MZz5cpdohvUV1yjGnqgVM4UnVF7JslRY0ImXAygdaCDV0jjUADEWu4y5xsDV8brtrTLg==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^4.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dev": true, + "dependencies": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-sax-parser/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", + "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "dev": true, + "dependencies": { + "lru-cache": "^9.0.0", + "minipass": "^5.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.0.tgz", + "integrity": "sha512-qFXQEwchrZcMVen2uIDceR8Tii6kCJak5rzDStfEM0qA3YLMswaxIEZO0DhIbJ3aqaJiDjt+3crlplOb0tDtKQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/piscina": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-3.2.0.tgz", + "integrity": "sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA==", + "dev": true, + "dependencies": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0" + }, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-loader": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.0.2.tgz", + "integrity": "sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/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==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-package-json": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.1.tgz", + "integrity": "sha512-AaHqXxfAVa+fNL07x8iAghfKOds/XXsu7zoouIVsbm7PEbQ3nMWXlvjcbrNLjElnUHWQtAo4QEa0RXuvD4XlpA==", + "dev": true, + "dependencies": { + "glob": "^9.3.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/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==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sass": { + "version": "1.58.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.1.tgz", + "integrity": "sha512-bnINi6nPXbP1XNRaranMFEBZWUfdW/AF16Ql5+ypRxfTvCRTTKrLsMIakyDcayUt2t/RZotmL4kgJwNH5xO+bg==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz", + "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "optional": true + }, + "node_modules/schema-utils": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", + "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sigstore": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.3.2.tgz", + "integrity": "sha512-0KT1DjpVB11FK15ep7BIsZQV6j1jBm4SnXIInbBCRvql6II39IKONOMO+j036sGsArU/+2xqa1NDJwJkic0neA==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.1.0", + "make-fetch-happen": "^11.0.1", + "tuf-js": "^1.1.3" + }, + "bin": { + "sigstore": "bin/sigstore.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.0.tgz", + "integrity": "sha512-7ChuOzCb1LzdQZrTy0ky6RsCoMYeM+Fh4cY0+4zsJVhNcH5Q3OJojLY1mGkD0xAhWB29lskECVb6ZopofwjldA==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/minipass-fetch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.2.tgz", + "integrity": "sha512-/ZpF1CQaWYqjbhfFgKNt3azxztEpc/JUPuMkqOgrnMQqcU8CbE409AUdJYTIWryl3PP5CBaTJZT71N49MXP/YA==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.3.tgz", + "integrity": "sha512-lJtX/BFPI/VEtxZmLfeh7pzisIs6micwZ3eruD3+ds9aPsXKlYpwDS2Q7omD6WC42WO9+bnUSzlMmfv8uK8meg==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/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==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/super-rpc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/super-rpc/-/super-rpc-1.0.1.tgz", + "integrity": "sha512-CQTEJh+FLnCJF8PMeoaa3U8M6y+vrSaw0SjpYRoFIhIe6y24dXP+GZbKzrzx6CfYxCRfR/pLeP65GHc+NsF+ww==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/terser": { + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", + "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", + "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", + "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/throttle-typescript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/throttle-typescript/-/throttle-typescript-1.1.0.tgz", + "integrity": "sha512-pxQ+jaKIZZBkRJxbc+CoH3ubz59zgfd8qr0GqHb5NiAIhwHp5SWCHdVnujv/t87EcnFw7BbNrzyLWxNJ1+K6Mg==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tuf-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.4.tgz", + "integrity": "sha512-Lw2JRM3HTYhEtQJM2Th3aNCPbnXirtWMl065BawwmM2pX6XStH/ZO9e8T2hh0zk/HUa+1i6j+Lv6eDitKTau6A==", + "dev": true, + "dependencies": { + "@tufjs/models": "1.0.3", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.0.tgz", + "integrity": "sha512-7ChuOzCb1LzdQZrTy0ky6RsCoMYeM+Fh4cY0+4zsJVhNcH5Q3OJojLY1mGkD0xAhWB29lskECVb6ZopofwjldA==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/minipass-fetch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.2.tgz", + "integrity": "sha512-/ZpF1CQaWYqjbhfFgKNt3azxztEpc/JUPuMkqOgrnMQqcU8CbE409AUdJYTIWryl3PP5CBaTJZT71N49MXP/YA==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", + "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-animations-js": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.2.tgz", + "integrity": "sha512-TOMFWtQdxzjWp8qx4DAraTWTsdhxVSiWa6NkPFSaPtZ1diKUxTn4yTix73A1euG1WbSOMMPcY51cnjTIHrGtDA==" + }, + "node_modules/webpack": { + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.0.1.tgz", + "integrity": "sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz", + "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.1", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", + "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", + "dev": true, + "dependencies": { + "typed-assert": "^1.0.8" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", + "webpack": "^5.12.0" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", + "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/zone.js": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.0.tgz", + "integrity": "sha512-7m3hNNyswsdoDobCkYNAy5WiUulkMd3+fWaGT9ij6iq3Zr/IwJo4RMCYPSDjT+r7tnPErmY9sZpKhWQ8S5k6XQ==", + "dependencies": { + "tslib": "^2.3.0" + } + } + } +} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/package.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/package.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/package.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/package.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ConnectionInfo.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ConnectionInfo.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ConnectionInfo.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ConnectionInfo.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/IProcessInfoAggregator.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/IProcessInfoAggregator.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/IProcessInfoAggregator.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/IProcessInfoAggregator.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ISubsystemController.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ISubsystemController.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ISubsystemController.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ISubsystemController.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ModuleInfo.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ModuleInfo.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ModuleInfo.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ModuleInfo.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ProcessInfo.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ProcessInfo.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ProcessInfo.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ProcessInfo.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ProcessInfoCollectorData.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ProcessInfoCollectorData.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/ProcessInfoCollectorData.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/ProcessInfoCollectorData.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/RegistrationInfo.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/RegistrationInfo.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/RegistrationInfo.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/RegistrationInfo.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/SubsystemInfo.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/SubsystemInfo.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/SubsystemInfo.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/SubsystemInfo.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/SubsystemState.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/SubsystemState.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/DTOs/SubsystemState.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/DTOs/SubsystemState.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app-routing.module.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app-routing.module.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app-routing.module.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app-routing.module.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.component.html b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.component.html similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.component.html rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.component.html diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.component.scss b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.component.scss similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.component.scss rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.component.scss diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.module.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.module.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/app.module.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/app.module.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/error-routing.module.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/error-routing.module.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/error-routing.module.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/error-routing.module.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/error/global-error-handler.service.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/error/global-error-handler.service.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/error/global-error-handler.service.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/error/global-error-handler.service.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/error/uncaught-error.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/error/uncaught-error.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/error/uncaught-error.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/error/uncaught-error.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/not-found/not-found.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/not-found/not-found.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/error-routing/not-found/not-found.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/error-routing/not-found/not-found.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.html b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.html similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.html rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.html diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.scss b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.scss similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.scss rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.scss diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/connections/connections.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/connections/connections.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view-routing.module.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view-routing.module.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view-routing.module.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view-routing.module.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.html b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.html similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.html rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.html diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.scss b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.scss similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.scss rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.scss diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.module.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.module.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/main-view.module.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/main-view.module.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/ServiceProcessObject.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/ServiceProcessObject.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/ServiceProcessObject.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/ServiceProcessObject.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.html b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.html similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.html rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.html diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.scss b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.scss similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.scss rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.scss diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/processes/processes.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/processes/processes.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/ServiceSubsystemObject.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/ServiceSubsystemObject.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/ServiceSubsystemObject.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/ServiceSubsystemObject.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.html b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.html similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.html rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.html diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.scss b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.scss similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.scss rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.scss diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/main-view/subsystems/subsystem.component.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/main-view/subsystems/subsystem.component.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-connections.service.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-connections.service.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-connections.service.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-connections.service.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-connections.service.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-connections.service.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-connections.service.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-connections.service.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-connections.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-connections.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-connections.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-connections.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-processes.service.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-processes.service.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-processes.service.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-processes.service.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-processes.service.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-processes.service.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-processes.service.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-processes.service.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-subsystems.service.spec.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-subsystems.service.spec.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-subsystems.service.spec.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-subsystems.service.spec.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-subsystems.service.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-subsystems.service.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/app/services/mock-subsystems.service.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/app/services/mock-subsystems.service.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/environments/environment.prod.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/environments/environment.prod.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/environments/environment.prod.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/environments/environment.prod.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/environments/environment.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/environments/environment.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/environments/environment.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/environments/environment.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/favicon.ico b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/favicon.ico similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/favicon.ico rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/favicon.ico diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/index.html b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/index.html similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/index.html rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/index.html diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/main.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/main.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/main.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/main.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/polyfills.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/polyfills.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/polyfills.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/polyfills.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/styles.scss b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/styles.scss similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/styles.scss rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/styles.scss diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/src/test.ts b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/test.ts similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/src/test.ts rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/src/test.ts diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig-es5.app.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig-es5.app.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig-es5.app.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig-es5.app.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig.app.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig.app.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig.app.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig.app.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig.spec.json b/Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig.spec.json similarity index 100% rename from Tryouts/Plugins/ApplicationPlugins/process explorer/tsconfig.spec.json rename to Tryouts/Plugins/ApplicationPlugins/MorganStanley.ComposeUI.ProcessExplorer/js/tsconfig.spec.json diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/ProcessInfoCollector.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/ProcessInfoCollector.cs deleted file mode 100644 index cf7d94aa0..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/LocalCollector/ProcessInfoCollector.cs +++ /dev/null @@ -1,297 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Diagnostics; -using LocalCollector.Communicator; -using LocalCollector.Connections; -using LocalCollector.EnvironmentVariables; -using LocalCollector.Logging; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -namespace LocalCollector; - -public class ProcessInfoCollector : IProcessInfoCollector -{ - public ProcessInfoCollectorData Data { get; } = new(); - private ICommunicator? _communicator; - private readonly ILogger _logger; - private readonly AssemblyInformation _assemblyID = new(); - private readonly object _locker = new(); - - ProcessInfoCollector(ICommunicator? channel = null, ILogger? logger = null, - string? assemblyId = null, int? pid = null) - { - this._communicator = channel; - this._logger = logger ?? NullLogger.Instance; - - if (assemblyId != null) - { - this._assemblyID.Name = assemblyId; - } - - if (pid != null) - { - Data.Id = Convert.ToInt32(pid); - } - } - - public ProcessInfoCollector(EnvironmentMonitorInfo envs, IConnectionMonitor cons, ICommunicator? channel = null, - ILogger? logger = null, string? assemblyId = null, int? pid = null) - : this(channel, logger, assemblyId, pid) - { - Data.Id = Process.GetCurrentProcess().Id; - Data.EnvironmentVariables = envs.EnvironmentVariables; - Data.Connections = cons.Data.Connections; - - SetConnectionChangedEvent(cons); - } - - public ProcessInfoCollector(EnvironmentMonitorInfo envs, IConnectionMonitor cons, - RegistrationMonitorInfo registrations, ModuleMonitorInfo modules, ICommunicator? channel = null, - ILogger? logger = null, string? assemblyId = null, int? pid = null) - : this(envs, cons, channel, logger, assemblyId, pid) - { - Data.Registrations = registrations.Services; - Data.Modules = modules.CurrentModules; - } - - public ProcessInfoCollector(IConnectionMonitor cons, ICollection regs, - ICommunicator? channel = null, ILogger? logger = null, string? assemblyId = null, - int? pid = null) - : this(EnvironmentMonitorInfo.FromEnvironment(), cons, RegistrationMonitorInfo.FromCollection(regs), - ModuleMonitorInfo.FromAssembly(), channel, logger, assemblyId, pid) - { - } - - public ProcessInfoCollector(IConnectionMonitor cons, IServiceCollection regs, ICommunicator? channel = null, - ILogger? logger = null, string? assemblyId = null, int? pid = null) - : this(EnvironmentMonitorInfo.FromEnvironment(), cons, RegistrationMonitorInfo.FromCollection(regs), - ModuleMonitorInfo.FromAssembly(), channel, logger, assemblyId, pid) - { - } - - public ProcessInfoCollector(IConnectionMonitor cons, RegistrationMonitorInfo regs, ICommunicator? channel = null, - ILogger? logger = null, string? assemblyId = null, int? pid = null) - : this(EnvironmentMonitorInfo.FromEnvironment(), cons, regs, ModuleMonitorInfo.FromAssembly(), channel, - logger, assemblyId, pid) - { - } - - - private void SetConnectionChangedEvent(IConnectionMonitor connectionMonitor) - { - connectionMonitor._connectionStatusChanged += ConnectionStatusChangedHandler; - } - - public void SetCommunicator(ICommunicator communicator) - { - this._communicator = communicator; - var runtimeInfo = new List>() - { - new KeyValuePair(_assemblyID, Data) - }; - - _communicator.AddRuntimeInfo(runtimeInfo); - } - - - private void ConnectionStatusChangedHandler(object? sender, ConnectionInfo connection) - { - if (_communicator == null) - { - return; - } - - try - { - lock (_locker) - { - var info = Data.Connections.FirstOrDefault(p => p.Id == connection.Id); - if (info != null) - { - var index = Data.Connections.IndexOf(info); - if (index >= 0 && Data.Connections.Count <= index) - { - Data.Connections[Convert.ToInt32(index)] = connection; - } - } - } - } - catch (Exception exception) - { - _logger.ConnectionStatusChangedError(exception); - } - - var connections = new List>() - { - new(_assemblyID, connection) - }; - - _communicator.UpdateConnectionInformation(connections) - .ConfigureAwait(true); - } - - public async Task SendRuntimeInfo() - { - if (_communicator != null) - { - var runtimeInfo = new List>() - { - new(_assemblyID, Data) - }; - - await _communicator.AddRuntimeInfo(runtimeInfo); - } - } - - public async Task AddConnectionMonitor(ConnectionMonitorInfo connections) - { - if(_communicator != null) - await AddOrUpdateElements( - connections.Connections, - Data.Connections, - (item) => (conn) => conn.Id == item.Id, - _communicator.AddConnectionCollection); - } - - - public async Task AddConnectionMonitor(IConnectionMonitor connections) - { - await AddConnectionMonitor(connections.Data); - } - - - public async Task AddEnvironmentVariables(EnvironmentMonitorInfo environmentVariables) - { - if (Data.EnvironmentVariables.IsEmpty) - { - lock (_locker) - { - Data.EnvironmentVariables = environmentVariables.EnvironmentVariables; - } - } - else - { - foreach (var env in environmentVariables.EnvironmentVariables) - { - lock (_locker) - { - Data.EnvironmentVariables.AddOrUpdate(env.Key, env.Value, (_, _) => env.Value); - } - } - - } - - if (_communicator != null) - { - var info = new List>>>() - { - new(_assemblyID, environmentVariables.EnvironmentVariables) - }; - - await _communicator.UpdateEnvironmentVariableInformation(info); - } - } - - private async Task AddOrUpdateElements( - SynchronizedCollection source, - SynchronizedCollection target, - Func> predicate, - Func>>, ValueTask> handler) - { - if (!target.Any()) - { - lock (_locker) - { - target = source; - } - } - else - { - foreach (var item in source) - { - lock (_locker) - { - var element = target.FirstOrDefault(predicate(item)); - if (element == null) - { - continue; - } - - var index = target.IndexOf(element); - if(index != -1) - { - target[index] = item; - } - else - { - target.Add(item); - } - } - } - } - - if(_communicator != null) - { - var info = new List>>() - { - new(_assemblyID, source) - }; - - await handler(info); - } - } - - public async Task AddRegistrations(RegistrationMonitorInfo registrations) - { - if (_communicator != null) - await AddOrUpdateElements( - registrations.Services, - Data.Registrations, - (item) => (reg) => reg.LifeTime == item.LifeTime && reg.ImplementationType == item.ImplementationType && reg.LifeTime == item.LifeTime, - _communicator.UpdateRegistrationInformation); - } - - public async Task AddModules(ModuleMonitorInfo modules) - { - if (_communicator != null) - await AddOrUpdateElements( - modules.CurrentModules, - Data.Modules, - (item) => (mod) => mod.Name == item.Name && mod.PublicKeyToken == item.PublicKeyToken && mod.Version == item.Version, - _communicator.UpdateModuleInformation); - } - - public async Task AddRuntimeInformation(IConnectionMonitor connections, - EnvironmentMonitorInfo environmentVariables, - RegistrationMonitorInfo registrations, ModuleMonitorInfo modules) - { - await AddConnectionMonitor(connections); - await AddEnvironmentVariables(environmentVariables); - await AddRegistrations(registrations); - await AddModules(modules); - } - - public void SetAssemblyId(string assemblyId) - { - this._assemblyID.Name = assemblyId; - } - - public void SetClientPid(int clientPid) - { - Data.Id = clientPid; - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Logging/SourceGeneratedLoggerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Logging/SourceGeneratedLoggerExtensions.cs deleted file mode 100644 index f57ff81ac..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Logging/SourceGeneratedLoggerExtensions.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using Microsoft.Extensions.Logging; - -namespace ModuleProcessMonitor.Logging; - -internal static partial class SourceGeneratedLoggerExtensions -{ - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "The Process Explorer list is initialized", SkipEnabledCheck = false)] - public static partial void ProcessListIsInitializedDebug(this ILogger logger); - - [LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "A process with PID: `{pid}` is terminated", SkipEnabledCheck = false)] - public static partial void ProcessTerminatedInformation(this ILogger logger, int pid); - - [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "A process with PID: `{pid}` is created", SkipEnabledCheck = false)] - public static partial void ProcessCreatedInformation(this ILogger logger, int pid); - - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "A process with PID: `{pid}` is modified", SkipEnabledCheck = false)] - public static partial void ProcessModifiedDebug(this ILogger logger, int pid); - - [LoggerMessage(EventId = 3, Level = LogLevel.Warning, Message = "The process `{pid}` does not exist in the ProcessMonitor list", SkipEnabledCheck = false)] - public static partial void ProcessNotFoundWarning(this ILogger logger, int pid); - - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "Couldn't find the PPID for the PID `{pid}`. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ManagementObjectPpid(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Couldn't read the child process. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ManagementObjectChild(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot find the process. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotFindProcess(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "Couldn't read the event of the process. Probably the event is not set for this WMI handler or the ProcessMonitor is disabled. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ManagementObjectWatchEvent(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot find an element with PID `{pid}` in the current process list. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotFindElement(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot stop process watcher. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotStopProcessWatcher(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot find an element with PID `{pid}` or the communicator has been not set properly. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CouldNotFoundModifiableProcess(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Nor PID does not exists: `{pid}` or the process list does not exists. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void PidNotExists(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Index does not exists for the PID: `{pid}` or the process list does not exists. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void IndexDoesNotExists(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot terminate process or the process does not exists in the current context. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotKillProcess(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Error while initializing list. The main process might be deleted. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotFillList(this ILogger logger, Exception ex, Exception exception); - - public static void ManagementObjectPpidExpected(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Debug)) - { - logger.ManagementObjectPpid(pid, exception, exception); - } - } - - public static void InstanceEventExpected(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Debug)) - { - logger.ManagementObjectWatchEvent(exception, exception); - } - } - - public static void ChildProcessExpected(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.ManagementObjectChild(exception, exception); - } - } - - public static void ProcessExpected(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotFindProcess(exception, exception); - } - } - - public static void WatcherInitializationError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.ManagementObjectChild(exception, exception); - } - } - - public static void PpidExpected(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotFindElement(pid, exception, exception); - } - } - - public static void StoppingWatcherExpected(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotStopProcessWatcher(exception, exception); - } - } - - public static void ModifiableProcessExpected(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CouldNotFoundModifiableProcess(pid, exception, exception); - } - } - - public static void PidExpected(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.PidNotExists(pid, exception, exception); - } - } - - public static void PidIndexExpected(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.IndexDoesNotExists(pid, exception, exception); - } - } - - public static void KillProcessError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotKillProcess(exception, exception); - } - } - - public static void ListInitializationError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotFillList(exception, exception); - } - } -} - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ModuleProcessMonitor.csproj b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ModuleProcessMonitor.csproj deleted file mode 100644 index dac7b5f28..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ModuleProcessMonitor.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - - - - - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ProcessMonitorFactory.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ProcessMonitorFactory.cs deleted file mode 100644 index 3ae85cf82..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/ProcessMonitorFactory.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using Microsoft.Extensions.Logging; -using ModuleProcessMonitor.Processes; - -namespace ModuleProcessMonitor; -public static class ProcessMonitorFactory -{ - public static IProcessMonitor CreateProcessMonitor(ProcessInfoManager processInfoManager, ILogger logger) - { - return new ProcessMonitor(processInfoManager, logger); - } - - public static ProcessInfoManager CreateProcessInfoGeneratorWindows(ILogger logger) - { - return new ProcessInfoGeneratorWindows(logger); - } - - public static ProcessInfoManager CreateProcessInfoGeneratorWindows( - EventHandler sendNewProcess, - EventHandler sendTerminatedProcess, - EventHandler sendModifiedProcess, - ILogger? logger = null) - { - return new ProcessInfoGeneratorWindows(sendNewProcess, sendTerminatedProcess, sendModifiedProcess, logger); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/IProcessMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/IProcessMonitor.cs deleted file mode 100644 index 1a954fd07..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/IProcessMonitor.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -namespace ModuleProcessMonitor.Processes; - -public interface IProcessMonitor -{ - /// - /// Event if a process has been terminated. - /// - event EventHandler _processTerminated; - - /// - /// Event if a process has been created. - /// - event EventHandler _processCreated; - - /// - /// Event if a process has been modified. - /// - event EventHandler _processModified; - - /// - /// Event if a list of processes has been modified. - /// - event EventHandler> _processesModified; - - /// - /// Returns the current list of the processes from the ProcessMonitor. - /// - /// - SynchronizedCollection? GetProcesses(); - - /// - /// Kills a process by ID. - /// - /// - void KillProcessById(int processId); - - /// - /// Kills a process by name. - /// - /// - void KillProcessByName(string processName); - - /// - /// Sets the ProcessID for the Compose. - /// - /// - void SetComposePid(int pid); - - /// - /// Sets the delay for the terminated processes. It represents the deletion/dissapearence of the processes from the UI and from the collection. - /// - /// - void SetDeadProcessRemovalDelay(int delay); - - /// - /// Sets the ProcessMonitor to watch continuously the created/terminated/modified processes. - /// - void SetWatcher(); - - /// - /// Disables to watch processes through ProcessMonitor. - /// - void UnsetWatcher(); - - /// - /// Adds a compose process to keep track on it. - /// - /// - void AddProcessInfo(ProcessInfoData processInfo); - - /// - /// Initializes the compose processes through the ModuleLoader. - /// - /// - void InitProcesses(IEnumerable processInfoDatas); -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoGeneratorWindows.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoGeneratorWindows.cs deleted file mode 100644 index 27b35332e..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoGeneratorWindows.cs +++ /dev/null @@ -1,374 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Collections.Concurrent; -using System.Diagnostics; -using System.Management; -using System.Runtime.InteropServices; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Logging; - -namespace ModuleProcessMonitor.Processes; - -[System.Runtime.Versioning.SupportedOSPlatform("windows")] -internal class ProcessInfoGeneratorWindows : ProcessInfoManager -{ - private readonly ILogger _logger; - private readonly ConcurrentDictionary _cpuPerformanceCounters; - private readonly ConcurrentDictionary _memoryPerformanceCounters; - private ManagementEventWatcher? _watcher; - private bool _disposed = false; - private readonly object _lock = new(); - public ProcessInfoGeneratorWindows(ILogger? logger) - { - _logger = logger ?? NullLogger.Instance; - _cpuPerformanceCounters = new(); - _memoryPerformanceCounters = new(); - } - - public ProcessInfoGeneratorWindows(EventHandler sendNewProcess, - EventHandler sendTerminatedProcess, EventHandler sendModifiedProcess, - ILogger? logger = null) - : this(logger) - { - base.SetEvents(sendModifiedProcess, sendNewProcess, sendTerminatedProcess); - } - - public override int? GetParentId(Process? process) - { - if (process == null) return null; - - int ppid = 0; - - using var mo = - new ManagementObject( - $"win32_process.handle='{process.Id}'"); - try - { - mo.Get(); - ppid = Convert.ToInt32(mo["ParentProcessId"]); - } - catch (Exception exception) - { - if (process.Id > 0) - { - _logger.ManagementObjectPpidExpected(process.Id, exception); - } - } - - return ppid; - } - - public override float GetMemoryUsage(Process process) - { - int memsize; - - var memoryPerformanceCounter = _memoryPerformanceCounters.GetOrAdd(process.Id, _ => - { - return new PerformanceCounter() - { - CategoryName = "Process", - CounterName = "Working Set - Private", - InstanceName = process.ProcessName, - }; - }); - - memsize = Convert.ToInt32(memoryPerformanceCounter.NextValue()) / Convert.ToInt32(1024) / Convert.ToInt32(1024); - - return (float)((memsize / GetTotalMemoryInMb()) * 100); - } - - private static double GetTotalMemoryInMb() - { - var gcMemoryInfo = GC.GetGCMemoryInfo(); - var installedMemory = gcMemoryInfo.TotalAvailableMemoryBytes; - return Convert.ToDouble(installedMemory) / 1048576.0; - } - - public override float GetCpuUsage(Process process) - { - var cpuPerformanceCounter = _memoryPerformanceCounters.GetOrAdd( - process.Id, - _ => - { - return new PerformanceCounter( - "Process", - "% Processor Time", - process.ProcessName, - true); - }); - - var processCpuUsage = cpuPerformanceCounter.NextValue(); - - return processCpuUsage / Environment.ProcessorCount; - } - - public SynchronizedCollection GetChildProcesses(Process process) - { - var children = new SynchronizedCollection(); - - var mos = new ManagementObjectSearcher( - string.Format( - "Select * From Win32_Process Where ParentProcessID={0} Or ProcessID={0}", - process.Id)); - - foreach (var objectCollection in mos.Get()) - { - var managementObject = (ManagementObject)objectCollection; - try - { - var childProcess = Process.GetProcessById(Convert.ToInt32(managementObject["ProcessID"])); - - var childProcessInfo = new ProcessInformation(childProcess); - - ProcessInformation.SetProcessInfoData(childProcessInfo, this); - - children.Add(childProcessInfo.ProcessInfo); - } - catch (Exception exception) - { - _logger.ChildProcessExpected(exception); - } - } - - return children; - } - - private static List GetProcessIds(IEnumerable processes) - { - var processIds = new List(); - - foreach (var process in processes) - { - if (process.PID != null) - { - processIds.Add(Convert.ToInt32(process.PID)); - } - } - - return processIds; - } - - public override void SetWatchableProcessList(IEnumerable processes) - { - Thread.Sleep(5000); - SetProcessIds(GetProcessIds(processes)); - } - - public override void WatchProcesses() - { - const string wmiQuery = "Select * From __InstanceOperationEvent Within 1 " + - "Where TargetInstance ISA 'Win32_Process' "; - try - { - var scope = new ManagementScope(@"\\.\root\CIMV2"); - scope.Connect(); - _watcher = new ManagementEventWatcher(scope, new EventQuery(wmiQuery)); - _watcher.EventArrived += WmiEventHandler; - _watcher.Start(); - } - catch (Exception exception) - { - _logger.WatcherInitializationError(exception); - } - } - - public override IEnumerable AddChildProcesses(ProcessInfoData processInfo) - { - lock (_lock) - { - if (!ContainsId((int)processInfo.PID!)) - { - AddProcess((int)processInfo.PID!); - } - } - - var processes = new List - { - processInfo - }; - - var pidComparer = new ProcessInfoDataComparer(); - - try - { - var process = Process.GetProcessById((int)processInfo.PID!); - var children = GetChildProcesses(process).ToList(); - - foreach (var child in CollectionsMarshal.AsSpan(children)) - { - if (child.PID == process.Id) - { - continue; - } - - processes.Add(child); - - SendProcessIfItsComposeProcess((int)child.PID!); - - var childrenOfChild = AddChildProcesses(child) - .ToList(); - - foreach (var cChild in CollectionsMarshal.AsSpan(childrenOfChild)) - { - if (processes.Contains(cChild, pidComparer)) - { - continue; - } - - processes.Add(cChild); - SendProcessIfItsComposeProcess((int)cChild.PID!); - } - } - } - catch (Exception exception) - { - _logger.PpidExpected((int)processInfo.PID!, exception); - } - - return processes; - } - - private void SendProcessIfItsComposeProcess(int pid) - { - lock (_lock) - { - if (!CheckIfIsComposeProcess(pid)) return; - - var alreadyAdded = ContainsId(pid); - if (alreadyAdded) return; - - AddProcess(pid); - } - - SendNewProcessUpdate(pid); - } - - private void WmiEventHandler(object sender, EventArrivedEventArgs e) - { - var pid = Convert.ToInt32( - ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["ProcessId"]); - - var wclass = (e.NewEvent).SystemProperties["__Class"] - .Value - .ToString(); - - if (wclass == null) return; - - try - { - switch (wclass) - { - case "__InstanceCreationEvent": - InstanceCreated(pid); - break; - - case "__InstanceDeletionEvent": - InstanceDeleted(pid); - break; - - case "__InstanceModificationEvent": - InstanceModified(pid); - break; - } - } - catch (Exception exception) - { - _logger.InstanceEventExpected(exception); - } - } - - private void InstanceModified(int pid) - { - lock (_lock) - { - var isExists = ContainsId(pid); - if (isExists) - { - SendProcessModifiedUpdate(pid); - } - } - } - - private void InstanceCreated(int pid) - { - var process = GetProcessIfPidExists(pid); - - if (process == null) return; - - lock (_lock) - { - if (!CheckIfIsComposeProcess(pid)) return; - - AddProcess(pid); - } - - SendNewProcessUpdate(pid); - } - - private void InstanceDeleted(int pid) - { - _cpuPerformanceCounters.TryRemove(pid, out var cpuPerf); - cpuPerf?.Close(); - cpuPerf?.Dispose(); - - _memoryPerformanceCounters.TryRemove(pid, out var memoryPerf); - memoryPerf?.Close(); - memoryPerf?.Dispose(); - - lock (_lock) - { - var pidExists = ContainsId(pid); - if (!pidExists) return; - - RemoveProcess(pid); - } - - SendTerminatedProcessUpdate(pid); - } - - private static Process? GetProcessIfPidExists(int pid) - { - try - { - var process = Process.GetProcessById(pid); - process.Refresh(); - return process.Id == 0 ? null : process; - } - catch (Exception) - { - return null; - } - } - - public override void Dispose(bool disposing) - { - ReleaseWatcher(true); - base.Dispose(disposing); - } - - protected virtual void ReleaseWatcher(bool disposing) - { - if (_disposed) return; - - if (disposing) - { - if (_watcher == null) return; - - _watcher.EventArrived -= WmiEventHandler; - _watcher.Stop(); - _watcher.Dispose(); - } - _disposed = true; - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoManager.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoManager.cs deleted file mode 100644 index 9fc9a210c..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessInfoManager.cs +++ /dev/null @@ -1,212 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Diagnostics; - -namespace ModuleProcessMonitor.Processes; - -public abstract class ProcessInfoManager -{ - private event EventHandler? _sendNewProcess; - private event EventHandler? _sendTerminatedProcess; - private event EventHandler? _sendModifiedProcess; - private SynchronizedCollection _processIds = new(); - private readonly object _locker = new(); - - /// - /// Sets the events to watch processes. Sets the actions to watch created, terminated and modified processes. - /// - /// - /// - /// - public void SetEvents(EventHandler sendModifiedProcessAction, - EventHandler sendNewProcessAction, - EventHandler sendTerminatedProcessAction) - { - _sendModifiedProcess += sendModifiedProcessAction; - _sendTerminatedProcess += sendTerminatedProcessAction; - _sendNewProcess += sendNewProcessAction; - } - - public bool ContainsId(Process process) - { - lock (_locker) - { - return _processIds.Contains(process.Id); - } - } - - public bool ContainsId(int pid) - { - lock (_locker) - { - return _processIds.Contains(pid); - } - } - - public void AddProcess(int pid) - { - lock (_locker) - { - _processIds.Add(pid); - } - } - - public void RemoveProcess(int pid) - { - lock (_locker) - { - _processIds.Remove(pid); - } - } - - public void SetProcessIds(IEnumerable ids) - { - lock (_locker) - { - foreach (var id in ids) - { - if (_processIds.Contains(id)) continue; - _processIds.Add(id); - } - } - } - - /// - /// Returns the PPID of the given process. - /// - /// - /// - public abstract int? GetParentId(Process? process); - - /// - /// Returns the memory usage (%) of the given process. - /// - /// - /// - public abstract float GetMemoryUsage(Process process); - - /// - /// Returns the CPU usage (%) of the given process. - /// - /// - /// - public abstract float GetCpuUsage(Process process); - - /// - /// Sets the processes to watch. - /// - /// - public abstract void SetWatchableProcessList(IEnumerable processes); - - /// - /// Continuously watching created processes. - /// - public abstract void WatchProcesses(); - - /// - /// Checks if the given process is related to the main process. - /// - /// - /// - private bool IsComposeProcess(object process) - { - var proc = process as Process; - proc?.Refresh(); - - if (proc == null) - { - return false; - } - - if (proc.Id == ProcessMonitor.ComposePid || - ContainsId(proc.Id)) - { - return true; - } - - int? ppid; - try - { - ppid = GetParentId(proc); - - if (ppid == null || ppid == 0) - { - return false; - } - - if (ContainsId((int)ppid)) - { - return true; - } - - proc = Process.GetProcessById(Convert.ToInt32(ppid)); - return IsComposeProcess(proc); - } - catch (Exception) - { - return false; - } - } - - /// - /// Searches for child processes to watch. - /// - /// - /// - public abstract IEnumerable AddChildProcesses(ProcessInfoData processInfo); - - /// - /// Checks if a process belongs to the Compose. - /// - /// - public bool CheckIfIsComposeProcess(int pid) - { - return IsComposeProcess(Process.GetProcessById(pid)); - } - - public void SendNewProcessUpdate(int pid) - { - _sendNewProcess?.Invoke(this, pid); - } - - /// - /// Sends a terminated process information to publish - /// - /// - public void SendTerminatedProcessUpdate(int pid) - { - _sendTerminatedProcess?.Invoke(this, pid); - } - - /// - /// Sends a modified process information to publish - /// - /// - public void SendProcessModifiedUpdate(int pid) - { - _sendModifiedProcess?.Invoke(this, pid); - } - - ~ProcessInfoManager() - { - Dispose(); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public virtual void Dispose(bool disposing) { } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessMonitor.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessMonitor.cs deleted file mode 100644 index 28b64f129..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessMonitor.cs +++ /dev/null @@ -1,395 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Diagnostics; -using System.Runtime.InteropServices; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Logging; - -namespace ModuleProcessMonitor.Processes; - -//TODO(Lilla): needs to handle when observability sends messages to them so new communicator -internal class ProcessMonitor : IProcessMonitor -{ - public static int ComposePid { get; set; } - public static int DelayTime = 60000; - private readonly ProcessMonitorInfo _processMonitorInfo = new(); - private readonly ProcessInfoManager? _processInfoManager; - private readonly ILogger _logger; - private readonly object _locker = new(); - public event EventHandler? _processTerminated; - public event EventHandler? _processCreated; - public event EventHandler? _processModified; - public event EventHandler>? _processesModified; - - public ProcessMonitor(ProcessInfoManager? processInfoManager, - ILogger? logger = null) - : this(logger) - { - _processInfoManager = processInfoManager; - SetEventsIfTheyAreNotDeclared(); - } - - public ProcessMonitor(ILogger? logger = null) - { - _logger = logger ?? NullLogger.Instance; - } - - private void ClearList() - { - lock (_locker) - { - _processMonitorInfo.Processes.Clear(); - } - } - - public void SetDeadProcessRemovalDelay(int delay) - { - DelayTime = delay * 1000; - } - - public void SetWatcher() - { - lock (_locker) - { - if (_processMonitorInfo.Processes.Any()) - { - _processInfoManager?.SetWatchableProcessList(_processMonitorInfo.Processes); - } - } - _processInfoManager?.WatchProcesses(); - _logger.ProcessListIsInitializedDebug(); - } - - public void UnsetWatcher() - { - _processInfoManager?.Dispose(); - } - - public void SetComposePid(int pid) - { - ComposePid = pid; - } - - private void SetEventsIfTheyAreNotDeclared() - { - _processInfoManager?.SetEvents(SendModifiedProcess, SendNewProcess, SendTerminatedProcess); - } - - public SynchronizedCollection GetProcesses() - { - lock (_locker) - { - return _processMonitorInfo.Processes; - } - } - - private void KillProcess(Process process) - { - try - { - process.Kill(); - } - catch (Exception exception) - { - _logger.KillProcessError(exception); - } - } - - public void KillProcessByName(string processName) - { - var process = Process.GetProcessesByName(processName) - .First(); - - KillProcessWithChecking(process); - } - - public void KillProcessById(int processId) - { - var process = Process.GetProcessById(processId); - - KillProcessWithChecking(process); - } - - private bool TryDeleteProcess(int pid) - { - try - { - var terminatedProcess = GetProcessInfoData(pid); - - if (terminatedProcess != null) - { - _logger.ProcessTerminatedInformation(pid); - ModifyStatusToTerminated(terminatedProcess); - RemoveProcessAfterTimeout(terminatedProcess); - return true; - } - } - catch (Exception exception) - { - _logger.PpidExpected(pid, exception); - } - - return false; - } - - private void ModifyStatusToTerminated(ProcessInfoData processToModify) - { - lock (_locker) - { - var index = _processMonitorInfo.Processes.IndexOf(processToModify); - _processMonitorInfo.Processes[index].ProcessStatus = Status.Terminated.ToStringCached(); - _processMonitorInfo.Processes[index].ProcessorUsage = 0; - _processMonitorInfo.Processes[index].PhysicalMemoryUsageBit = 0; - _processMonitorInfo.Processes[index].VirtualMemorySize = 0; - _processMonitorInfo.Processes[index].PrivateMemoryUsage = 0; - _processMonitorInfo.Processes[index].Threads = new SynchronizedCollection(); - _processModified?.Invoke(this, _processMonitorInfo.Processes[index]); - } - } - - private void RemoveProcessAfterTimeout(ProcessInfoData item) - { - Task.Run(async () => - { - await Task.Delay(DelayTime); - var terminatedProcess = GetProcessInfoData((int)item.PID!); - if (terminatedProcess != null) - { - lock (_locker) - { - var indexOfTerminatedProcess = _processMonitorInfo.Processes.IndexOf(terminatedProcess); - - _processMonitorInfo.Processes.RemoveAt(indexOfTerminatedProcess); - - _processesModified?.Invoke(this, _processMonitorInfo.Processes); - _processTerminated?.Invoke(this, Convert.ToInt32(item.PID)); - } - } - }); - } - - private void SendNewProcess(object? sender, int processId) - { - var processInfo = ProcessCreated(Process.GetProcessById(processId)); - - if (processInfo == null) - { - return; - } - - if (!AlreadyAdded(processId)) - { - lock (_locker) - { - _processMonitorInfo.Processes.Add(processInfo.ProcessInfo); - } - - _logger.ProcessCreatedInformation(processId); - } - - _processCreated?.Invoke(this, processInfo.ProcessInfo); - } - - private void SendTerminatedProcess(object? sender, int pid) - { - if (!TryDeleteProcess(pid)) - { - _logger.ProcessNotFoundWarning(pid); - } - } - - private void SendModifiedProcess(object? sender, int pid) - { - try - { - var process = Process.GetProcessById(pid); - process.Refresh(); - - if (process.Id <= 0 || - _processInfoManager == null) return; - - var processInfo = new ProcessInformation(process); - ProcessInformation.SetProcessInfoData(processInfo, _processInfoManager); - - if (processInfo.ProcessInfo.PID == null) - { - return; - } - - var existedProcessInfo = GetProcessInfoData((int)processInfo.ProcessInfo.PID!); - - if (existedProcessInfo == null) return; - - lock (_locker) - { - var index = Convert.ToInt32(_processMonitorInfo.Processes - .IndexOf(existedProcessInfo)); - - ModifyElement(index, processInfo.ProcessInfo); - } - - _processModified?.Invoke(this, existedProcessInfo); - - _logger.ProcessModifiedDebug(pid); - } - catch (Exception exception) - { - _logger.ModifiableProcessExpected(pid, exception); - } - } - - private bool AlreadyAdded(int pid) - { - lock (_locker) - { - var isExists = _processMonitorInfo.Processes - .Any(p => p.PID == pid); - - return isExists; - } - } - - //It is used in lock statements. - private void ModifyElement(int index, ProcessInfoData processInfo) - { - if (index == -1) return; - - _processMonitorInfo.Processes[index].ProcessStatus = processInfo.ProcessStatus; - _processMonitorInfo.Processes[index].PhysicalMemoryUsageBit = processInfo.PhysicalMemoryUsageBit; - _processMonitorInfo.Processes[index].ProcessorUsage = processInfo.ProcessorUsage; - _processMonitorInfo.Processes[index].ProcessorUsageTime = processInfo.ProcessorUsageTime; - _processMonitorInfo.Processes[index].ProcessPriorityClass = processInfo.ProcessPriorityClass; - _processMonitorInfo.Processes[index].PriorityLevel = processInfo.PriorityLevel; - _processMonitorInfo.Processes[index].Threads = processInfo.Threads; - _processMonitorInfo.Processes[index].VirtualMemorySize = processInfo.VirtualMemorySize; - _processMonitorInfo.Processes[index].PrivateMemoryUsage = processInfo.PrivateMemoryUsage; - _processMonitorInfo.Processes[index].MemoryUsage = processInfo.MemoryUsage; - _processMonitorInfo.Processes[index].StartTime = processInfo.StartTime; - } - - private void KillProcessWithChecking(Process? process) - { - lock (_locker) - { - var isComposeProcess = _processMonitorInfo.Processes - .Any(proc => - proc.PID == process?.Id); - - if (process != null && - isComposeProcess) - { - KillProcess(process); - } - } - } - - private ProcessInfoData? GetProcessInfoData(int pid) - { - lock (_locker) - { - var processInfoData = _processMonitorInfo.Processes - .FirstOrDefault(p => p.PID == pid); - - return processInfoData; - } - } - - public void AddProcessInfo(ProcessInfoData processInfo) - { - lock (_locker) - { - var existedProcessInfo = _processMonitorInfo.Processes - .FirstOrDefault(p => - p.PID == processInfo.PID); - - - if (existedProcessInfo == null) - { - _processMonitorInfo.Processes.Add(processInfo); - } - else - { - var index = _processMonitorInfo.Processes - .IndexOf(existedProcessInfo); - - ModifyElement(index, processInfo); - } - - RefreshWatchedProcessList(processInfo); - } - } - - public void InitProcesses(IEnumerable processInfoDatas) - { - ClearList(); - - var processes = processInfoDatas.ToList(); - lock (_locker) - { - foreach (var process in CollectionsMarshal.AsSpan(processes)) - { - if (process == null) continue; - _processMonitorInfo.Processes.Add(process); - _processInfoManager?.AddChildProcesses(process); - } - - _processesModified?.Invoke(this, _processMonitorInfo.Processes); - } - } - - private void RefreshWatchedProcessList(ProcessInfoData processInfo) - { - var children = _processInfoManager? - .AddChildProcesses(processInfo) - .ToList(); - - var pidComparer = new ProcessInfoDataComparer(); - - lock (_locker) - { - foreach (var child in CollectionsMarshal.AsSpan(children)) - { - if (!_processMonitorInfo.Processes.Contains(child, pidComparer)) - { - _processMonitorInfo.Processes.Add(child); - } - else - { - var index = _processMonitorInfo - .Processes.IndexOf(child); - - ModifyElement(index, child); - } - } - - //Refreshes the list to watch - _processInfoManager?.SetWatchableProcessList(_processMonitorInfo.Processes); - } - } - - /// - /// Creates a processInfoData object. - /// - /// - /// - private ProcessInformation? ProcessCreated(Process process) - { - if (_processInfoManager == null) return null; - - var processInfo = ProcessInformation - .GetProcessInfoWithCalculatedData(process, _processInfoManager); - - return processInfo; - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessThreadInfo.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessThreadInfo.cs deleted file mode 100644 index fede413d5..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Processes/ProcessThreadInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.ComponentModel; -using System.Diagnostics; -using ThreadState = System.Diagnostics.ThreadState; - -namespace ModuleProcessMonitor.Processes; - -public class ProcessThreadInfo -{ - public string? StartTime { get; internal set; } - public int? PriorityLevel { get; internal set; } - public int? Id { get; internal set; } - public string? Status { get; internal set; } - public TimeSpan? ProcessorUsageTime { get; internal set; } - public string? WaitReason { get; internal set; } - - internal static ProcessThreadInfo? FromProcessThread(ProcessThread processThread) - { - var result = new ProcessThreadInfo(); - try - { - if (processThread.ThreadState == ThreadState.Wait) - { - result.WaitReason = processThread.WaitReason.ToStringCached(); - } - result.StartTime = processThread.StartTime.ToString("yyyy.MM.dd. hh:mm:s"); - result.ProcessorUsageTime = processThread.TotalProcessorTime; - } - //ProcessThread could raise 2 exceptions: Win32(thread time could not be retrieved) and NotSupported(computer is on remote computer) - catch (Win32Exception) - { - return null; - } - catch (NotSupportedException) - { - return null; - } - finally - { - result.PriorityLevel = processThread.CurrentPriority; - result.Id = processThread.Id; - result.Status = processThread.ThreadState.ToStringCached(); - } - - return result; - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/ISubsystemControllerCommunicator.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/ISubsystemControllerCommunicator.cs deleted file mode 100644 index 53f1ff824..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ModuleProcessMonitor/Subsystems/ISubsystemControllerCommunicator.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -namespace ModuleProcessMonitor.Subsystems; - -public interface ISubsystemControllerCommunicator -{ - /// - /// Sets the route of the communication to send messages to the ModuleLoader, if the user wants to launch/restart/stop multiple subsystems, - /// or launch a subsystem after a given period of time. - /// - /// - ValueTask InitializeCommunicationRoute(); -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer.sln b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer.sln deleted file mode 100644 index ad393728a..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer.sln +++ /dev/null @@ -1,51 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocalCollector", "LocalCollector\LocalCollector.csproj", "{7477253B-E661-4619-AE03-4315C7AF00FC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer", "ProcessExplorer\ProcessExplorer.csproj", "{AC711864-0E65-43C9-A131-C650C25185F6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuperRPC-POC", "SuperRPC-POC\SuperRPC-POC.csproj", "{D429CD1B-0DA4-441F-8F4B-5E7E3BDD4763}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModuleProcessMonitor", "ModuleProcessMonitor\ModuleProcessMonitor.csproj", "{E03A6F9D-6CBA-4B64-945B-515C19998744}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7477253B-E661-4619-AE03-4315C7AF00FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7477253B-E661-4619-AE03-4315C7AF00FC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7477253B-E661-4619-AE03-4315C7AF00FC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7477253B-E661-4619-AE03-4315C7AF00FC}.Release|Any CPU.Build.0 = Release|Any CPU - {AC711864-0E65-43C9-A131-C650C25185F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AC711864-0E65-43C9-A131-C650C25185F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AC711864-0E65-43C9-A131-C650C25185F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AC711864-0E65-43C9-A131-C650C25185F6}.Release|Any CPU.Build.0 = Release|Any CPU - {D429CD1B-0DA4-441F-8F4B-5E7E3BDD4763}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D429CD1B-0DA4-441F-8F4B-5E7E3BDD4763}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D429CD1B-0DA4-441F-8F4B-5E7E3BDD4763}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D429CD1B-0DA4-441F-8F4B-5E7E3BDD4763}.Release|Any CPU.Build.0 = Release|Any CPU - {07FFBC09-033E-4EDA-95DA-C8B9390F85D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {07FFBC09-033E-4EDA-95DA-C8B9390F85D6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07FFBC09-033E-4EDA-95DA-C8B9390F85D6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {07FFBC09-033E-4EDA-95DA-C8B9390F85D6}.Release|Any CPU.Build.0 = Release|Any CPU - {E03A6F9D-6CBA-4B64-945B-515C19998744}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E03A6F9D-6CBA-4B64-945B-515C19998744}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E03A6F9D-6CBA-4B64-945B-515C19998744}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E03A6F9D-6CBA-4B64-945B-515C19998744}.Release|Any CPU.Build.0 = Release|Any CPU - {BEA2109E-4D46-4129-9EB6-AD0E1E37D54B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BEA2109E-4D46-4129-9EB6-AD0E1E37D54B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BEA2109E-4D46-4129-9EB6-AD0E1E37D54B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BEA2109E-4D46-4129-9EB6-AD0E1E37D54B}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {819F883C-DDD0-4F2B-82C5-820D4D6AB446} - EndGlobalSection -EndGlobal diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/UIClientsStore.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/UIClientsStore.cs deleted file mode 100644 index b97cbe5ab..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Infrastructure/UIClientsStore.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - - -namespace ProcessExplorer.Infrastructure; - -internal static class UiClientsStore -{ - internal static SynchronizedCollection _uiClients = new(); - internal static readonly object _uiClientLocker = new(); - - public static void AddUiConnection(IUIHandler uiHandler) - { - lock (_uiClientLocker) - { - var element = _uiClients.FirstOrDefault(uih => uih == uiHandler); - if (element == null) - { - _uiClients.Add(uiHandler); - } - } - } - - public static void RemoveUiConnection(IUIHandler uiHandler) - { - lock (_uiClientLocker) - { - var element = _uiClients - .FirstOrDefault(uih => - uih == uiHandler); - - if (element != null) - { - _uiClients.Remove(uiHandler); - } - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Logging/SourceGeneratedLoggerExtensions.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Logging/SourceGeneratedLoggerExtensions.cs deleted file mode 100644 index cc6631aef..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Logging/SourceGeneratedLoggerExtensions.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using Microsoft.Extensions.Logging; - -namespace ProcessExplorer.Logging; -internal static partial class SourceGeneratedLoggerExtensions -{ - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "Couldn't find the PPID for the PID `{pid}`. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ManagementObjectPpid(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "ProcessMonitor UICommunicator is set.", SkipEnabledCheck = false)] - public static partial void ProcessMonitorCommunicatorIsSetDebug(this ILogger logger); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot add the connections to collection. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ConnectionCollectionCannotBeAdded(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Connection cannot be updated. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ConnectionCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Couldn't watch the processes. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void EnvironmentVariablesCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Registrations cannot be updated. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void RegistrationsCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Modules cannot be updated. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ModulesCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "A UIHandler is removed from the collection", SkipEnabledCheck = false)] - public static partial void UiCommunicatorIsRemovedDebug(this ILogger logger); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot modify subsystem's state with ID `{subsystemId}`. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void ModifyingSubsystemsState(this ILogger logger, string subsystemId, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Error while terminating the process, ID: {pid}. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotTerminateProcess(this ILogger logger, int pid, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Updating the information on UI cannot be completed. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void UiInformationCannotBeUpdated(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot send launch request to the SubsystemLauncher. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotSendLaunchRequest(this ILogger logger, Exception ex, Exception exception); - - [LoggerMessage(EventId = 4, Level = LogLevel.Error, Message = "Cannot terminate a subsystem. Detailed exception: `{exception}`", SkipEnabledCheck = true)] - private static partial void CannotTerminateSubsystem(this ILogger logger, Exception ex, Exception exception); - - - public static void UiInformationCannotBeUpdatedError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.UiInformationCannotBeUpdated(exception, exception); - } - } - public static void CannotTerminateSubsystemError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotTerminateSubsystem(exception, exception); - } - } - - public static void CannotSendLaunchRequestError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotSendLaunchRequest(exception, exception); - } - } - - public static void ManagementObjectPPID(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Debug)) - { - logger.ManagementObjectPpid(pid, exception, exception); - } - } - - public static void ConnectionCollectionCannotBeAddedError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.ConnectionCollectionCannotBeAdded(exception, exception); - } - } - - public static void ConnectionCannotBeUpdatedError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.ConnectionCannotBeUpdated(exception, exception); - } - } - - public static void EnvironmentVariablesCannotBeUpdatedError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.EnvironmentVariablesCannotBeUpdated(exception, exception); - } - } - - public static void RegistrationsCannotBeUpdatedError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.RegistrationsCannotBeUpdated(exception, exception); - } - } - - public static void ModulesCannotBeUpdatedError(this ILogger logger, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.ModulesCannotBeUpdated(exception, exception); - } - } - - public static void CannotTerminateProcessError(this ILogger logger, int pid, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.CannotTerminateProcess(pid, exception, exception); - } - } - - public static void ModifyingSubsystemsStateError(this ILogger logger, Guid subsystemId, Exception exception) - { - if (logger.IsEnabled(LogLevel.Error)) - { - logger.ModifyingSubsystemsState(subsystemId.ToString(), exception, exception); - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/ProcessInfoAggregator.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/ProcessInfoAggregator.cs deleted file mode 100644 index 2d21e85e6..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/ProcessInfoAggregator.cs +++ /dev/null @@ -1,354 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Collections.Concurrent; -using LocalCollector; -using LocalCollector.Connections; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Processes; -using ProcessExplorer.Infrastructure; -using ProcessExplorer.Logging; - -namespace ProcessExplorer; - -internal class ProcessInfoAggregator : IProcessInfoAggregator -{ - private readonly ILogger _logger; - public ConcurrentDictionary ProcessInformation { get; } = new(); - public IProcessMonitor? ProcessMonitor { get; private set; } - private readonly object _informationLocker = new(); - - public ProcessInfoAggregator(ILogger? logger, IProcessMonitor? processMonitor) - { - _logger = logger ?? NullLogger.Instance; - - if (processMonitor == null) - { - return; - } - - ProcessMonitor = processMonitor; - SetUiCommunicatorsToWatchProcessChanges(); - } - - private static IEnumerable CreateCopyOfClients() - { - lock (UiClientsStore._uiClientLocker) - { - return UiClientsStore._uiClients.ToArray(); - } - } - - public async Task AddInformation(string assemblyId, ProcessInfoCollectorData runtimeInfo) - { - lock (_informationLocker) - { - ProcessInformation.AddOrUpdate(assemblyId, runtimeInfo, (_, _) => runtimeInfo); - } - await UpdateInfoOnUI(handler => handler.AddRuntimeInfo(assemblyId, runtimeInfo)); - } - - public void RemoveAInfoAggregatorInformation(string assembly) - { - lock (_informationLocker) - { - ProcessInformation.TryRemove(assembly, out _); - } - } - - public void SetComposePid(int pid) - { - ProcessMonitor?.SetComposePid(pid); - } - - public IEnumerable? GetProcesses() - { - return ProcessMonitor?.GetProcesses(); - } - - - private void SetUiCommunicatorsToWatchProcessChanges() - { - if (ProcessMonitor == null) - { - return; - } - - ProcessMonitor._processCreated += ProcessCreated; - ProcessMonitor._processModified += ProcessModified; - ProcessMonitor._processTerminated += ProcessTerminated; - ProcessMonitor._processesModified += ProcessesModified; - } - - private void ProcessesModified(object? sender, SynchronizedCollection e) - { - lock (UiClientsStore._uiClientLocker) - { - foreach (var client in UiClientsStore._uiClients) - { - client.AddProcesses(e); - } - } - } - - private void ProcessTerminated(object? sender, int e) - { - lock (UiClientsStore._uiClientLocker) - { - foreach (var client in UiClientsStore._uiClients) - { - client.RemoveProcessByID(e); - if (ProcessMonitor != null) - { - client.AddProcesses(ProcessMonitor.GetProcesses()!); - } - } - } - } - - private void ProcessModified(object? sender, ProcessInfoData e) - { - lock (UiClientsStore._uiClientLocker) - { - foreach (var client in UiClientsStore._uiClients) - { - client.UpdateProcess(e); - } - } - } - - private void ProcessCreated(object? sender, ProcessInfoData e) - { - lock (UiClientsStore._uiClientLocker) - { - foreach (var client in UiClientsStore._uiClients) - { - client.AddProcess(e); - } - } - } - - public void SetDeadProcessRemovalDelay(int delay) - { - ProcessMonitor?.SetDeadProcessRemovalDelay(delay); - } - - public void AddUiConnection(IUIHandler uiHandler) - { - UiClientsStore.AddUiConnection(uiHandler); - if (ProcessMonitor == null) - { - return; - } - - uiHandler.AddProcesses(ProcessMonitor.GetProcesses()!); - uiHandler.AddRuntimeInfo(ProcessInformation); - _logger.ProcessMonitorCommunicatorIsSetDebug(); - } - - public void RemoveUiConnection(IUIHandler uiHandler) - { - UiClientsStore.RemoveUiConnection(uiHandler); - _logger.UiCommunicatorIsRemovedDebug(); - } - - private ProcessInfoCollectorData? GetDataToModify(string assemblyId) - { - ProcessInfoCollectorData? data; - - lock (_informationLocker) - { - data = ProcessInformation - .First(kvp => kvp.Key == assemblyId) - .Value; - } - - return data; - } - - private void UpdateProcessInfoCollectorData(string assemblyId, ProcessInfoCollectorData data) - { - lock (_informationLocker) - { - ProcessInformation.AddOrUpdate(assemblyId, data, (_, _) => data); - } - } - - public async Task AddConnectionCollection(string assemblyId, IEnumerable connections) - { - ProcessInfoCollectorData? processInfoToModify = GetDataToModify(assemblyId); - - if (processInfoToModify != null) - { - try - { - processInfoToModify.AddOrUpdateConnections(connections); - UpdateProcessInfoCollectorData(assemblyId, processInfoToModify); - } - catch (Exception exception) - { - _logger.ConnectionCollectionCannotBeAddedError(exception); - } - await UpdateInfoOnUI(handler => handler.AddConnections(assemblyId, connections)); - } - } - - public async Task UpdateConnectionInfo(string assemblyId, ConnectionInfo connectionInfo) - { - ProcessInfoCollectorData? processInfoToModify = GetDataToModify(assemblyId); - - if (processInfoToModify != null) - { - try - { - processInfoToModify.UpdateConnection(connectionInfo); - UpdateProcessInfoCollectorData(assemblyId, processInfoToModify); - } - catch (Exception exception) - { - _logger.ConnectionCannotBeUpdatedError(exception); - } - await UpdateInfoOnUI(handler => handler.UpdateConnection(assemblyId, connectionInfo)); - } - } - - public async Task UpdateEnvironmentVariablesInfo(string assemblyId, IEnumerable> environmentVariables) - { - ProcessInfoCollectorData? processInfoToModify = GetDataToModify(assemblyId); - - if (processInfoToModify != null) - { - try - { - processInfoToModify.UpdateEnvironmentVariables(environmentVariables); - UpdateProcessInfoCollectorData(assemblyId, processInfoToModify); - } - catch (Exception exception) - { - _logger.EnvironmentVariablesCannotBeUpdatedError(exception); - } - await UpdateInfoOnUI(handler => handler.UpdateEnvironmentVariables(assemblyId, environmentVariables)); - } - } - - public async Task UpdateRegistrationInfo(string assemblyId, IEnumerable registrations) - { - ProcessInfoCollectorData? processInfoToModify = GetDataToModify(assemblyId); - - if (processInfoToModify != null) - { - try - { - processInfoToModify.UpdateRegistrations(registrations); - UpdateProcessInfoCollectorData(assemblyId, processInfoToModify); - } - catch (Exception exception) - { - _logger.RegistrationsCannotBeUpdatedError(exception); - } - await UpdateInfoOnUI(handler => handler.UpdateRegistrations(assemblyId, registrations)); - } - } - - public async Task UpdateModuleInfo(string assemblyId, IEnumerable modules) - { - ProcessInfoCollectorData? processInfoToModify = GetDataToModify(assemblyId); - - if (processInfoToModify != null) - { - try - { - processInfoToModify.UpdateModules(modules); - UpdateProcessInfoCollectorData(assemblyId, processInfoToModify); - } - catch (Exception exception) - { - _logger.ModulesCannotBeUpdatedError(exception); - } - await UpdateInfoOnUI(handler => handler.UpdateModules(assemblyId, modules)); - } - } - - public async Task RemoveProcessById(int pid) - { - try - { - ProcessMonitor?.KillProcessById(pid); - } - catch (Exception exception) - { - _logger.CannotTerminateProcessError(pid, exception); - } - await UpdateInfoOnUI(handler => handler.RemoveProcessByID(pid)); - } - - public void EnableWatchingSavedProcesses() - { - ProcessMonitor?.SetWatcher(); - } - - public void DisableWatchingProcesses() - { - ProcessMonitor?.UnsetWatcher(); - } - - public void InitProcesses(IEnumerable processInfo) - { - ProcessMonitor?.InitProcesses(processInfo); - } - - private Task UpdateInfoOnUI(Func handlerAction) - { - try - { - return Task.WhenAll(CreateCopyOfClients().Select(handlerAction)); - } - catch (Exception exception) - { - _logger.UiInformationCannotBeUpdatedError(exception); - return Task.CompletedTask; - } - } - - public Task SetProcessMonitor(IProcessMonitor processMonitor) - { - return new Task(() => - { - UnSubscribeProcessMonitor(); - ProcessMonitor = processMonitor; - SetUiCommunicatorsToWatchProcessChanges(); - }); - } - - private void UnSubscribeProcessMonitor() - { - if (ProcessMonitor == null) - { - return; - } - - ProcessMonitor._processCreated -= ProcessCreated; - ProcessMonitor._processModified -= ProcessModified; - ProcessMonitor._processTerminated -= ProcessTerminated; - ProcessMonitor._processesModified -= ProcessesModified; - - ProcessMonitor = null; - } - - public void AddProcessInfo(ProcessInfoData processInfo) - { - ProcessMonitor?.AddProcessInfo(processInfo); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/SubsystemController.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/SubsystemController.cs deleted file mode 100644 index d43321909..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/Subsystems/SubsystemController.cs +++ /dev/null @@ -1,418 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Collections.ObjectModel; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Subsystems; -using ProcessExplorer.Infrastructure; -using ProcessExplorer.Logging; - -namespace ProcessExplorer.Subsystems; - -/// -/// Gets the messages from the UI and sends command to the subsystemHandler (proxy object) -/// -internal class SubsystemController : ISubsystemController -{ - private ObservableCollection> _subsystems = new(); - private readonly object _subsystemLock = new(); - private readonly ILogger _logger; - public ISubsystemLauncherCommunicator SubsystemLauncherCommunicator { get; } - - public SubsystemController(ISubsystemLauncherCommunicator subsystemLauncherCommunicator, - ILogger? logger) - { - SubsystemLauncherCommunicator = subsystemLauncherCommunicator; - _logger = logger ?? NullLogger.Instance; - } - - public async Task InitializeSubsystems(IEnumerable> subsystems) - { - UpdateOrAddElements(subsystems); - - SetCollectionChangedEvent(); - - await LaunchSubsystemsAutomatically(); - await SendInitializedSubsystemInfoToUis(); - } - - private void SetCollectionChangedEvent() - { - lock (_subsystemLock) - { - _subsystems.CollectionChanged += async (sender, args) => - { - List> subsystemsCopy; - lock (_subsystemLock) - { - subsystemsCopy = _subsystems.ToList(); - } - - await UpdateInfoOnUI(handler => handler.AddSubsystems(subsystemsCopy)); - }; - } - } - - public async Task LaunchAllRegisteredSubsystem() - { - try - { - var guids = Enumerable.Empty(); - - lock (_subsystemLock) - { - if (_subsystems.Any()) - { - //Must have key - guids = _subsystems - .Select(subsystem => subsystem.Key); - } - - if (!guids.Any()) return; - } - - await SubsystemLauncherCommunicator.SendLaunchSubsystemsRequest(guids); - } - catch (Exception exception) - { - _logger.CannotSendLaunchRequestError(exception); - } - } - - public async Task LaunchSubsystemAfterTime(Guid subsystemId, int periodOfTime) - { - await SubsystemLauncherCommunicator.SendLaunchSubsystemAfterTimeRequest(subsystemId, periodOfTime); - } - - public async Task LaunchSubsystemAutomatically(Guid subsystemId) - { - var subsystem = GetSubsystem(subsystemId); - - if (subsystem != null) - { - await LaunchSubsystem(subsystem.Value.Key.ToString()); - subsystem.Value.Value.AutomatedStart = true; - } - } - - public async Task LaunchSubsystemsAutomatically() - { - var subsystemIds = new SynchronizedCollection(); - lock (_subsystemLock) - { - if (_subsystems.Any()) - { - foreach (var subsystem in _subsystems) - { - if (subsystem.Value.AutomatedStart == true && subsystem.Value.State == SubsystemState.Stopped) - { - subsystemIds.Add(subsystem.Key.ToString()); - } - } - } - } - - await LaunchSubsystems(subsystemIds); - } - - public async Task LaunchSubsystems(IEnumerable subsystems) - { - try - { - if (subsystems.Any()) - { - var subsystemIds = subsystems - .Select(id => new Guid(id)); - - await SubsystemLauncherCommunicator.SendLaunchSubsystemsRequest(subsystemIds); - } - } - catch (Exception exception) - { - _logger.CannotSendLaunchRequestError(exception); - } - } - - public async Task LaunchSubsystem(string subsystemId) - { - await SubsystemLauncherCommunicator.SendLaunchSubsystemsRequest(new List { new(subsystemId) }); - } - - public async Task RestartSubsystems(IEnumerable subsystems) - { - foreach (var subsystemId in subsystems) - { - var registeredSubsystem = GetSubsystem(new Guid(subsystemId)); - - if (registeredSubsystem == null) - { - continue; - } - - await SubsystemLauncherCommunicator.SendRestartSubsystemsRequest(new List { new(subsystemId) }); - } - } - - public async Task RestartSubsystem(string subsystemId) - { - await SubsystemLauncherCommunicator.SendRestartSubsystemsRequest(new List { new(subsystemId) }); - } - - public async Task ShutdownAllRegisteredSubsystem() - { - try - { - IEnumerable> copySubsystems; - - lock (_subsystemLock) - { - copySubsystems = _subsystems.ToList(); - } - - if (copySubsystems.Any()) - { - await SubsystemLauncherCommunicator - .SendShutdownSubsystemsRequest(copySubsystems - .Select(element => element.Key)); - } - } - catch (Exception exception) - { - _logger.CannotTerminateSubsystemError(exception); - } - } - - public async Task ShutdownSubsystem(string subsystemId) - { - await SubsystemLauncherCommunicator.SendShutdownSubsystemsRequest(new List() { new Guid(subsystemId) }); - } - - public async Task ShutdownSubsystems(IEnumerable subsystems) - { - try - { - var subsystemIds = subsystems - .Select(id => new Guid(id)); - - await SubsystemLauncherCommunicator.SendShutdownSubsystemsRequest(subsystemIds); - } - catch (Exception exception) - { - _logger.CannotTerminateSubsystemError(exception); - } - } - - - public async Task ModifySubsystemState(Guid subsystemId, string state) - { - KeyValuePair subsystem; - - lock (_subsystemLock) - { - subsystem = _subsystems - .FirstOrDefault(sub => - sub.Key.Equals(subsystemId)); - - try - { - - subsystem.Value.State = state; - - } - catch (Exception exception) - { - _logger.ModifyingSubsystemsStateError(subsystemId, exception); - } - } - - await UpdateInfoOnUI(handler => handler.UpdateSubsystemInfo(subsystemId, subsystem.Value)); - } - - public async Task AddUIConnection(IUIHandler uiHandler) - { - UiClientsStore.AddUiConnection(uiHandler); - await SendInitializedSubsystemInfoToUis(); - } - - public Task RemoveUIConnection(IUIHandler uiHandler) - { - return Task.Factory.StartNew(() => - { - UiClientsStore.RemoveUiConnection(uiHandler); - }); - } - - public async Task AddSubsystems(IEnumerable> subsystems) - { - UpdateOrAddElements(subsystems); - await UpdateInfoOnUI(handler => handler.AddSubsystems(subsystems)); - } - - public void AddSubsystem(Guid subsystemId, SubsystemInfo subsystem) - { - lock (_subsystemLock) - { - _subsystems.Add(new(subsystemId, subsystem)); - } - } - - public void RemoveSubsystem(Guid subsystemId) - { - var subsystem = GetSubsystem(subsystemId); - - lock (_subsystemLock) - { - if (subsystem == null || - !_subsystems.Contains(subsystem.Value)) - { - return; - } - - var subsystems = _subsystems - .Where(subsystemKeyValuePair => - subsystemKeyValuePair.Key != subsystemId); - - _subsystems = new ObservableCollection>(subsystems); - SetCollectionChangedEvent(); - } - } - - private KeyValuePair? GetSubsystem(Guid subsystemId) - { - KeyValuePair subsystem; - - lock (_subsystemLock) - { - subsystem = _subsystems - .FirstOrDefault(s => - s.Key == subsystemId); - } - - return subsystem; - } - - private async Task SendInitializedSubsystemInfoToUis() - { - var handlers = new List(); - - lock (UiClientsStore._uiClientLocker) - { - if (UiClientsStore._uiClients.Count > 0) - { - handlers.AddRange(UiClientsStore._uiClients); - } - } - - if (handlers.Count > 0) - { - await SendInfoToInitializedUIs(handlers); - } - } - - private async Task SendInfoToInitializedUIs(List handlers) - { - var subsystemCopy = new Dictionary(); - - lock (_subsystemLock) - { - if (_subsystems.Any()) - { - foreach (var subsystem in _subsystems) - { - subsystemCopy - .Add(subsystem.Key, subsystem.Value); - } - } - } - - if (subsystemCopy.Count > 0) - { - foreach (var uiHandler in handlers) - { - await uiHandler.AddSubsystems(subsystemCopy); - } - } - } - - private async Task SetState(Guid subsystemId, string state) - { - var subsystem = GetSubsystem(subsystemId); - - if (subsystem == null) return; - - lock (_subsystemLock) - { - if (subsystem.Value.Value.State != state) - { - subsystem.Value.Value.State = state; - } - } - - await UpdateInfoOnUI(handler => handler.UpdateSubsystemInfo(subsystemId, subsystem.Value.Value)); - } - - private async Task SetStates(IEnumerable> states) - { - foreach (var state in states) - { - await SetState(state.Key, state.Value); - } - } - - private Task UpdateInfoOnUI(Func handlerAction) - { - try - { - return Task.WhenAll(CreateCopyOfClients().Select(handlerAction)); - } - catch (Exception exception) - { - _logger.UiInformationCannotBeUpdatedError(exception); - return Task.CompletedTask; - } - } - - private IEnumerable CreateCopyOfClients() - { - lock (UiClientsStore._uiClientLocker) - { - return UiClientsStore._uiClients.ToArray(); - } - } - - private void UpdateOrAddElements(IEnumerable> subsystems) - { - lock (_subsystemLock) - { - foreach (var subsystem in subsystems) - { - var element = _subsystems - .FirstOrDefault(sub => - subsystem.Key == sub.Key); - - if (element.Value != null) - { - element.Value.Name = subsystem.Value.Name; - element.Value.Path = subsystem.Value.Path; - element.Value.State = subsystem.Value.State; - element.Value.Description = subsystem.Value.Description; - element.Value.AutomatedStart = subsystem.Value.AutomatedStart; - } - else - { - _subsystems.Add(subsystem); - } - } - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/User/MachineInfo.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/User/MachineInfo.cs deleted file mode 100644 index 53dd0eb0e..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/ProcessExplorer/User/MachineInfo.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Runtime.InteropServices; - -namespace ProcessExplorer.Processes.User; - -[System.Runtime.Versioning.SupportedOSPlatform("windows")] -public class MachineInfo -{ - public string? MachineName { get; internal set; } - public bool? IsUnix { get; internal set; } - public OperatingSystem? OSVersion { get; internal set; } - public bool? Is64BIOS { get; internal set; } - public bool? Is64BitProcess { get; internal set; } - public long? TotalRAM { get; internal set; } - public double? AvailableRAM { get; internal set; } - - public static MachineInfo FromMachine() - { - var Data = new MachineInfo(); - - Data.MachineName = Environment.MachineName; - Data.IsUnix = (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)); - Data.OSVersion = Environment.OSVersion; - Data.Is64BIOS = Environment.Is64BitOperatingSystem; - Data.Is64BitProcess = Environment.Is64BitProcess; - Data.TotalRAM = MachineInfo.GetTotalRAM(); - Data.AvailableRAM = MachineInfo.GetAvailableRAM(); - return Data; - } - - private static long GetTotalRAM() - { - long memKb; - GetPhysicallyInstalledSystemMemory(out memKb); - return memKb / 1024 /1024; - } - - private static double? GetAvailableRAM() - { - var performance = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes"); - var memory = performance.NextValue(); - - return Convert.ToDouble(memory) / 1024 ; - } - - [DllImport("kernel32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool GetPhysicallyInstalledSystemMemory(out long TotalMemoryInKilobytes); -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/IModuleLoaderInformationReceiver.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/IModuleLoaderInformationReceiver.cs deleted file mode 100644 index 232748a87..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/IModuleLoaderInformationReceiver.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using ProcessExplorer; -using ProcessExplorer.Subsystems; - -namespace SuperRPC_POC.Infrastructure; - -public interface IModuleLoaderInformationReceiver -{ - IProcessInfoAggregator? ProcessInfoAggregator { get; } - ISubsystemController SubsystemController { get; } - ValueTask SubscribeToProcessExplorerTopicAsync(); - ValueTask SubscribeToProcessExplorerChangedElementTopicAsync(); - ValueTask SubscribeToEnableProcessMonitorTopicAsync(); - ValueTask SubscribeToDisableProcessMonitorTopicAsync(); - ValueTask SetSubsystemLauncherCommunicator(ISubsystemLauncherCommunicator subsystemCommunicator); - ValueTask SubscribeToSubsystemsTopicAsync(); - ValueTask SubscribeToRuntimeInformationTopicAsync(); - ISubsystemLauncherCommunicator GetSubsystemLauncherCommunicator(); -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessInfoListRouterMessage.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessInfoListRouterMessage.cs deleted file mode 100644 index 2dbab9aed..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessInfoListRouterMessage.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Text.Json; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Processes; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer; - -namespace SuperRPC_POC.Infrastructure.Messages; - -public class ProcessInfoListRouterMessage : IObserver -{ - private readonly ILogger _logger; - private readonly IProcessInfoAggregator? _processInfoAggregator; - - public ProcessInfoListRouterMessage(ILogger? logger, IProcessInfoAggregator? processInfoAggregator) - { - _logger = logger ?? NullLogger.Instance; - _processInfoAggregator = processInfoAggregator ?? null; - } - - public void OnCompleted() - { - _logger.LogInformation("Received all of the information for the current message"); - } - - public void OnError(Exception exception) - { - _logger.LogError($"Some error(s) occurred while receiving the process information from module loader... : {exception}"); - } - - public void OnNext(TopicMessage value) - { - var payload = value.Payload; - if (payload == null) - { - return; - } - - var processInfo = JsonSerializer.Deserialize>(payload.GetString()); - - if (processInfo == null) - { - return; - } - - _processInfoAggregator?.InitProcesses(processInfo); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessInfoRouterMessage.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessInfoRouterMessage.cs deleted file mode 100644 index 07f4589a2..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessInfoRouterMessage.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Text.Json; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Processes; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer; - -namespace SuperRPC_POC.Infrastructure.Messages; - -public class ProcessInfoRouterMessage : IObserver -{ - private readonly ILogger _logger; - private readonly IProcessInfoAggregator? _processInfoAggregator; - - public ProcessInfoRouterMessage(ILogger? logger, - IProcessInfoAggregator? processInfoAggregator) - { - _logger = logger ?? NullLogger.Instance; - _processInfoAggregator = processInfoAggregator ?? null; - } - - public void OnCompleted() - { - _logger.LogInformation("Received all of the information for the current message"); - } - - public void OnError(Exception exception) - { - _logger.LogError($"Some error(s) occurred while receiving the process information from module loader... : {exception}"); - } - - public void OnNext(TopicMessage value) - { - var payload = value.Payload; - if (payload is null) - { - return; - } - - var processInfo = JsonSerializer.Deserialize(payload.GetString()); - - if (processInfo == null) - { - return; - } - - Thread.Sleep(5000); - _processInfoAggregator?.AddProcessInfo(processInfo); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessMonitorCheckerRouterMessage.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessMonitorCheckerRouterMessage.cs deleted file mode 100644 index 35693f7f8..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/ProcessMonitorCheckerRouterMessage.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using Microsoft.Extensions.Logging.Abstractions; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer; -using ProcessExplorerMessageRouterTopics; - -namespace SuperRPC_POC.Infrastructure.Messages; - -public class ProcessMonitorCheckerRouterMessage : IObserver -{ - private readonly ILogger _logger; - private readonly IProcessInfoAggregator? _processInfoAggregator; - - public ProcessMonitorCheckerRouterMessage(ILogger? logger, - IProcessInfoAggregator? processInfoAggregator) - { - _processInfoAggregator = processInfoAggregator ?? null; - _logger = logger ?? NullLogger.Instance; - } - - public void OnCompleted() - { - _logger.LogInformation("Received all of the information for the current message"); - } - - public void OnError(Exception exception) - { - _logger.LogError($"Some error(s) occurred while receiving the process monitor checker from module loader... : {exception}"); - } - - public void OnNext(TopicMessage value) - { - var topic = value.Topic; - - switch (topic) - { - case Topics.enableProcessWatcher: - _processInfoAggregator?.EnableWatchingSavedProcesses(); - break; - case Topics.disableProcessWatcher: - _processInfoAggregator?.DisableWatchingProcesses(); - break; - } - } -} - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/RuntimeInformationRouterMessage.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/RuntimeInformationRouterMessage.cs deleted file mode 100644 index dcb0eb485..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/RuntimeInformationRouterMessage.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Text.Json; -using LocalCollector; -using LocalCollector.Communicator; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using Microsoft.Extensions.Logging.Abstractions; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer; -using ProcessExplorerMessageRouterTopics; -using ConnectionInfo = LocalCollector.Connections.ConnectionInfo; - -namespace SuperRPC_POC.Infrastructure.Messages; - -public class RuntimeInformationRouterMessage : IObserver -{ - private readonly IProcessInfoAggregator _processInfoAggregator; - private readonly ILogger _logger; - - public RuntimeInformationRouterMessage(IProcessInfoAggregator processInfoAggregator, - ILogger? logger = null) - { - _processInfoAggregator = processInfoAggregator; - _logger = logger ?? NullLogger.Instance; - } - - public void OnCompleted() - { - _logger.LogInformation("Received all of the information for the current message"); - } - - public void OnError(Exception exception) - { - _logger.LogError($"Some error(s) occurred while receiving the process monitor checker from module loader... : {exception}"); - } - - public async void OnNext(TopicMessage value) - { - var topic = value.Topic; - var payload = value.Payload; - - if (payload is null) - { - return; - } - - switch (topic) - { - case Topics.addingConnections: - - var connections = JsonSerializer.Deserialize>>>(payload.GetString()); - - if (connections == null) - { - return; - } - - foreach (var connection in connections) - { - if (connection.Key == null) continue; - await _processInfoAggregator.AddConnectionCollection(connection.Key.Name, connection.Value); - } - - break; - - case Topics.updatingRuntime: - var runtimeInfo = JsonSerializer.Deserialize>>(payload.GetString()); - - if (runtimeInfo == null) - { - return; - } - - foreach (var runtime in runtimeInfo) - { - if (runtime.Key == null || runtime.Value == null) continue; - await _processInfoAggregator.AddInformation(runtime.Key.Name, runtime.Value); - } - - break; - - case Topics.updatingConnection: - var connectionUpdates = JsonSerializer.Deserialize>>(payload.GetString()); - - if (connectionUpdates == null) - { - return; - } - - foreach(var connectionUpdate in connectionUpdates) - { - if(connectionUpdate.Key == null || connectionUpdate.Value == null) continue; - await _processInfoAggregator.UpdateConnectionInfo(connectionUpdate.Key.Name, connectionUpdate.Value); - } - - break; - - case Topics.updatingEnvironmentVariables: - var envs = JsonSerializer.Deserialize>>>>(payload.GetString()); - - if (envs == null) - { - return; - } - - foreach(var env in envs) - { - if(env.Key == null || env.Value == null) continue; - await _processInfoAggregator.UpdateEnvironmentVariablesInfo(env.Key.Name, env.Value); - } - - break; - - case Topics.updatingModules: - var modules = JsonSerializer.Deserialize>>>(payload.GetString()); - - if (modules == null) - { - return; - } - - foreach( var module in modules) - { - if(module.Key == null || module.Value == null) continue; - await _processInfoAggregator.UpdateModuleInfo(module.Key.Name, module.Value); - } - break; - - case Topics.updatingRegistrations: - var registrations = JsonSerializer.Deserialize>>>(payload.GetString()); - - if (registrations == null) - { - return; - } - - foreach(var registration in registrations) - { - if(registration.Key == null || registration.Value == null) continue; - await _processInfoAggregator.UpdateRegistrationInfo(registration.Key.Name, registration.Value); - } - break; - } - - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/SubsystemRouterMessage.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/SubsystemRouterMessage.cs deleted file mode 100644 index ba2696e45..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/Messages/SubsystemRouterMessage.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Text.Json; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Subsystems; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer.Subsystems; -using ProcessExplorerMessageRouterTopics; - -namespace SuperRPC_POC.Infrastructure.Messages; - -public class SubsystemRouterMessage : IObserver -{ - private readonly ILogger _logger; - private ISubsystemController? _subsystemController; - - public SubsystemRouterMessage(ILogger? logger) - { - _logger = logger ?? NullLogger.Instance; - } - - public void SetSubsystemController(ISubsystemController subsystemController) - { - _subsystemController = subsystemController; - } - - public void OnCompleted() - { - _logger.LogInformation("Received all of the information for the current message"); - } - - public void OnError(Exception exception) - { - _logger.LogError( - $"Some error(s) occurred while receiving the process information from module loader... : {exception}"); - } - - public void OnNext(TopicMessage value) - { - var topic = value.Topic; - var payload = value.Payload; - - if (payload is null) - { - return; - } - - switch (topic) - { - case Topics.initilaizingSubsystems: - - var initSubsystems = JsonSerializer.Deserialize>(payload.GetString()); - - if (initSubsystems == null) - { - return; - } - - _subsystemController.InitializeSubsystems(initSubsystems); - - break; - - case Topics.addingSubsystem: - var addSubsystem = JsonSerializer.Deserialize>(payload.GetString()); - - if (addSubsystem.Key == null) - { - return; - } - - _subsystemController.AddSubsystem(addSubsystem.Key, addSubsystem.Value); - - break; - - case Topics.modifyingSubsystem: - var modifySubsystem = JsonSerializer.Deserialize>(payload.GetString()); - - if (modifySubsystem.Key == null) - { - return; - } - - _subsystemController.ModifySubsystemState(modifySubsystem.Key, modifySubsystem.Value); - - break; - - case Topics.removingSubsystem: - var subsystemId = JsonSerializer.Deserialize(payload.GetString()); - - if (subsystemId == null) - { - return; - } - - _subsystemController.RemoveSubsystem(subsystemId); - - break; - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/ModuleLoaderInformationReceiver.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/ModuleLoaderInformationReceiver.cs deleted file mode 100644 index c583ccf2a..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/ModuleLoaderInformationReceiver.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Diagnostics; -using System.Reflection; -using Microsoft.Extensions.Logging.Abstractions; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer; -using ProcessExplorer.Extensions; -using ProcessExplorer.Subsystems; -using ProcessExplorerMessageRouterTopics; -using SuperRPC_POC.Infrastructure.Messages; - -namespace SuperRPC_POC.Infrastructure; - -public class ModuleLoaderInformationReceiver : IModuleLoaderInformationReceiver -{ - private readonly ILogger _logger; - private readonly IMessageRouter _messageRouter; - private readonly IObserver _processInfoListMessage; - private readonly IObserver _processInfoMessage; - private readonly IObserver _processMonitorWatcherChecker; - private readonly IObserver _runtimeObserver; - public IProcessInfoAggregator? ProcessInfoAggregator { get; } - private readonly ISubsystemController _subsystemController; - private ISubsystemLauncherCommunicator _subsystemLauncherCommunicator; - - public ISubsystemController SubsystemController - { - get - { - return _subsystemController; - } - } - - public ModuleLoaderInformationReceiver(IProcessInfoAggregator aggregator, - IMessageRouter messageRouter, - ILoggerFactory loggerFactory, - ProcessInfoListRouterMessage processInfoListMessage, - ProcessInfoRouterMessage processInfoMessage, - ProcessMonitorCheckerRouterMessage processMonitorCheckerRouterMessage, - RuntimeInformationRouterMessage runtimeInformationRouterMessage, - ILogger? logger) - { - _logger = logger ?? NullLogger.Instance; - _messageRouter = messageRouter; - ProcessInfoAggregator = aggregator; - _processInfoListMessage = processInfoListMessage; - _processInfoMessage = processInfoMessage; - _processMonitorWatcherChecker = processMonitorCheckerRouterMessage; - _runtimeObserver = runtimeInformationRouterMessage; - - //Subsystems Set-Up - var subsystemsRouterMessage = new SubsystemRouterMessage(loggerFactory.CreateLogger()); - - _subsystemLauncherCommunicator - = new SubsystemLauncherCommunicator(loggerFactory.CreateLogger(), - messageRouter, - subsystemsRouterMessage); - - _subsystemController - = SubsystemFactory.CreateSubsystemController(_subsystemLauncherCommunicator, - loggerFactory.CreateLogger()); - - subsystemsRouterMessage.SetSubsystemController(_subsystemController); - - //if you do not want to start the frontend of the PE comment out this code. - StartFrontend(); - } - - public async ValueTask SubscribeToProcessExplorerChangedElementTopicAsync() - { - _logger.LogInformation($"Subscribing to topic {Topics.changedProcessInfo} to receive information from moduleLoader"); - - try - { - await _messageRouter.SubscribeAsync(Topics.changedProcessInfo, _processInfoMessage); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while subscribing to topic: process_explorer : {exception}"); - } - } - - public async ValueTask SubscribeToEnableProcessMonitorTopicAsync() - { - _logger.LogInformation($"Subscribing to topic {Topics.enableProcessWatcher} to receive information from moduleLoader"); - - try - { - await _messageRouter.SubscribeAsync(Topics.enableProcessWatcher, _processMonitorWatcherChecker); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while subscribing to topic: {Topics.enableProcessWatcher} : {exception}"); - } - - } - - public async ValueTask SubscribeToDisableProcessMonitorTopicAsync() - { - _logger.LogInformation($"Subscribing to topic {Topics.disableProcessWatcher} to receive information from moduleLoader"); - - try - { - await _messageRouter.SubscribeAsync(Topics.disableProcessWatcher, _processMonitorWatcherChecker); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while subscribing to topic: {Topics.disableProcessWatcher} : {exception}"); - } - } - - public async ValueTask SetSubsystemLauncherCommunicator(ISubsystemLauncherCommunicator subsystemCommunicator) - { - _subsystemLauncherCommunicator = subsystemCommunicator; - await _subsystemLauncherCommunicator.InitializeCommunicationRoute(); - } - - public async ValueTask SubscribeToSubsystemsTopicAsync() - { - await _subsystemLauncherCommunicator.InitializeCommunicationRoute(); - } - - public ISubsystemLauncherCommunicator GetSubsystemLauncherCommunicator() - { - if (_subsystemLauncherCommunicator == null) - throw new ArgumentNullException(nameof(_subsystemLauncherCommunicator)); - return _subsystemLauncherCommunicator; - } - - public async ValueTask SubscribeToProcessExplorerTopicAsync() - { - _logger.LogInformation($"Subscribing to topic {Topics.watchingProcessChanges} to receive information from moduleLoader"); - - try - { - await _messageRouter.SubscribeAsync(Topics.watchingProcessChanges, _processInfoListMessage); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while subscribing to topic: {Topics.watchingProcessChanges} : {exception}"); - } - } - - public async ValueTask SubscribeToRuntimeInformationTopicAsync() - { - try - { - if (_messageRouter != null) - { - await _messageRouter.SubscribeAsync(Topics.addingConnections, _runtimeObserver); - await _messageRouter.SubscribeAsync(Topics.updatingRuntime, _runtimeObserver); - await _messageRouter.SubscribeAsync(Topics.updatingConnection, _runtimeObserver); - await _messageRouter.SubscribeAsync(Topics.updatingEnvironmentVariables, _runtimeObserver); - await _messageRouter.SubscribeAsync(Topics.updatingModules, _runtimeObserver); - await _messageRouter.SubscribeAsync(Topics.updatingRegistrations, _runtimeObserver); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing... {exception}"); - } - } - - private void StartFrontend() - { - var ps1FilePath = $@"{Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location)}\scripts\npm-frontend-start.ps1"; - var processStartInfo = new ProcessStartInfo() - { - FileName = "powershell.exe", - Arguments = $"-File \"{ps1FilePath}\"", - UseShellExecute = true, - }; - - Process.Start(processStartInfo); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/SubsystemLauncherCommunicator.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/SubsystemLauncherCommunicator.cs deleted file mode 100644 index 99822d1f9..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/SubsystemLauncherCommunicator.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Text.Json; -using Microsoft.Extensions.Logging.Abstractions; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorer.Subsystems; -using ProcessExplorerMessageRouterTopics; -using SuperRPC_POC.Infrastructure.Messages; - -namespace SuperRPC_POC.Infrastructure; - -public class SubsystemLauncherCommunicator : ISubsystemLauncherCommunicator -{ - private readonly ILogger _logger; - private readonly IMessageRouter? _messageRouter; - private readonly IObserver _subsystemsObserver; - - public SubsystemLauncherCommunicator(ILogger? logger, - IMessageRouter? messageRouter, - SubsystemRouterMessage subsystemsObserver) - { - _logger = logger ?? NullLogger.Instance; - _messageRouter = messageRouter; - _subsystemsObserver = subsystemsObserver; - } - - public async ValueTask InitializeCommunicationRoute() - { - _logger.LogInformation($"Getting the collection of subsystems to Process Explorer to show on the UI."); - try - { - if (_messageRouter != null) - { - await _messageRouter.SubscribeAsync(Topics.initilaizingSubsystems, _subsystemsObserver); - await _messageRouter.SubscribeAsync(Topics.addingSubsystem, _subsystemsObserver); - await _messageRouter.SubscribeAsync(Topics.modifyingSubsystem, _subsystemsObserver); - await _messageRouter.SubscribeAsync(Topics.removingSubsystem, _subsystemsObserver); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing... {exception}"); - } - } - - public async ValueTask SendLaunchSubsystemAfterTimeRequest(Guid subsystemId, int periodOfTime) - { - _logger.LogInformation($"Publishing launch after time request to SubsystemControllerCommunicator to handle subsystems..."); - - try - { - if (_messageRouter != null) - { - var serializableSubsystem = new KeyValuePair(subsystemId, periodOfTime); - await _messageRouter.PublishAsync(Topics.launchingSubsystemWithDelay, JsonSerializer.Serialize(serializableSubsystem)); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.launchingSubsystemWithDelay}... {exception}"); - } - } - - public async ValueTask SendLaunchSubsystemsRequest(IEnumerable subsystems) - { - _logger.LogInformation($"Publishing launch request to SubsystemControllerCommunicator to handle subsystems..."); - - try - { - if (_messageRouter != null) - { - await _messageRouter.PublishAsync(Topics.launchingSubsystems, JsonSerializer.Serialize(subsystems)); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.launchingSubsystems}... {exception}"); - } - } - - public async ValueTask SendRestartSubsystemsRequest(IEnumerable subsystems) - { - _logger.LogInformation($"Publishing restart request to SubsystemControllerCommunicator to handle subsystems..."); - - try - { - if (_messageRouter != null) - { - await _messageRouter.PublishAsync(Topics.restartingSubsystems, JsonSerializer.Serialize(subsystems)); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.restartingSubsystems}... {exception}"); - } - } - - public async ValueTask SendShutdownSubsystemsRequest(IEnumerable subsystems) - { - _logger.LogInformation($"Publishing stop request to SubsystemControllerCommunicator to handle subsystems..."); - - try - { - if (_messageRouter != null) - { - await _messageRouter.PublishAsync(Topics.terminatingSubsystems, JsonSerializer.Serialize(subsystems)); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.terminatingSubsystems}... {exception}"); - } - } -} - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/UIHandler.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/UIHandler.cs deleted file mode 100644 index cbb6ea330..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Infrastructure/UIHandler.cs +++ /dev/null @@ -1,226 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using LocalCollector; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Processes; -using ModuleProcessMonitor.Subsystems; -using ProcessExplorer.Infrastructure; -using Super.RPC; -using SuperRPC_POC.Protocol.ProxyObjects; -using ConnectionInfo = LocalCollector.Connections.ConnectionInfo; - -namespace SuperRPC_POC.ClientBehavior; - -public class UIHandler : IUIHandler -{ - private SuperRPC? rpc; - private IProcessAggregatorUIServiceObject? processServiceProxy; - private ISubsystemServiceObject? subsystemServiceObject; - private readonly ILogger logger; - - public UIHandler(ILogger? logger = null) - { - this.logger = logger ?? NullLogger.Instance; - } - - public async Task InitSuperRPCForProcessAsync(SuperRPC superRpc) - { - this.rpc = superRpc; - await rpc.RequestRemoteDescriptors(); - processServiceProxy = rpc.GetProxyObject("ServiceProcessObject"); - } - - public async Task InitSuperRPCForSubsystemAsync(SuperRPC superRpc) - { - this.rpc = superRpc; - await rpc.RequestRemoteDescriptors(); - subsystemServiceObject = rpc.GetProxyObject("SubsystemServiceObject"); - } - - public async Task AddProcesses(IEnumerable? processes) - { - try - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.AddProcesses(processes); - } - catch (Exception exception) - { - logger.LogError(exception.Message); - } - } - - public async Task AddProcess(ProcessInfoData process) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.AddProcess(process); - } - - public async Task UpdateProcess(ProcessInfoData process) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.UpdateProcess(process); - } - - public async Task RemoveProcess(int pid) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.TerminateProcess(pid); - } - - public async Task AddRuntimeInfo(string assemblyId, ProcessInfoCollectorData dataObject) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.AddRuntimeInfo(assemblyId, dataObject); - } - - public async Task AddConnections(string assemblyId, IEnumerable connections) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.AddConnections(assemblyId, connections); - } - - public async Task AddConnection(string assemblyId, ConnectionInfo connection) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.AddConnection(assemblyId, connection); - } - - public async Task UpdateConnection(string assemblyId, ConnectionInfo connection) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.UpdateConnection(assemblyId, connection); - } - - public async Task UpdateEnvironmentVariables(string assemblyId, IEnumerable> environmentVariables) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.UpdateEnvironmentVariables(assemblyId, environmentVariables); - } - - public async Task UpdateRegistrations(string assemblyId, IEnumerable registrations) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.UpdateRegistrations(assemblyId, registrations); - } - - public async Task UpdateModules(string assemblyId, IEnumerable modules) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.UpdateModules(assemblyId, modules); - } - - public async Task AddRuntimeInfo(IEnumerable> runtimeInfos) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.AddRuntimeInfos(runtimeInfos); - } - - public async Task RemoveProcessByID(int pid) - { - if (processServiceProxy == null) - { - return; - } - await processServiceProxy.TerminateProcess(pid); - } - - - //subsystemPart - public async Task UpdateSubsystemInfo(Guid subsystemId, SubsystemInfo subsystem) - { - if (subsystemServiceObject == null) - { - return; - } - await subsystemServiceObject.UpdateSubsystemInfoAsync(subsystemId.ToString(), subsystem); - } - - public async Task AddSubsystems(IEnumerable> subsystems) - { - if (subsystemServiceObject == null) - { - return; - } - - var subsystemsWithStringIds = new Dictionary(); - - if (subsystems.Any()) - { - foreach (var subsystem in subsystems) - { - subsystemsWithStringIds.Add(subsystem.Key.ToString(), subsystem.Value); - } - } - - await subsystemServiceObject.AddSubsystemsAsync(subsystemsWithStringIds); - } - - public async Task AddSubsystem(Guid subsystemId, SubsystemInfo subsystem) - { - if (subsystemServiceObject == null) - { - return; - } - - await subsystemServiceObject.AddSubsystemAsync(subsystemId.ToString(), subsystem); - } - - public async Task RemoveSubsystem(Guid subsystemId) - { - if (subsystemServiceObject == null) - { - return; - } - - await subsystemServiceObject.RemoveSubsystemAsync(subsystemId.ToString()); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/MiddlewareV2.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/MiddlewareV2.cs deleted file mode 100644 index 9388572f5..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/MiddlewareV2.cs +++ /dev/null @@ -1,205 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Net; -using System.Net.WebSockets; -using LocalCollector.Communicator; -using ProcessExplorer.Factories; -using Super.RPC; -using SuperRPC_POC.ClientBehavior; -using SuperRPC_POC.Infrastructure; - -namespace SuperRPC_POC; - -public class SuperRpcWebSocketMiddlewareV2 -{ - private readonly RequestDelegate _next; - private readonly IModuleLoaderInformationReceiver _collector; - - public SuperRpcWebSocketMiddlewareV2(RequestDelegate next, IModuleLoaderInformationReceiver collector) - { - _next = next; - _collector = collector; - - //fire - and - forget - _collector.SubscribeToProcessExplorerTopicAsync(); - _collector.SubscribeToProcessExplorerChangedElementTopicAsync(); - _collector.SubscribeToEnableProcessMonitorTopicAsync(); - _collector.SubscribeToDisableProcessMonitorTopicAsync(); - _collector.SubscribeToSubsystemsTopicAsync(); - _collector.SubscribeToRuntimeInformationTopicAsync(); - } - - private SuperRPC SetupRpc(RPCReceiveChannel channel, ICommunicator? communicator) - { - var rpc = new SuperRPC(() => Guid.NewGuid().ToString("N")); - SuperRPCWebSocket.RegisterCustomDeserializer(rpc); - rpc.Connect(channel); - - if (communicator != null) - { - rpc.RegisterHostObject("communicator", communicator, new ObjectDescriptor - { - Functions = new FunctionDescriptor[] { - "AddRuntimeInfo", - "AddRuntimeInfos", - "AddConnectionCollection", - "UpdateConnectionInformation", - "UpdateEnvironmentVariableInformation", - "UpdateRegistrationInformation", - "UpdateModuleInformation", - "TerminateProcess" } - }); - } - - if (_collector.ProcessInfoAggregator != null) - { - rpc.RegisterHostObject("processController", _collector.ProcessInfoAggregator, new ObjectDescriptor - { - Functions = new FunctionDescriptor[] { "RemoveProcessById" } - }); - } - - if (_collector.SubsystemController != null) - { //Subsystems handler on UI: - rpc.RegisterHostObject("subsystemController", _collector.SubsystemController, new ObjectDescriptor - { - Functions = new FunctionDescriptor[] { - "LaunchSubsystem", - "LaunchSubsystems", - "RestartSubsystem", - "RestartSubsystems", - "ShutdownSubsystem", - "ShutdownSubsystems" } - }); - } - - return rpc; - } - - private SuperRPC SetupRpc(RPCReceiveChannel channel) - { - var rpc = new SuperRPC(() => Guid.NewGuid().ToString("N")); - SuperRPCWebSocket.RegisterCustomDeserializer(rpc); - rpc.Connect(channel); - return rpc; - } - - public async Task InvokeAsync(HttpContext context) - { - if (context.Request.Path == "/processes") - { - if (context.WebSockets.IsWebSocketRequest) - { - using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); - - // set behavior of the infocollector's changes - ICommunicator? communicator = null; - - // set implementation of ui notifications - var uiHandler = new UIHandler(); - - - if (_collector.ProcessInfoAggregator != null) - { - communicator = ProcessAggregatorFactory.CreateCommunicator(_collector.ProcessInfoAggregator); - } - - var rpcWebSocketHandler = SuperRPCWebSocket.CreateHandler(webSocket); - - // registering proxy objects, what we are using - var rpc = SetupRpc(rpcWebSocketHandler.ReceiveChannel, communicator); - - // after we get those objects what we want to use then we should add this ui handler to the collection because the relationship can be 1:N - if (_collector.ProcessInfoAggregator != null) - { - uiHandler.InitSuperRPCForProcessAsync(rpc) - .ContinueWith(_ => _collector.ProcessInfoAggregator.AddUiConnection(uiHandler)); - - await rpcWebSocketHandler.StartReceivingAsync(_collector.ProcessInfoAggregator, uiHandler); - } - else - { - await rpcWebSocketHandler.StartReceivingAsync(uiHandler: uiHandler); - } - } - else - { - context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - return; - } - - // another endpoint --- same functionality with infocollector as infoaggregator - if (context.Request.Path == "/subsystems") - { - if (context.WebSockets.IsWebSocketRequest) - { - using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); - var rpcWebSocketHandler = SuperRPCWebSocket.CreateHandler(webSocket); - - var rpc = SetupRpc(rpcWebSocketHandler.ReceiveChannel, null); - - var uiHandler = new UIHandler(); - - if (_collector.ProcessInfoAggregator != null) - { - uiHandler.InitSuperRPCForSubsystemAsync(rpc) - .ContinueWith(_ => _collector.SubsystemController.AddUIConnection(uiHandler)); - - await rpcWebSocketHandler.StartReceivingAsync(_collector.ProcessInfoAggregator, uiHandler); - } - } - else - { - context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - return; - } - - if (context.Request.Path == "/collector-rpc") - { - if (context.WebSockets.IsWebSocketRequest) - { - using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); - ICommunicator? collectorHandler = null; - - if (_collector.ProcessInfoAggregator != null) - { - collectorHandler = ProcessAggregatorFactory.CreateCommunicator(_collector.ProcessInfoAggregator); - } - - var rpcWebSocketHandler = SuperRPCWebSocket.CreateHandler(webSocket); - var rpc = SetupRpc(rpcWebSocketHandler.ReceiveChannel, collectorHandler); - await rpcWebSocketHandler.StartReceivingAsync(); - } - else - { - context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - return; - } - - if(context.Request.Path == "/module-loader-init") - { - if (context.WebSockets.IsWebSocketRequest) - { - using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); - var rpcWebSocketHandler = SuperRPCWebSocket.CreateHandler(webSocket); - var rpc = SetupRpc(rpcWebSocketHandler.ReceiveChannel); - await rpcWebSocketHandler.StartReceivingAsync(); - } - } - - await _next(context); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Properties/launchSettings.json b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Properties/launchSettings.json deleted file mode 100644 index a7fe007ff..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Properties/launchSettings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:13840", - "sslPort": 44319 - } - }, - "profiles": { - "SuperRPC_POC": { - "commandName": "Project", - "dotnetRunMessages": true, - "applicationUrl": "https://localhost:7059;http://localhost:5059", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/ProxyObjects/IProcessAggregatorUIServiceObject.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/ProxyObjects/IProcessAggregatorUIServiceObject.cs deleted file mode 100644 index 3122e608e..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/ProxyObjects/IProcessAggregatorUIServiceObject.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using LocalCollector; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using ModuleProcessMonitor.Processes; -using ConnectionInfo = LocalCollector.Connections.ConnectionInfo; - -namespace SuperRPC_POC.Protocol.ProxyObjects; - -public interface IProcessAggregatorUIServiceObject -{ - Task AddRuntimeInfo(string assemblyId, ProcessInfoCollectorData dataObject); - Task AddRuntimeInfos(IEnumerable> runtimeInfos); - Task AddConnections(string assemblyId, IEnumerable connections); - Task AddConnection(string assemblyId, ConnectionInfo connection); - Task UpdateConnection(string assemblyId, ConnectionInfo connection); - Task UpdateEnvironmentVariables(string assemblyId, IEnumerable> environmentVariables); - Task UpdateRegistrations(string assemblyId, IEnumerable registrations); - Task UpdateModules(string assemblyId, IEnumerable modules); - Task AddProcesses(IEnumerable? processes); - Task AddProcess(ProcessInfoData process); - Task UpdateProcess(ProcessInfoData process); - Task TerminateProcess(int pid); -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/object-id-dictionary.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/object-id-dictionary.cs deleted file mode 100644 index 7b0f89cad..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/object-id-dictionary.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; -namespace Super.RPC; - -public class ObjectIdDictionary - where TKeyId : notnull - where TKeyObj : notnull -{ - public record Entry(TKeyId id, TKeyObj obj, TValue value); - - public ConcurrentDictionary ById = new ConcurrentDictionary(); - public ConcurrentDictionary ByObj = new ConcurrentDictionary(); - - public void Add(TKeyId id, TKeyObj obj, TValue value) - { - lock (ById) - { - var entry = new Entry(id, obj, value); - ById[id] = entry; - ByObj[obj] = entry; - } - } - - public void RemoveById(TKeyId id) - { - lock (ById) if (ById.Remove(id, out var entry)) - { - ByObj.Remove(entry.obj, out var entry2); - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/proxy-object-registry.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/proxy-object-registry.cs deleted file mode 100644 index 6a4dcc314..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/proxy-object-registry.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Collections.Generic; -using System.Runtime; - -namespace Super.RPC; - -public class ProxyObjectRegistry -{ - - // https://www.nimaara.com/per-object-garbage-collection-notification-in-net/ - private sealed record NotifyWhenDisposed(Action disposed) - { - ~NotifyWhenDisposed() { disposed(); } - } - - private readonly Dictionary byId = new Dictionary(); - private readonly ConditionalWeakTable byObj = new ConditionalWeakTable(); - - public void Register(string objId, object obj, Action? dispose = null) - { - lock (byId) - { - byId.Add(objId, new DependentHandle(obj, new NotifyWhenDisposed(() => { - byId.Remove(objId); - dispose?.Invoke(); - }))); - byObj.Add(obj, objId); - } - } - - public string? GetId(object obj) - { - lock (byId) return byObj.TryGetValue(obj, out var objId) ? objId : null; - } - - public object? Get(string objId) - { - lock (byId) - { - if (byId.TryGetValue(objId, out var handle)) - { - var obj = handle.Target; - if (obj is not null) - { - return obj; - } - else - { - byId.Remove(objId); - } - } - return null; - } - } - -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-channel.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-channel.cs deleted file mode 100644 index 079d393c2..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-channel.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -namespace Super.RPC; - -public interface IRPCChannel { } -public interface IRPCSendSyncChannel : IRPCChannel -{ - /** - * Sends a message and returns the response synchronously. - */ - object? SendSync(RPC_Message message); -} - -public interface IRPCSendAsyncChannel : IRPCChannel -{ - /** - * Sends a message asnychronously. The response will come via the `receive` callback function. - */ - void SendAsync(RPC_Message message); -} - -public record MessageReceivedEventArgs(RPC_Message message, IRPCChannel? replyChannel = null, object? context = null); - -public interface IRPCReceiveChannel : IRPCChannel -{ - /** - * Event for when an async message arrives. - */ - event EventHandler MessageReceived; -} - -/*** Helper implementations ***/ -public record RPCSendAsyncChannel(Action sendAsync) : IRPCSendAsyncChannel -{ - public void SendAsync(RPC_Message message) - { - sendAsync(message); - } -} - -public record RPCReceiveChannel : IRPCReceiveChannel -{ - public event EventHandler? MessageReceived; - - public void Received(RPC_Message message, IRPCChannel? replyChannel = null, object? context = null, object? sender = null) - { - MessageReceived?.Invoke(sender ?? this, new MessageReceivedEventArgs(message, replyChannel, context)); - } -} - -public record RPCSendAsyncAndReceiveChannel(Action sendAsync) : RPCReceiveChannel, IRPCSendAsyncChannel -{ - public void SendAsync(RPC_Message message) - { - sendAsync(message); - } -} - -public record RPCSendSyncAndReceiveChannel(Func sendSync) : RPCReceiveChannel, IRPCSendSyncChannel -{ - public object? SendSync(RPC_Message message) - { - return sendSync(message); - } -} - -public record RPCSendSyncAsyncReceiveChannel(Func sendSync, Action sendAsync) : RPCSendAsyncAndReceiveChannel(sendAsync), IRPCSendSyncChannel -{ - public object? SendSync(RPC_Message message) - { - return sendSync(message); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-descriptor-types.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-descriptor-types.cs deleted file mode 100644 index 88ec39921..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-descriptor-types.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Runtime.Serialization; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - - -namespace Super.RPC; - -[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] -public enum FunctionReturnBehavior -{ - [EnumMember(Value = "void")] - Void, - [EnumMember(Value = "sync")] - Sync, - [EnumMember(Value = "async")] - Async -} - -public abstract record Descriptor(string type); - -public record FunctionDescriptor() : Descriptor("function") -{ - [JsonProperty("name")] - public string? Name; - - [JsonProperty("arguments", NullValueHandling = NullValueHandling.Ignore)] - public ArgumentDescriptor[]? Arguments; - - [JsonProperty("returns", NullValueHandling = NullValueHandling.Ignore)] - public FunctionReturnBehavior Returns = FunctionReturnBehavior.Async; - - public static implicit operator FunctionDescriptor(string name) => new FunctionDescriptor { Name = name }; -} - -public record PropertyDescriptor() : Descriptor("property") -{ - [JsonProperty("name")] - public string? Name; - - [JsonProperty("get", NullValueHandling = NullValueHandling.Ignore)] - public FunctionDescriptor? Get; - - [JsonProperty("set", NullValueHandling = NullValueHandling.Ignore)] - public FunctionDescriptor? Set; - - [JsonProperty("getOnly", NullValueHandling = NullValueHandling.Ignore)] - public bool? GetOnly; - - public static implicit operator PropertyDescriptor(string name) => new PropertyDescriptor { Name = name }; -} - -public record ArgumentDescriptor : FunctionDescriptor // TODO: Func or Object ? deserialize? -{ - public int? idx; -} - -public record ObjectDescriptor() : Descriptor("object") -{ - [JsonProperty("functions", NullValueHandling = NullValueHandling.Ignore)] - public FunctionDescriptor[]? Functions; - - [JsonProperty("proxiedProperties", NullValueHandling = NullValueHandling.Ignore)] - public PropertyDescriptor[]? ProxiedProperties; - - [JsonProperty("readonlyProperties", NullValueHandling = NullValueHandling.Ignore)] - public string[]? ReadonlyProperties; - - [JsonProperty("events", NullValueHandling = NullValueHandling.Ignore)] - public FunctionDescriptor[]? Events; - -} - -public record ObjectDescriptorWithProps : ObjectDescriptor -{ - [JsonProperty("props")] - public Dictionary? Props; - - public static ObjectDescriptorWithProps From(ObjectDescriptor other, Dictionary props) - { - return new ObjectDescriptorWithProps - { - Functions = other.Functions, - ReadonlyProperties = other.ReadonlyProperties, - ProxiedProperties = other.ProxiedProperties, - Events = other.Events, - Props = props - }; - } -} - -public record ClassDescriptor() : Descriptor("class") -{ - [JsonProperty("classId")] - public string? ClassId; - - [JsonProperty("ctor", NullValueHandling = NullValueHandling.Ignore)] - public FunctionDescriptor? Ctor; - - [JsonProperty("static", NullValueHandling = NullValueHandling.Ignore)] - public ObjectDescriptor? Static; - - [JsonProperty("instance", NullValueHandling = NullValueHandling.Ignore)] - public ObjectDescriptor? Instance; -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-message-types.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-message-types.cs deleted file mode 100644 index 5b2495c5e..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/rpc-message-types.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; - -using ObjectDescriptors = System.Collections.Generic.Dictionary; -using FunctionDescriptors = System.Collections.Generic.Dictionary; -using ClassDescriptors = System.Collections.Generic.Dictionary; - -namespace Super.RPC; - -public abstract record RPC_Message -{ - public string rpc_marker = "srpc"; - public string? action; - - public static readonly Dictionary MessageTypesByAction = new Dictionary - { - ["get_descriptors"] = typeof(RPC_GetDescriptorsMessage), - ["descriptors"] = typeof(RPC_DescriptorsResultMessage), - ["prop_get"] = typeof(RPC_PropGetMessage), - ["prop_set"] = typeof(RPC_PropSetMessage), - ["ctor_call"] = typeof(RPC_CtorCallMessage), - ["fn_call"] = typeof(RPC_FnCallMessage), - ["method_call"] = typeof(RPC_RpcCallMessage), - ["obj_died"] = typeof(RPC_ObjectDiedMessage), - ["fn_reply"] = typeof(RPC_FnResultMessageBase), - }; -} - -public record RPC_GetDescriptorsMessage : RPC_Message -{ - public RPC_GetDescriptorsMessage() { action = "get_descriptors"; } -} - -public record RPC_DescriptorsResultMessage : RPC_Message -{ - public RPC_DescriptorsResultMessage() { action = "descriptors"; } - public ObjectDescriptors? objects; - public FunctionDescriptors? functions; - public ClassDescriptors? classes; -} - -public record RPC_FnCallMessageBase : RPC_Message -{ - public string objId; - public object?[] args; -} - -public record RPC_AnyCallTypeFnCallMessage : RPC_FnCallMessageBase -{ - public FunctionReturnBehavior callType; - public string? callId; - // this should be in *some* of the derived records - public string? prop; -} - - -public record RPC_FnCallMessage : RPC_AnyCallTypeFnCallMessage -{ - public RPC_FnCallMessage() { action = "fn_call"; } -} -public record RPC_CtorCallMessage : RPC_AnyCallTypeFnCallMessage -{ - public RPC_CtorCallMessage() { action = "ctor_call"; } -} -public record RPC_PropGetMessage : RPC_AnyCallTypeFnCallMessage -{ - public RPC_PropGetMessage() { action = "prop_get"; } -} -public record RPC_PropSetMessage : RPC_AnyCallTypeFnCallMessage -{ - public RPC_PropSetMessage() { action = "prop_set"; } -} -public record RPC_RpcCallMessage : RPC_AnyCallTypeFnCallMessage -{ - public RPC_RpcCallMessage() { action = "method_call"; } -} - -public record RPC_FnResultMessageBase : RPC_Message -{ - public RPC_FnResultMessageBase() { action = "fn_reply"; } - public bool success; - public object? result; - public string? callId; - public FunctionReturnBehavior callType; -} -public record RPC_SyncFnResultMessage : RPC_FnResultMessageBase -{ - public RPC_SyncFnResultMessage() { callType = FunctionReturnBehavior.Sync; } -} -public record RPC_AsyncFnResultMessage : RPC_FnResultMessageBase -{ - public RPC_AsyncFnResultMessage() { callType = FunctionReturnBehavior.Async; } -} - -public record RPC_ObjectDiedMessage : RPC_Message -{ - public RPC_ObjectDiedMessage() { action = "obj_died"; } - public string objId; -} -public record RPC_AsyncCallbackCallMessage : RPC_FnCallMessageBase -{ - public RPC_AsyncCallbackCallMessage() { action = "async_fn"; } -} - -public record RPC_BaseObj(string objId, string _rpc_type); -public record RPC_Object(string objId, string _rpc_type, Dictionary? props, string? classId = null) : RPC_BaseObj(objId, _rpc_type); diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/super-rpc.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/super-rpc.cs deleted file mode 100644 index d50834a76..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Protocol/Super-RPC/super-rpc.cs +++ /dev/null @@ -1,1518 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -using ObjectDescriptors = System.Collections.Generic.Dictionary; -using FunctionDescriptors = System.Collections.Generic.Dictionary; -using ClassDescriptors = System.Collections.Generic.Dictionary; -using System.Diagnostics; - -namespace Super.RPC; - -record AsyncCallbackEntry(Task task, Action complete, Action fail, Type? type); -public record CallContext(IRPCChannel replyChannel, object? data = null) -{ - public TaskCompletionSource? replySent; -} - -public class SuperRPC -{ - private AsyncLocal _currentContextAsyncLocal = new AsyncLocal(); - public CallContext? CurrentContext - { - get => _currentContextAsyncLocal.Value; - private set => _currentContextAsyncLocal.Value = value; - } - - protected readonly Func ObjectIDGenerator; - protected IRPCChannel? Channel; - - private ObjectDescriptors? remoteObjectDescriptors; - private FunctionDescriptors? remoteFunctionDescriptors; - private ClassDescriptors? remoteClassDescriptors; - private TaskCompletionSource? remoteDescriptorsReceived = null; - - private readonly Dictionary asyncCallbacks = new Dictionary(); - private readonly Dictionary asyncCallbackValues = new Dictionary(); - private volatile int callId = 0; - - private readonly ProxyObjectRegistry proxyObjectRegistry = new ProxyObjectRegistry(); - private readonly ObjectIdDictionary?> proxyClassRegistry = new ObjectIdDictionary?>(); - - private readonly ObjectIdDictionary hostObjectRegistry = new ObjectIdDictionary(); - private readonly ObjectIdDictionary hostFunctionRegistry = new ObjectIdDictionary(); - private readonly ObjectIdDictionary hostClassRegistry = new ObjectIdDictionary(); - - - public SuperRPC(Func objectIdGenerator) - { - ObjectIDGenerator = objectIdGenerator; - } - - private string DebugId = ""; - public SuperRPC(Func objectIdGenerator, string debugId) : this(objectIdGenerator) - { - DebugId = debugId; - } - - public void Connect(IRPCChannel channel) - { - Channel = channel; - if (channel is IRPCReceiveChannel receiveChannel) - { - receiveChannel.MessageReceived += MessageReceived; - } - } - - public void RegisterHostObject(string objId, object target, ObjectDescriptor descriptor) - { - hostObjectRegistry.Add(objId, target, descriptor); - } - - public void RegisterHostFunction(string objId, Delegate target, FunctionDescriptor? descriptor = null) - { - hostFunctionRegistry.Add(objId, target, descriptor ?? new FunctionDescriptor()); - } - - public void RegisterHostClass(string classId, Type clazz, ClassDescriptor descriptor) - { - descriptor.ClassId = classId; - if (descriptor.Static is not null) - { - RegisterHostObject(classId, clazz, descriptor.Static); - } - - hostClassRegistry.Add(classId, clazz, descriptor); - } - - public void RegisterHostClass(string classId, ClassDescriptor descriptor) - { - RegisterHostClass(classId, typeof(TClass), descriptor); - } - - public void RegisterProxyClass(string classId) - { - RegisterProxyClass(classId, typeof(TInterface)); - } - - public void RegisterProxyClass(string classId, Type ifType) - { - proxyClassRegistry.Add(classId, ifType, null); - } - - protected void MessageReceived(object? sender, MessageReceivedEventArgs eventArgs) - { - var message = eventArgs.message; - var replyChannel = eventArgs.replyChannel ?? Channel; - CurrentContext = new CallContext(replyChannel!, eventArgs.context); - - if (message.rpc_marker != "srpc") return; // TODO: throw? - - switch (message) - { - case RPC_GetDescriptorsMessage: - SendRemoteDescriptors(replyChannel); - break; - case RPC_DescriptorsResultMessage descriptors: - SetRemoteDescriptors(descriptors); - if (remoteDescriptorsReceived is not null) - { - remoteDescriptorsReceived.SetResult(true); - remoteDescriptorsReceived = null; - } - break; - case RPC_AnyCallTypeFnCallMessage functionCall: - CallTargetFunction(functionCall, CurrentContext); - break; - case RPC_ObjectDiedMessage objectDied: - hostObjectRegistry.RemoveById(objectDied.objId); - hostFunctionRegistry.RemoveById(objectDied.objId); - break; - case RPC_FnResultMessageBase fnResult: - { - if (fnResult.callType == FunctionReturnBehavior.Async) - { - - AsyncCallbackEntry? entry = null; - lock (asyncCallbacks) - { - if (!asyncCallbacks.Remove(fnResult.callId!, out entry)) - { - // If the Task is not registered yet, we still store the value (result) that we're going to use to complete it. - // In case it's a success=true, we cannot process it yet, because we don't know the exact type (resultType) - // but if it's an exception, we store an Exception object, so later we can figure out the success state based on that. - asyncCallbackValues.Add(fnResult.callId!, fnResult.success ? fnResult.result : new ArgumentException(fnResult.result?.ToString())); - } - } - - if (entry is not null) - { - if (fnResult.success) - { - var result = ProcessValueAfterDeserialization(fnResult.result, CurrentContext, entry.type); - entry.complete(result); - } - else - { - entry.fail(new ArgumentException(fnResult.result?.ToString())); - } - } - } - break; - } - default: - throw new ArgumentException("Invalid message received"); - } - } - - private T GetHostObject(string objId, IDictionary registry) - { - if (!registry.TryGetValue(objId, out var entry)) - { - throw new ArgumentException($"No object found with ID '{objId}'."); - } - return entry; - } - - protected void CallTargetFunction(RPC_AnyCallTypeFnCallMessage message, CallContext context) - { - object? result = null; - bool success = true; - - context.replySent = new TaskCompletionSource(); - - try - { - switch (message.action) - { - case "prop_get": - { - var entry = GetHostObject(message.objId, hostObjectRegistry.ById); - result = (entry.obj as Type ?? entry.obj.GetType()).GetProperty(message.prop!)?.GetValue(entry.obj); - break; - } - case "prop_set": - { - var entry = GetHostObject(message.objId, hostObjectRegistry.ById); - var propInfo = (entry.obj as Type ?? entry.obj.GetType()).GetProperty(message.prop!); - if (propInfo is null) - { - throw new ArgumentException($"Could not find property '{message.prop}' on object '{message.objId}'."); - } - var argDescriptors = entry.value.ProxiedProperties?.FirstOrDefault(pd => pd.Name == message.prop)?.Set?.Arguments; - var argDescriptor = argDescriptors?.Length > 0 ? argDescriptors[0] : null; - var value = ProcessValueAfterDeserialization(message.args[0], context, propInfo.PropertyType, argDescriptor); - propInfo.SetValue(entry.obj, value); - break; - } - case "method_call": - { - var entry = GetHostObject(message.objId, hostObjectRegistry.ById); - var objType = entry.obj as Type ?? entry.obj.GetType(); - var method = objType.GetMethod(message.prop!); - if (method is null) - { - throw new ArgumentException($"Method '{message.prop}' not found on object '{message.objId}'."); - } - var argDescriptors = entry.value.Functions?.FirstOrDefault(fd => fd.Name == message.prop)?.Arguments; - var args = ProcessArgumentsAfterDeserialization(message.args, context, method.GetParameters().Select(param => param.ParameterType).ToArray(), argDescriptors); - result = method.Invoke(entry.obj, args); - break; - } - case "fn_call": - { - var entry = GetHostObject(message.objId, hostFunctionRegistry.ById); - var method = entry.obj.Method; - var args = ProcessArgumentsAfterDeserialization( - message.args, - context, - method.GetParameters().Select(param => param.ParameterType).ToArray(), - entry.value?.Arguments); - result = entry.obj.DynamicInvoke(args); - break; - } - case "ctor_call": - { - var classId = message.objId; - if (!hostClassRegistry.ById.TryGetValue(classId, out var entry)) - { - throw new ArgumentException($"No class found with ID '{classId}'."); - } - var method = entry.obj.GetConstructors()[0]; - var args = ProcessArgumentsAfterDeserialization( - message.args, - context, - method.GetParameters().Select(param => param.ParameterType).ToArray(), - entry.value.Ctor?.Arguments); - result = method.Invoke(args); - break; - } - default: - { - throw new ArgumentException($"Invalid message received, action={message.action}"); - } - } - } - catch (Exception e) - { - success = false; - result = e.ToString(); - } - - if (message.callType == FunctionReturnBehavior.Async) - { - - void SendAsyncResult(bool success, object? result) - { - SendAsyncIfPossible(new RPC_AsyncFnResultMessage - { - success = success, - result = result, - callId = message.callId - }, context.replyChannel); - } - - if (result is Task task) - { - SendResultOnTaskCompletion(task, SendAsyncResult, context); - } - else - { - SendAsyncResult(success, ProcessValueBeforeSerialization(result, context)); - } - context.replySent.SetResult(); - } - else if (message.callType == FunctionReturnBehavior.Sync) - { - SendSyncIfPossible(new RPC_SyncFnResultMessage - { - success = success, - result = ProcessValueBeforeSerialization(result, context), - }, context.replyChannel); - context.replySent.SetResult(); - } - } - - /** - * Send a request to get the descriptors for the registered host objects from the other side. - * Uses synchronous communication if possible and returns `true`/`false` based on if the descriptors were received. - * If sync is not available, it uses async messaging and returns a Task. - */ - public ValueTask RequestRemoteDescriptors() - { - if (Channel is IRPCSendSyncChannel syncChannel) - { - var response = syncChannel.SendSync(new RPC_GetDescriptorsMessage()); - if (response is RPC_DescriptorsResultMessage descriptors) - { - SetRemoteDescriptors(descriptors); - return new ValueTask(true); - } - } - - if (Channel is IRPCSendAsyncChannel asyncChannel) - { - remoteDescriptorsReceived = new TaskCompletionSource(); - asyncChannel.SendAsync(new RPC_GetDescriptorsMessage()); - return new ValueTask(remoteDescriptorsReceived.Task); - } - - return new ValueTask(false); - } - - private void SetRemoteDescriptors(RPC_DescriptorsResultMessage response) - { - if (response.objects is not null) - { - this.remoteObjectDescriptors = response.objects; - } - if (response.functions is not null) - { - this.remoteFunctionDescriptors = response.functions; - } - if (response.classes is not null) - { - this.remoteClassDescriptors = response.classes; - } - } - - /** - * Send the descriptors for the registered host objects to the other side. - * If possible, the message is sent synchronously. - * This is a "push" style message, for "pull" see [[requestRemoteDescriptors]]. - */ - public void SendRemoteDescriptors(IRPCChannel? replyChannel = null) - { - replyChannel ??= Channel; - SendSyncIfPossible(new RPC_DescriptorsResultMessage - { - objects = GetLocalObjectDescriptors(), - functions = hostFunctionRegistry.ById.ToDictionary(x => x.Key, x => x.Value.value), - classes = hostClassRegistry.ById.ToDictionary(x => x.Key, x => x.Value.value), - }, replyChannel); - } - - private ObjectDescriptors GetLocalObjectDescriptors() - { - var descriptors = new ObjectDescriptors(); - - foreach (var (key, entry) in hostObjectRegistry.ById) - { - if (entry.value is ObjectDescriptor objectDescriptor) - { - var props = new Dictionary(); - if (objectDescriptor.ReadonlyProperties is not null) - { - foreach (var prop in objectDescriptor.ReadonlyProperties) - { - var value = entry.obj.GetType().GetProperty(prop, BindingFlags.Public | BindingFlags.Instance)?.GetValue(entry.obj); - if (value is not null) props.Add(prop, value); - } - } - descriptors.Add(key, ObjectDescriptorWithProps.From(objectDescriptor, props)); - } - } - - return descriptors; - } - - private object? SendSyncIfPossible(RPC_Message message, IRPCChannel? channel = null) - { - channel ??= Channel; - - if (channel is IRPCSendSyncChannel syncChannel) - { - return syncChannel.SendSync(message); - } - else if (channel is IRPCSendAsyncChannel asyncChannel) - { - asyncChannel.SendAsync(message); - } - return null; - } - - - private object? SendAsyncIfPossible(RPC_Message message, IRPCChannel? channel = null) - { - channel ??= Channel; - - if (channel is IRPCSendAsyncChannel asyncChannel) - { - asyncChannel.SendAsync(message); - } - else if (channel is IRPCSendSyncChannel syncChannel) - { - return syncChannel.SendSync(message); - } - return null; - } - - private string RegisterLocalObj(object obj, ObjectDescriptor? descriptor = null) - { - descriptor ??= new ObjectDescriptor(); - - if (hostObjectRegistry.ByObj.TryGetValue(obj, out var entry)) - { - return entry.id; - } - var objId = ObjectIDGenerator(); - hostObjectRegistry.Add(objId, obj, descriptor); - return objId; - } - - private string RegisterLocalFunc(Delegate obj, FunctionDescriptor descriptor) - { - if (hostFunctionRegistry.ByObj.TryGetValue(obj, out var entry)) - { - return entry.id; - } - var objId = ObjectIDGenerator(); - hostFunctionRegistry.Add(objId, obj, descriptor); - return objId; - } - - private Dictionary> deserializers = new Dictionary>(); - - public void RegisterDeserializer(Type type, Func deserializer) - { - deserializers.Add(type, deserializer); - } - - private void CallAfterReplySent(CallContext context, Action action) - { - if (context.replySent is not null) - { - context.replySent.Task.ContinueWith(_ => action()); - } - else - { - action(); - } - } - - private async void SendResultOnTaskCompletion(Task task, Action sendResult, CallContext context) - { - var taskType = task.GetType(); - try - { - await task; - } - catch (Exception) - { - // Could not find another way to wait for the task, but ignore any exceptions/failures. - } - - if (taskType.IsGenericType && taskType.GetGenericArguments()[0].Name != "VoidTaskResult") - { - sendResult(!task.IsFaulted, - task.IsFaulted ? task.Exception?.ToString() : - ProcessValueBeforeSerialization(((dynamic)task).Result, context) - ); - } - else - { - sendResult(!task.IsFaulted, null); - } - } - - private bool ProcessPropertyValuesBeforeSerialization(object obj, PropertyInfo[] properties, Dictionary propertyBag, CallContext context, HashSet marked) - { - var needToConvert = false; - foreach (var propInfo in properties) - { - if (!propInfo.CanRead || propInfo.GetIndexParameters().Length > 0) continue; - - var value = propInfo.GetValue(obj); - var newValue = ProcessValueBeforeSerialization(value, context, marked); - propertyBag.Add(propInfo.Name, newValue); - - if (value is null ? newValue is not null : !value.Equals(newValue)) - { - needToConvert = true; - } - } - return needToConvert; - } - - private object?[] ProcessArgumentsBeforeSerialization(object?[] args/* , Type[] parameterTypes */, FunctionDescriptor? func, CallContext context) - { - for (var i = 0; i < args.Length; i++) - { - var arg = args[i]; - // var type = parameterTypes[i]; - args[i] = ProcessValueBeforeSerialization(arg, context); - } - return args; - } - - private RPC_Object? ProcessHostObject(object obj, Type? objType, CallContext context, HashSet marked) - { - while (objType != null) - { - if (hostClassRegistry.ByObj.TryGetValue(objType, out var entry)) - { - var descriptor = entry.value; - var objId = RegisterLocalObj(obj, descriptor.Instance); - var propertyBag = new Dictionary(); - - if (descriptor.Instance?.ReadonlyProperties is not null) - { - var propertyInfos = descriptor.Instance.ReadonlyProperties.Select( - prop => objType.GetProperty(prop, BindingFlags.Public | BindingFlags.Instance) - ).ToArray(); - ProcessPropertyValuesBeforeSerialization(obj, propertyInfos!, propertyBag, context, marked); - } - return new RPC_Object(objId, "object", propertyBag, entry.id); - } - objType = objType.BaseType; - } - return null; - } - - private object? ProcessValueBeforeSerialization(object? obj, CallContext context, HashSet? marked = null) - { - marked ??= new HashSet(); - - if (obj is null) return null; - - if (marked.Contains(obj)) - { - return null; - } - - try - { - marked.Add(obj); - - var proxyId = proxyObjectRegistry.GetId(obj); - if (proxyId is not null) - { - return obj is Delegate ? new RPC_BaseObj(proxyId, "hostfunction") : new RPC_BaseObj(proxyId, "hostobject"); - } - - var objType = obj.GetType(); - const BindingFlags PropBindFlags = BindingFlags.Public | BindingFlags.Instance; - - if (obj is Task task) - { - string? objId = null; - if (!hostObjectRegistry.ByObj.ContainsKey(obj)) - { - - void SendResult(bool success, object? result) - { - SendAsyncIfPossible(new RPC_AsyncFnResultMessage - { - success = success, - result = result, - callId = objId - }, context.replyChannel); - } - - CallAfterReplySent(context, () => SendResultOnTaskCompletion(task, SendResult, context)); - } - objId = RegisterLocalObj(obj); - return new RPC_Object(objId, "object", null, "Promise"); - } - - var rpcObj = ProcessHostObject(obj, objType, context, marked); - if (rpcObj is not null) return rpcObj; - - if (obj is Delegate func) - { - var objId = RegisterLocalFunc(func, new FunctionDescriptor()); - return new RPC_BaseObj(objId, "function"); - } - - if ((objType.IsArray || (objType.IsGenericType && objType.GetGenericTypeDefinition() == typeof(List<>))) - && obj is System.Collections.IList array) - { - List list = new List(); - for (var i = 0; i < array.Count; i++) - { - list.Add(ProcessValueBeforeSerialization(array[i], context, marked)); - } - return list; - } - else - if (objType.IsClass && objType != typeof(string)) - { - var propertyInfos = objType.GetProperties(PropBindFlags); - var propertyBag = new Dictionary(); - - if (ProcessPropertyValuesBeforeSerialization(obj, propertyInfos, propertyBag, context, marked)) - { - var objId = RegisterLocalObj(obj); - return new RPC_Object(objId, "object", propertyBag); - } - } - - return obj; - } - finally - { - marked.Remove(obj); - } - } - - private object?[] ProcessArgumentsAfterDeserialization(object?[] args, CallContext context, Type[] parameterTypes, ArgumentDescriptor[]? argumentDescriptors) - { - if (args.Length != parameterTypes.Length) - { - throw new ArgumentException($"Method argument number mismatch. Expected {parameterTypes.Length} and got {args.Length}."); - } - - for (var i = 0; i < args.Length; i++) - { - var arg = args[i]; - var descr = argumentDescriptors?.FirstOrDefault(ad => ad.idx == i || ad.idx is null); - var type = parameterTypes[i]; - args[i] = ProcessValueAfterDeserialization(args[i], context, parameterTypes[i], descr); - } - - return args; - } - - private Func? GetDeserializer(Type type) - { - if (deserializers.TryGetValue(type, out var deserializer)) - { - return deserializer; - } - else if (deserializers.TryGetValue(typeof(object), out deserializer)) - { - return deserializer; - } - return null; - } - - private static Action CreateSetResultDelegate(dynamic source) - { - return (object? result) => source.SetResult((T?)result); - } - - private AsyncCallbackEntry CreateAsyncCallback(Type returnType) - { - dynamic source = typeof(TaskCompletionSource<>).MakeGenericType(returnType).GetConstructor(Type.EmptyTypes).Invoke(null); - return new AsyncCallbackEntry(source.Task, - (Action)GetType().GetMethod("CreateSetResultDelegate", BindingFlags.NonPublic | BindingFlags.Static) - .MakeGenericMethod(returnType).Invoke(null, new object[] { source }), - (Action)((Exception ex) => source.SetException(ex)), - returnType); - } - - private object? ProcessValueAfterDeserialization(object? obj, CallContext context, Type? type = null, ArgumentDescriptor? argDescriptor = null) - { - if (obj is null) - { - if (type?.IsValueType == true) - { - throw new ArgumentException("null cannot be passed as a value type"); - } - } - else - { - var objType = obj.GetType(); - - if (obj is not RPC_BaseObj) - { - RPC_BaseObj? rpcObj1 = null; - var rpcObjDeserializer = GetDeserializer(typeof(RPC_Object)); - if (rpcObjDeserializer is not null) - { - rpcObj1 = rpcObjDeserializer(obj, typeof(RPC_Object)) as RPC_Object; - } - if (rpcObj1 is null) - { - rpcObjDeserializer = GetDeserializer(typeof(RPC_BaseObj)); - if (rpcObjDeserializer is not null) - { - rpcObj1 = rpcObjDeserializer(obj, typeof(RPC_BaseObj)) as RPC_BaseObj; - } - } - if (rpcObj1 is not null && rpcObj1._rpc_type is not null) - { - obj = rpcObj1; - objType = obj.GetType(); - } - } - - if (obj is RPC_BaseObj rpcObj && rpcObj?.objId is not null) - { - - if (rpcObj._rpc_type == "object" && type is null && - rpcObj is RPC_Object rpcObj2 && rpcObj2.classId is not null && - proxyClassRegistry.ById.TryGetValue(rpcObj2.classId, out var proxyEntry)) - { - type = proxyEntry.obj; - } - - // special cases for _rpc_type=[host]object/function - switch (rpcObj._rpc_type) - { - case "function": - { - // If the proxy function is "sync" we don't want to reply on the replyChannel, - // because the fn call that this proxy function is passed into - // might also want to return its result synchronously. - var ctx = argDescriptor?.Returns == FunctionReturnBehavior.Sync || context.replyChannel is not IRPCSendAsyncChannel ? - new CallContext(Channel!) { replySent = context.replySent } : context; - if (type is not null) - { - obj = GetOrCreateProxyFunction(rpcObj.objId, type, ctx, argDescriptor); - } - break; - } - case "object": - { - // If a function on the proxy object is "sync" we don't want to reply on the replyChannel, - // because the fn call that this proxy object is passed into - // might also want to return its result synchronously. - var channel = context.replyChannel as IRPCSendAsyncChannel ?? Channel; - if (type is not null && rpcObj is RPC_Object rpcObj3) - { - var props = ProcessValueAfterDeserialization(rpcObj3.props, context) as Dictionary; - obj = GetOrCreateProxyInstance(rpcObj.objId, rpcObj3.classId, props, type, channel!); - } - break; - } - case "hostobject": - { - if (hostObjectRegistry.ById.TryGetValue(rpcObj.objId, out var entry)) - { - obj = entry.obj; - } - else - { - throw new ArgumentException($"No host object found with ID '{rpcObj.objId}'."); - } - break; - } - case "hostfunction": - { - if (hostFunctionRegistry.ById.TryGetValue(rpcObj.objId, out var entry)) - { - obj = entry.obj; - } - else - { - throw new ArgumentException($"No host function found with ID '{rpcObj.objId}'."); - } - break; - } - default: throw new ArgumentException($"Invalid _rpc_type '{rpcObj._rpc_type}'."); - } - objType = obj.GetType(); - } - - if (type is not null) - { - // custom deserializers - var deserializer = GetDeserializer(type); - if (deserializer is not null) - { - var obj1 = deserializer(obj, type); - if (obj1 is not null) - { - obj = obj1; - objType = obj.GetType(); - } - } - - if (!objType.IsAssignableTo(type) && obj is IConvertible) - { - obj = Convert.ChangeType(obj, type); - } - } - - // recursive call for Dictionary - if (obj is IDictionary dict) - { - foreach (var (key, value) in dict) - { - dict[key] = ProcessValueAfterDeserialization(value, context); - } - } - } - return obj; - } - - private void SendObjectDied(string objId, IRPCChannel? replyChannel = null) - { - SendAsyncIfPossible(new RPC_ObjectDiedMessage { objId = objId }, replyChannel ?? Channel); - } - - private void AddPropsToObject(Dictionary? props, object obj) - { - if (props is not null) - { - var objType = obj.GetType(); - foreach (var (name, value) in props) - { - // We know that the generated dynamic class has a private backing field with name "_" - var fieldInfo = objType.GetField("_" + name, BindingFlags.NonPublic | BindingFlags.Instance); - if (fieldInfo is not null) - { - fieldInfo.SetValue(obj, value); - continue; - } - var propInfo = objType.GetProperty(name, BindingFlags.Public | BindingFlags.Instance); - if (propInfo is not null) - { - propInfo.SetValue(obj, value); - } - } - } - } - - public T GetProxyObject(string objId, IRPCChannel? channel = null) - { - var obj = (T?)proxyObjectRegistry.Get(objId); - if (obj is not null) return obj; - - if (remoteObjectDescriptors?.TryGetValue(objId, out var descriptor) is not true) - { - throw new ArgumentException($"No descriptor found for object ID {objId}."); - } - - var factory = GetProxyClassFactory(objId + ".class", typeof(T), descriptor, channel); - obj = (T)factory(objId); - - AddPropsToObject(descriptor?.Props, obj); - - proxyObjectRegistry.Register(objId, obj); - return obj; - } - - private object GetOrCreateProxyInstance(string objId, string? classId, Dictionary? props, Type type, IRPCChannel replyChannel) - { - var obj = proxyObjectRegistry.Get(objId); - if (obj is not null) return obj; - - if (classId == "Promise") - { - var resultType = type == typeof(Task) ? typeof(object) : UnwrapTaskReturnType(type); - var asyncCallback = CreateAsyncCallback(resultType); - - object? asyncResult = null; - lock (asyncCallbacks) - { - if (!asyncCallbackValues.Remove(objId, out asyncResult)) - { - asyncCallbacks.Add(objId, asyncCallback); - } - } - - if (asyncResult is not null) - { - if (asyncResult is Exception asyncFailure) - { - asyncCallback.fail(asyncFailure); - } - else - { - var result = ProcessValueAfterDeserialization(asyncResult, CurrentContext!, resultType); - asyncCallback.complete(result); - } - } - - obj = asyncCallback.task; - } - else - if (proxyClassRegistry.ByObj.TryGetValue(type, out var proxyClassEntry)) - { - var factory = proxyClassEntry.value; - if (factory is null) - { - factory = GetProxyClassFactory(proxyClassEntry.id, replyChannel); - proxyClassRegistry.Add(proxyClassEntry.id, proxyClassEntry.obj, factory); - } - obj = factory(objId); - AddPropsToObject(props, obj); - } - else - throw new ArgumentException($"No proxy class registered for type {type.FullName}."); - - proxyObjectRegistry.Register(objId, obj, () => SendObjectDied(objId, replyChannel)); - return obj; - } - - private Delegate GetOrCreateProxyFunction(string objId, Type type, CallContext context, ArgumentDescriptor? argDescriptor) - { - var obj = (Delegate?)proxyObjectRegistry.Get(objId); - if (obj is not null) return obj; - - obj = CreateProxyFunctionFromDelegateType(type, objId, argDescriptor ?? new FunctionDescriptor(), context); - proxyObjectRegistry.Register(objId, obj, () => SendObjectDied(objId, context.replyChannel)); - return obj; - } - - private Delegate CreateVoidProxyFunction(string? objId, FunctionDescriptor? func, string action, CallContext context) - { - - TReturn? ProxyFunction(string instanceObjId, object?[] args) - { - SendAsyncIfPossible(new RPC_AnyCallTypeFnCallMessage - { - action = action, - callType = FunctionReturnBehavior.Void, - objId = objId ?? instanceObjId, - prop = func?.Name, - args = ProcessArgumentsBeforeSerialization(args, func, context) - }, context.replyChannel); - return default; - } - - return ProxyFunction; - } - - private Delegate CreateSyncProxyFunction(string? objId, FunctionDescriptor? func, string action, CallContext context) - { - - TReturn? ProxyFunction(string instanceObjId, object?[] args) - { - var response = (RPC_SyncFnResultMessage?)SendSyncIfPossible(new RPC_AnyCallTypeFnCallMessage - { - action = action, - callType = FunctionReturnBehavior.Sync, - objId = objId ?? instanceObjId, - prop = func?.Name, - args = ProcessArgumentsBeforeSerialization(args, func, context) - }, context.replyChannel); - if (response is null) - { - throw new ArgumentException($"No response received"); - } - if (!response.success) - { - throw new ArgumentException(response.result?.ToString()); - } - - return (TReturn?)ProcessValueAfterDeserialization(response.result, context); - } - - return ProxyFunction; - } - - private Delegate CreateAsyncProxyFunction(string? objId, FunctionDescriptor? func, string action, CallContext context) - { - - Task ProxyFunction(string instanceObjId, object?[] args) - { - callId++; - - var ownCtx = context.replySent is null; - var ctx = ownCtx ? new CallContext(context.replyChannel) { replySent = new TaskCompletionSource() } : context; - - var asyncCallback = CreateAsyncCallback(UnwrapTaskReturnType(typeof(TReturn))); - try - { - lock (asyncCallbacks) - asyncCallbacks.Add(callId.ToString(), asyncCallback); - } - catch (Exception ex) - { - Debug.WriteLine(ex.ToString()); - } - - SendAsyncIfPossible(new RPC_AnyCallTypeFnCallMessage - { - action = action, - callType = FunctionReturnBehavior.Async, - callId = callId.ToString(), - objId = objId ?? instanceObjId, - prop = func?.Name, - args = ProcessArgumentsBeforeSerialization(args, func, ctx) - }, ctx.replyChannel); - - if (ownCtx) - { - ctx.replySent!.SetResult(); - } - - return (Task)asyncCallback.task; - } - - return ProxyFunction; - } - - private Delegate CreateProxyFunction( - string objId, - FunctionDescriptor? descriptor, - string action, - CallContext context, - FunctionReturnBehavior defaultCallType = FunctionReturnBehavior.Async) - { - var replyChannel = context.replyChannel ?? Channel; - var callType = descriptor?.Returns ?? defaultCallType; - - if (callType == FunctionReturnBehavior.Async && replyChannel is not IRPCSendAsyncChannel) callType = FunctionReturnBehavior.Sync; - if (callType == FunctionReturnBehavior.Sync && replyChannel is not IRPCSendSyncChannel) callType = FunctionReturnBehavior.Async; - - return callType switch - { - FunctionReturnBehavior.Void => CreateVoidProxyFunction(objId, descriptor, action, context), - FunctionReturnBehavior.Sync => CreateSyncProxyFunction(objId, descriptor, action, context), - _ => CreateAsyncProxyFunction(objId, descriptor, action, context) - }; - } - - private Delegate CreateProxyFunctionWithReturnType( - Type returnType, - string? objId, - FunctionDescriptor? descriptor, - string action, - CallContext context, - FunctionReturnBehavior defaultCallType = FunctionReturnBehavior.Async) - { - if (returnType == typeof(void)) - { - returnType = typeof(object); - } - return (Delegate)(typeof(SuperRPC)) - .GetMethod("CreateProxyFunction", BindingFlags.NonPublic | BindingFlags.Instance) - .MakeGenericMethod(returnType) - .Invoke(this, new object[] { objId, descriptor, action, context, defaultCallType }); - } - - private Delegate CreateDynamicWrapperMethod(string methodName, Delegate proxyFunction, Type delegateType, MethodInfo method) - { - var paramTypes = method.GetParameters().Select(pi => pi.ParameterType).ToArray(); - - var dmethod = new DynamicMethod(methodName, - method.ReturnType, - paramTypes.Prepend(proxyFunction.Target!.GetType()).ToArray(), - proxyFunction.Target.GetType(), true); - - var il = dmethod.GetILGenerator(); - - il.Emit(OpCodes.Ldarg_0); // "this" (ref of the instance of the class generated for proxyFunction) - - il.Emit(OpCodes.Ldnull); // "null" to the stack -> instanceObjId - - il.Emit(OpCodes.Ldc_I4, paramTypes.Length); - il.Emit(OpCodes.Newarr, typeof(object)); //arr = new object[paramTypes.Length] - - for (var i = 0; i < paramTypes.Length; i++) - { - il.Emit(OpCodes.Dup); // arr ref - il.Emit(OpCodes.Ldc_I4, i); // int32: idx - il.Emit(OpCodes.Ldarg, i + 1); // arg(i+1) - if (paramTypes[i].IsValueType) - { - il.Emit(OpCodes.Box, paramTypes[i]); - } - il.Emit(OpCodes.Stelem_Ref); // arr[idx] = arg - } - - il.Emit(OpCodes.Call, proxyFunction.Method); - if (method.ReturnType == typeof(void)) - { - il.Emit(OpCodes.Pop); - } - il.Emit(OpCodes.Ret); - - return dmethod.CreateDelegate(delegateType, proxyFunction.Target); - } - - private static bool IsTaskType(Type type) - { - return type == typeof(Task) || type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>); - } - private static Type UnwrapTaskReturnType(Type type) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) - { - type = type.GetGenericArguments()[0]; - } - return type; - } - - public T GetProxyFunction(string objId, CallContext? context = null) where T : Delegate - { - context ??= new CallContext(Channel!); - - var obj = (T?)proxyObjectRegistry.Get(objId); - if (obj is not null) return obj; - - if (remoteFunctionDescriptors?.TryGetValue(objId, out var descriptor) is not true) - { - throw new ArgumentException($"No object descriptor found with ID '{objId}'."); - } - - obj = (T)CreateProxyFunctionFromDelegateType(typeof(T), objId, descriptor, context); - proxyObjectRegistry.Register(objId, obj); - return obj; - } - - private Delegate CreateProxyFunctionFromDelegateType(Type delegateType, string objId, FunctionDescriptor descriptor, CallContext context) - { - var method = delegateType.GetMethod("Invoke"); - if (method is null) - { - throw new ArgumentException($"Given generic type is not a generic delegate ({delegateType.FullName})"); - } - - var proxyFunc = CreateProxyFunctionWithReturnType(UnwrapTaskReturnType(method.ReturnType), objId, descriptor, "fn_call", context); - - return CreateDynamicWrapperMethod(objId + "_" + descriptor.Name, proxyFunc, delegateType, method); - } - - private ObjectIdDictionary?>.Entry GetProxyClassEntry(string classId) - { - if (!proxyClassRegistry.ById.TryGetValue(classId, out var proxyClassEntry)) - { - throw new ArgumentException($"No proxy class interface registered with ID '{classId}'."); - } - return proxyClassEntry; - } - - public Func GetProxyClass(string classId) - { - if (remoteClassDescriptors?.TryGetValue(classId, out var descriptor) is not true) - { - throw new ArgumentException($"No class descriptor found with ID '{classId}'."); - } - - var proxyFunc = CreateProxyFunction(classId, descriptor.Ctor, "ctor_call", new CallContext(Channel!)); - return (string id) => (T)proxyFunc.DynamicInvoke(id, new object[0])!; - } - - private Func GetProxyClassFactory(string classId, IRPCChannel? channel = null) - { - var entry = GetProxyClassEntry(classId); - if (entry.value is not null) - { - return entry.value; - } - - var factory = CreateProxyClass(classId, channel); - proxyClassRegistry.Add(classId, entry.obj, factory); - return factory; - } - - private Func GetProxyClassFactory(string classId, Type ifType, ObjectDescriptor descriptor, IRPCChannel? channel = null) - { - if (proxyClassRegistry.ById.TryGetValue(classId, out var proxyClassEntry) && proxyClassEntry?.value is not null) - { - return proxyClassEntry.value; - } - - var factory = CreateProxyClass(classId, ifType, descriptor, channel); - proxyClassRegistry.Add(classId, ifType, factory); - return factory; - } - - private Func CreateProxyClass(string classId, IRPCChannel? channel = null) - { - if (remoteClassDescriptors?.TryGetValue(classId, out var descriptor) is not true) - { - throw new ArgumentException($"No class descriptor found with ID '{classId}'."); - } - - var ifType = GetProxyClassEntry(classId).obj; - - if (ifType.IsClass) - { - var ctor = ifType.GetConstructor(Type.EmptyTypes); - if (ctor is null) throw new InvalidOperationException($"Proxy class {ifType.FullName} has no parameterless constructor."); - return (string objId) => ctor.Invoke(null); - } - - if (!ifType.IsInterface) - { - throw new InvalidOperationException($"Proxy class {ifType.FullName} is not a class or an interface."); - } - - return CreateProxyClass(classId, ifType, descriptor.Instance!, channel); - } - - private Func CreateProxyClass(string classId, Type ifType, ObjectDescriptor descriptor, IRPCChannel? channel = null) - { - channel ??= Channel!; - - var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName($"SuperRPC_dynamic({Guid.NewGuid()})"), AssemblyBuilderAccess.Run); - var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); - var typeBuilder = moduleBuilder.DefineType(classId, - TypeAttributes.Public | - TypeAttributes.Class | - TypeAttributes.AutoClass | - TypeAttributes.AnsiClass | - TypeAttributes.BeforeFieldInit | - TypeAttributes.AutoLayout, - null, new[] { ifType }); - - var objIdField = typeBuilder.DefineField("objId", typeof(string), FieldAttributes.Public | FieldAttributes.InitOnly); - var proxyFunctionsField = typeBuilder.DefineField("proxyFunctions", typeof(Delegate[]), FieldAttributes.Public | FieldAttributes.Static); - - var proxyFunctions = new List(); - var skipMethods = new List(); - - var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(string) }); - var ctorIL = constructorBuilder.GetILGenerator(); - - // call base() - ctorIL.Emit(OpCodes.Ldarg_0); - ConstructorInfo superConstructor = typeof(Object).GetConstructor(Type.EmptyTypes)!; - - ctorIL.Emit(OpCodes.Call, superConstructor); - - ctorIL.Emit(OpCodes.Ldarg_0); // this - ctorIL.Emit(OpCodes.Ldarg_1); // objId ref - ctorIL.Emit(OpCodes.Stfld, objIdField); // this.objId = arg1 - - // ctorIL.Emit(OpCodes.Ldarg_0); // this - // ctorIL.Emit(OpCodes.Ldarg_2); // proxyFunctions ref - // ctorIL.Emit(OpCodes.Stfld, proxyFunctionsField); // this.proxyFunctions = arg2 - - ctorIL.Emit(OpCodes.Ret); - - ClassDescriptor? classDescriptor = null; - remoteClassDescriptors?.TryGetValue(classId, out classDescriptor); - - // Static methods - // var smethods = ifType.GetMethods(BindingFlags.Public | BindingFlags.Static); - - // foreach (var methodInfo in smethods) { - // if (skipMethods.Contains(methodInfo.Name)) continue; - - // var funcDescriptor = classDescriptor?.Static?.Functions?.FirstOrDefault(desc => desc.Name == methodInfo.Name); // TODO: camelCase <-> PascalCase ? - // if (funcDescriptor is null) { - // throw new ArgumentException($"No function descriptor found for method '{methodInfo.Name}' in class '{classId}'."); - // } - - // var paramInfos = methodInfo.GetParameters(); - // var paramTypes = paramInfos.Select(pi => pi.ParameterType).ToArray(); - - // var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name, - // MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.Virtual, - // CallingConventions.Standard, - // methodInfo.ReturnType, - // // methodInfo.ReturnParameter.GetRequiredCustomModifiers(), - // // methodInfo.ReturnParameter.GetOptionalCustomModifiers(), - // paramTypes - // // paramInfos.Select(pi => pi.GetRequiredCustomModifiers()).ToArray(), - // // paramInfos.Select(pi => pi.GetOptionalCustomModifiers()).ToArray() - // ); - - // GenerateILMethod(methodBuilder.GetILGenerator(), objIdField, proxyFunctionsField, proxyFunctions.Count, paramTypes, methodInfo.ReturnType, isStatic: true); - // proxyFunctions.Add(CreateProxyFunctionWithReturnType(UnwrapTaskReturnType(methodInfo.ReturnType), classId, funcDescriptor, "method_call", new CallContext(channel))); - // } - - // Events - var events = ifType.GetEvents(BindingFlags.Public | BindingFlags.Instance); - - foreach (var eventInfo in events) - { - if (eventInfo.EventHandlerType is null) - { - throw new InvalidOperationException($"EventHandlerType is null in EventInfo {eventInfo.Name}"); - } - - var addMethodName = "add_" + eventInfo.Name; - var removeMethodName = "remove_" + eventInfo.Name; - - skipMethods.Add(addMethodName); - skipMethods.Add(removeMethodName); - - var eventBuilder = typeBuilder.DefineEvent(eventInfo.Name, EventAttributes.None, eventInfo.EventHandlerType); - - // add method - var addMethodParams = new[] { eventInfo.EventHandlerType }; - var addMethodBuilder = typeBuilder.DefineMethod(addMethodName, - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot, - CallingConventions.Standard | CallingConventions.HasThis, typeof(void), addMethodParams); - - eventBuilder.SetAddOnMethod(addMethodBuilder); - - var addDescriptor = descriptor?.Functions?.FirstOrDefault(func => func.Name == addMethodName); - - GenerateILMethod(addMethodBuilder.GetILGenerator(), objIdField, proxyFunctionsField, proxyFunctions.Count, addMethodParams, typeof(void)); - proxyFunctions.Add(CreateProxyFunctionWithReturnType(typeof(void), null, - addDescriptor ?? new FunctionDescriptor { Name = addMethodName, Returns = FunctionReturnBehavior.Sync }, "method_call", new CallContext(channel))); - - // remove method - var removeMethodParams = new[] { eventInfo.EventHandlerType }; - var removeMethodBuilder = typeBuilder.DefineMethod(removeMethodName, - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot, - CallingConventions.Standard | CallingConventions.HasThis, typeof(void), removeMethodParams); - - eventBuilder.SetRemoveOnMethod(removeMethodBuilder); - - var removeDescriptor = descriptor?.Functions?.FirstOrDefault(func => func.Name == removeMethodName); - - GenerateILMethod(removeMethodBuilder.GetILGenerator(), objIdField, proxyFunctionsField, proxyFunctions.Count, removeMethodParams, typeof(void)); - proxyFunctions.Add(CreateProxyFunctionWithReturnType(typeof(void), null, - removeDescriptor ?? new FunctionDescriptor { Name = removeMethodName, Returns = FunctionReturnBehavior.Sync /*TODO: args? */ }, "method_call", new CallContext(channel))); - } - - // Properties - var properties = ifType.GetProperties(BindingFlags.Public | BindingFlags.Instance); - - foreach (var propertyInfo in properties) - { - var isProxied = true; - - var propDescriptor = descriptor?.ProxiedProperties?.FirstOrDefault(desc => desc.Name == propertyInfo.Name); // TODO: camelCase <-> PascalCase ? - if (propDescriptor is null) - { - if (descriptor?.ReadonlyProperties?.Contains(propertyInfo.Name) is not true) - { // TODO: camelCase <-> PascalCase ? - throw new ArgumentException($"No property descriptor found for property '{propertyInfo.Name}' in class '{classId}'."); - } - isProxied = false; - } - - var isGetOnly = propDescriptor?.GetOnly ?? false; - - var propertyBuilder = typeBuilder.DefineProperty(propertyInfo.Name, - PropertyAttributes.HasDefault, - propertyInfo.PropertyType, - null); - - // The property set and property get methods require a special - // set of attributes. - var getSetAttr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig; - - // Define the "get" accessor method - var getterName = "get_" + propertyInfo.Name; - skipMethods.Add(getterName); - var getPropMthdBldr = typeBuilder.DefineMethod(getterName, - getSetAttr, - propertyInfo.PropertyType, - Type.EmptyTypes); - - var getterIL = getPropMthdBldr.GetILGenerator(); - propertyBuilder.SetGetMethod(getPropMthdBldr); - - ILGenerator? setterIL = null; - if (!isGetOnly) - { - // Define the "set" accessor method - var setterName = "set_" + propertyInfo.Name; - skipMethods.Add(setterName); - var setPropMthdBldr = typeBuilder.DefineMethod(setterName, - getSetAttr, - null, - new[] { propertyInfo.PropertyType }); - - setterIL = setPropMthdBldr.GetILGenerator(); - propertyBuilder.SetSetMethod(setPropMthdBldr); - } - - if (isProxied) - { - GenerateILMethod(getterIL, objIdField, proxyFunctionsField, proxyFunctions.Count, Type.EmptyTypes, propertyInfo.PropertyType); - proxyFunctions.Add(CreateProxyFunctionWithReturnType( - UnwrapTaskReturnType(propertyInfo.PropertyType), - null, - propDescriptor?.Get ?? new FunctionDescriptor { Name = propDescriptor!.Name, Returns = FunctionReturnBehavior.Sync }, - "prop_get", - new CallContext(channel))); - - if (!isGetOnly) - { - GenerateILMethod(setterIL!, objIdField, proxyFunctionsField, proxyFunctions.Count, new[] { propertyInfo.PropertyType }, typeof(void)); - proxyFunctions.Add(CreateProxyFunctionWithReturnType(typeof(void), - null, - propDescriptor?.Set ?? new FunctionDescriptor - { - Name = propDescriptor!.Name, - Returns = channel is IRPCSendSyncChannel ? FunctionReturnBehavior.Sync : FunctionReturnBehavior.Void - }, - "prop_set", - new CallContext(channel))); - } - } - else - { // not proxied -> "readonly" - // backing field - var backingFieldBuilder = typeBuilder.DefineField("_" + propertyInfo.Name, - propertyInfo.PropertyType, - FieldAttributes.Private); - - getterIL.Emit(OpCodes.Ldarg_0); - getterIL.Emit(OpCodes.Ldfld, backingFieldBuilder); - getterIL.Emit(OpCodes.Ret); - - setterIL!.Emit(OpCodes.Ldarg_0); - setterIL.Emit(OpCodes.Ldarg_1); - setterIL.Emit(OpCodes.Stfld, backingFieldBuilder); - setterIL.Emit(OpCodes.Ret); - } - } - - // Methods - var methods = ifType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - - foreach (var methodInfo in methods) - { - if (skipMethods.Contains(methodInfo.Name)) continue; - - var funcDescriptor = descriptor?.Functions?.FirstOrDefault(desc => desc.Name == methodInfo.Name); // TODO: camelCase <-> PascalCase ? - if (funcDescriptor is null) - { - throw new ArgumentException($"No function descriptor found for method '{methodInfo.Name}' in class '{classId}'."); - } - - var paramInfos = methodInfo.GetParameters(); - var paramTypes = paramInfos.Select(pi => pi.ParameterType).ToArray(); - - var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name, - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, - CallingConventions.HasThis, - methodInfo.ReturnType, - methodInfo.ReturnParameter.GetRequiredCustomModifiers(), - methodInfo.ReturnParameter.GetOptionalCustomModifiers(), - paramTypes, - paramInfos.Select(pi => pi.GetRequiredCustomModifiers()).ToArray(), - paramInfos.Select(pi => pi.GetOptionalCustomModifiers()).ToArray() - ); - - GenerateILMethod(methodBuilder.GetILGenerator(), objIdField, proxyFunctionsField, proxyFunctions.Count, paramTypes, methodInfo.ReturnType); - proxyFunctions.Add(CreateProxyFunctionWithReturnType(UnwrapTaskReturnType(methodInfo.ReturnType), null, funcDescriptor, "method_call", new CallContext(channel))); - } - - var proxyFunctionsArr = proxyFunctions.ToArray(); - try - { - var type = typeBuilder.CreateType(); - type!.GetField(proxyFunctionsField.Name, BindingFlags.Public | BindingFlags.Static)!.SetValue(type, proxyFunctionsArr); - - object CreateInstance(string objId) - { - return Activator.CreateInstance(type, objId)!; - } - return CreateInstance; - } - catch (Exception ex) - { - Console.WriteLine(ex.ToString()); - } - - return null; - - } - - void GenerateILMethod(ILGenerator il, FieldBuilder objIdField, FieldBuilder proxyFunctionsField, int funcIdx, Type[] paramTypes, Type returnType, bool isStatic = false) - { - il.Emit(OpCodes.Ldsfld, proxyFunctionsField); // ref of Delegate[] containing proxy functions - il.Emit(OpCodes.Ldc_I4, funcIdx); - il.Emit(OpCodes.Ldelem_Ref); // proxyFunction [Delegate] is on the stack now - - il.Emit(OpCodes.Ldc_I4_2); - il.Emit(OpCodes.Newarr, typeof(object)); //arr2 = new object[2] - - il.Emit(OpCodes.Dup); // arr2 - il.Emit(OpCodes.Ldc_I4_0); // 0 - - if (isStatic) - { - il.Emit(OpCodes.Ldnull); - } - else - { - il.Emit(OpCodes.Ldarg_0); // "this" - il.Emit(OpCodes.Ldfld, objIdField); // push(this.objId) - } - il.Emit(OpCodes.Stelem_Ref); // arr2[0] = objId - - il.Emit(OpCodes.Dup); // arr2 - il.Emit(OpCodes.Ldc_I4_1); // 1 - - il.Emit(OpCodes.Ldc_I4, paramTypes.Length); - il.Emit(OpCodes.Newarr, typeof(object)); //arr1 = new object[paramTypes.Length] - - for (var i = 0; i < paramTypes.Length; i++) - { - il.Emit(OpCodes.Dup); // arr ref - il.Emit(OpCodes.Ldc_I4, i); // int32: idx - il.Emit(OpCodes.Ldarg, i + 1); // arg(i+1) - if (paramTypes[i].IsValueType) - { - il.Emit(OpCodes.Box, paramTypes[i]); - } - il.Emit(OpCodes.Stelem_Ref); // arr1[idx] = arg - } - - il.Emit(OpCodes.Stelem_Ref); // arr2[1] = arr1 - - il.Emit(OpCodes.Callvirt, typeof(Delegate).GetMethod("DynamicInvoke")!); - - if (returnType == typeof(void)) - { - il.Emit(OpCodes.Pop); - } - else if (returnType.IsValueType) - { - il.Emit(OpCodes.Unbox_Any, returnType); - } - - il.Emit(OpCodes.Ret); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/RPC-WebSocket.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/RPC-WebSocket.cs deleted file mode 100644 index 488d21f94..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/RPC-WebSocket.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System.Buffers; -using System.Collections; -using System.Collections.Concurrent; -using System.Diagnostics; -using System.IO.Pipelines; -using System.Net.WebSockets; -using System.Text; -using Nerdbank.Streams; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using ProcessExplorer; -using ProcessExplorer.Infrastructure; -using Super.RPC; - -namespace SuperRPC_POC; - -public record SuperRPCWebSocket(WebSocket webSocket, object? context) -{ - public RPCReceiveChannel ReceiveChannel; - public IRPCSendAsyncChannel SendChannel; - - // This is for the websocket client case. You need to call StartReceivingAsync() - // after connecting the SuperRPC instance to SuperRPCWebSocket.ReceiveChannel - public static SuperRPCWebSocket CreateHandler(WebSocket webSocket, object? context = null) - { - var rpcWebSocket = new SuperRPCWebSocket(webSocket, context); - var sendAndReceiveChannel = new RPCSendAsyncAndReceiveChannel(rpcWebSocket.ScheduleMessage); - - rpcWebSocket.SendChannel = sendAndReceiveChannel; - rpcWebSocket.ReceiveChannel = sendAndReceiveChannel; - - return rpcWebSocket; - } - - // This is useful when handling a server-side WebSocket connection. - // The replyChannel will be passed to the message event automatically. - public static Task HandleWebsocketConnectionAsync(WebSocket webSocket, - RPCReceiveChannel receiveChannel, - object? context = null, - IProcessInfoAggregator? aggregator = null, IUIHandler? uiHandler = null) - { - var rpcWebSocket = new SuperRPCWebSocket(webSocket, context); - rpcWebSocket.ReceiveChannel = receiveChannel; - rpcWebSocket.SendChannel = new RPCSendAsyncChannel(rpcWebSocket.ScheduleMessage); - return rpcWebSocket.StartReceivingAsync(aggregator, uiHandler); - } - - public static void RegisterCustomDeserializer(SuperRPC rpc) - { - rpc.RegisterDeserializer(typeof(object), ConvertTo); - } - - private static object? ConvertTo(object? obj, Type targetType) - { - if (obj is JArray array) - { - if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(List<>)) - { - var elementType = targetType.GetGenericArguments()[0]; - var list = (IList)Activator.CreateInstance(targetType); - foreach (var item in array) - { - list.Add(ConvertTo(item, elementType)); - } - return list; - } - if (targetType.IsArray) - { - var elementType = targetType.GetElementType(); - var arr = (IList)Activator.CreateInstance(targetType, array.Count); - for (var i = 0; i < array.Count; i++) - { - arr[i] = ConvertTo(array[i], elementType); - } - return arr; - } - return obj; - } - return (obj is JToken jToken) ? jToken.ToObject(targetType) : obj; - } - - private const int ReceiveBufferSize = 4 * 1024; - private JsonSerializer jsonSerializer = new JsonSerializer(); - private ArrayBufferWriter responseBuffer = new ArrayBufferWriter(); - private BlockingCollection messageQueue = new BlockingCollection(new ConcurrentQueue()); - - async Task SendMessage(RPC_Message message) - { - try - { - TextWriter textWriter = new StreamWriter(responseBuffer.AsStream()); - jsonSerializer.Serialize(textWriter, message); - await textWriter.FlushAsync(); - await webSocket.SendAsync(responseBuffer.WrittenMemory, WebSocketMessageType.Text, true, CancellationToken.None); - responseBuffer.Clear(); - } - catch (Exception e) - { - Debug.WriteLine("Error during SendMessage " + e.ToString()); - } - } - - void ScheduleMessage(RPC_Message message) - { - messageQueue.Add(message); - } - - async Task ProcessMessageQueue() - { - while (!webSocket.CloseStatus.HasValue) - { - var message = messageQueue.Take(); - await SendMessage(message); - } - } - - public async Task StartReceivingAsync(IProcessInfoAggregator? aggregator = null, IUIHandler? uiHandler = null) - { - Debug.WriteLine("WebSocket connected"); - - var pipe = new Pipe(new PipeOptions(pauseWriterThreshold: 0)); - var messageLength = 0; - - Task.Run(ProcessMessageQueue); - - while (!webSocket.CloseStatus.HasValue) - { - var mem = pipe.Writer.GetMemory(ReceiveBufferSize); - - var receiveResult = await webSocket.ReceiveAsync(mem, CancellationToken.None); - - if (receiveResult.MessageType == WebSocketMessageType.Close) break; - - messageLength += receiveResult.Count; - pipe.Writer.Advance(receiveResult.Count); - - if (receiveResult.EndOfMessage) - { - await pipe.Writer.FlushAsync(); - while (pipe.Reader.TryRead(out var readResult)) - { - if (readResult.Buffer.Length >= messageLength) - { - var messageBuffer = readResult.Buffer.Slice(readResult.Buffer.Start, messageLength); - var message = ParseMessage(messageBuffer); - if (message != null) - { - ReceiveChannel.Received(message, SendChannel, context ?? SendChannel); - } - pipe.Reader.AdvanceTo(messageBuffer.End); - messageLength = 0; - break; - } - - if (readResult.IsCompleted) break; - } - } - } - Debug.WriteLine($"WebSocket closed with status {webSocket.CloseStatus} {webSocket.CloseStatusDescription}"); - if(aggregator != null && uiHandler != null) - aggregator.RemoveUiConnection(uiHandler); - } - - - private RPC_Message? ParseMessage(ReadOnlySequence messageBuffer) - { - var jsonReader = new JsonTextReader(new SequenceTextReader(messageBuffer, Encoding.UTF8)); - var obj = jsonSerializer.Deserialize(jsonReader); - - if (obj == null) - { - throw new InvalidOperationException("Received data is not JSON"); - } - - var action = obj["action"]?.Value(); - if (action == null) - { - throw new ArgumentNullException("The action field is null."); - } - - Type? messageType; - if (RPC_Message.MessageTypesByAction.TryGetValue(action, out messageType) && messageType != null) - { - return (RPC_Message?)obj.ToObject(messageType); - } - - throw new ArgumentException($"Invalid action value {action}"); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Startup.cs b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Startup.cs deleted file mode 100644 index 349a0e35e..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/Startup.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using ModuleProcessMonitor; -using ModuleProcessMonitor.Processes; -using MorganStanley.ComposeUI.Messaging; -using MorganStanley.ComposeUI.Messaging.Client.WebSocket; -using ProcessExplorer; -using ProcessExplorer.Factories; -using SuperRPC_POC.Infrastructure; -using SuperRPC_POC.Infrastructure.Messages; - -namespace SuperRPC_POC; - -public class Startup -{ - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - var loggerFactory = LoggerFactory.Create(builder => - { - builder.AddDebug(); - builder.AddConsole(); - builder.AddFilter(null, LogLevel.Information); - }); - - var processInfoManagerForWindows = - ProcessMonitorFactory.CreateProcessInfoGeneratorWindows(loggerFactory.CreateLogger()); - - var processMonitor = - ProcessMonitorFactory.CreateProcessMonitor(processInfoManagerForWindows, loggerFactory.CreateLogger()); - - var processInfoAggregator = - ProcessAggregatorFactory.CreateProcessInfoAggregator(loggerFactory.CreateLogger(), processMonitor); - - services.AddMessageRouter( - mr => mr.UseWebSocket( - new MessageRouterWebSocketOptions() { Uri = new("ws://localhost:5000/ws") })); - - var processInfoListRouterMessage = - new ProcessInfoListRouterMessage(loggerFactory.CreateLogger(), processInfoAggregator); - - var processInfoRouterMessage = - new ProcessInfoRouterMessage(loggerFactory.CreateLogger(), processInfoAggregator); - - var processMonitorCheckerRouterMessage = - new ProcessMonitorCheckerRouterMessage(loggerFactory.CreateLogger(), - processInfoAggregator); - - var runtimeInfoRouterMessage = new RuntimeInformationRouterMessage(processInfoAggregator, - loggerFactory.CreateLogger()); - - services.AddSingleton(loggerFactory); - services.AddSingleton(processInfoListRouterMessage); - services.AddSingleton(processInfoRouterMessage); - services.AddSingleton(processMonitorCheckerRouterMessage); - services.AddSingleton(runtimeInfoRouterMessage); - services.AddSingleton(); - services.AddSingleton(processInfoAggregator); - services.AddSingleton(processInfoManagerForWindows); - services.AddSingleton(processMonitor); - - services.AddLogging(builder => - { - builder.AddDebug(); - builder.AddConsole(); - builder.AddFilter(null, LogLevel.Debug); - }); - - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseDefaultFiles(); - app.UseStaticFiles(); - app.UseRouting(); - app.UseWebSockets(); - app.UseMiddleware(); - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/SuperRPC-POC.csproj b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/SuperRPC-POC.csproj deleted file mode 100644 index 413d0cefc..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/SuperRPC-POC.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - net6.0 - enable - enable - SuperRPC_POC - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - - - - - - - - - - - - - - - - - diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/appsettings.Development.json b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/appsettings.json b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/appsettings.json deleted file mode 100644 index 81d2855d8..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "Microsoft.AspNetCore": "Debug" - } - }, - "AllowedHosts": "*" -} diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/scripts/npm-build.ps1 b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/scripts/npm-build.ps1 deleted file mode 100644 index 67ecd699f..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/scripts/npm-build.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -cd ..\..\..\..\..\Plugins\ApplicationPlugins\process` explorer\ -npm install diff --git a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/scripts/npm-frontend-start.ps1 b/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/scripts/npm-frontend-start.ps1 deleted file mode 100644 index 7abaae7bd..000000000 --- a/Tryouts/Plugins/ApplicationPlugins/process explorer/backend/SuperRPC-POC/scripts/npm-frontend-start.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -cd ..\..\..\..\..\Plugins\ApplicationPlugins\process` explorer\ -npm start diff --git a/package-lock.json b/package-lock.json index c59046033..126cd37c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3751,121 +3751,11 @@ "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@gar/promisify": { "version": "1.1.3", "dev": true, "license": "MIT" }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -7734,66 +7624,6 @@ } } }, - "node_modules/@schematics/angular": { - "version": "15.1.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@angular-devkit/core": "15.1.4", - "@angular-devkit/schematics": "15.1.4", - "jsonc-parser": "3.2.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "15.1.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "6.6.7", - "source-map": "0.7.4" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@schematics/angular/node_modules/rxjs": { - "version": "6.6.7", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@schematics/angular/node_modules/tslib": { - "version": "1.14.1", - "dev": true, - "license": "0BSD", - "peer": true - }, "node_modules/@sigstore/protobuf-specs": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", @@ -8039,10 +7869,6 @@ "@types/node": "*" } }, - "node_modules/@types/hammerjs": { - "version": "2.0.41", - "license": "MIT" - }, "node_modules/@types/http-proxy": { "version": "1.17.10", "dev": true, @@ -8148,11 +7974,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/semver": { - "version": "7.3.13", - "dev": true, - "license": "MIT" - }, "node_modules/@types/serve-index": { "version": "1.9.1", "dev": true, @@ -8835,25 +8656,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "7.4.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/acorn-walk": { "version": "8.2.0", "dev": true, @@ -9036,6 +8838,7 @@ }, "node_modules/anymatch": { "version": "3.1.3", + "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -9073,14 +8876,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/aria-query": { - "version": "5.1.3", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, "node_modules/array-differ": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", @@ -9177,17 +8972,6 @@ "postcss": "^8.1.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/axios": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", @@ -9198,14 +8982,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/axobject-query": { - "version": "3.1.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, "node_modules/babel-jest": { "version": "29.5.0", "dev": true, @@ -9479,6 +9255,7 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9579,6 +9356,7 @@ }, "node_modules/braces": { "version": "3.0.2", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.0.1" @@ -9837,6 +9615,7 @@ }, "node_modules/chokidar": { "version": "3.5.3", + "dev": true, "funding": [ { "type": "individual", @@ -10022,14 +9801,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/columnify": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", @@ -10553,6 +10324,7 @@ }, "node_modules/core-util-is": { "version": "1.0.3", + "dev": true, "license": "MIT" }, "node_modules/cors": { @@ -10782,38 +10554,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-equal": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, "node_modules/deepmerge": { "version": "4.3.0", "dev": true, @@ -11003,17 +10743,6 @@ "node": ">=6" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serialize": { "version": "2.2.1", "dev": true, @@ -11315,25 +11044,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-module-lexer": { "version": "0.9.3", "dev": true, @@ -11400,270 +11110,6 @@ "dev": true, "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "7.32.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "5.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, "node_modules/esprima": { "version": "4.0.1", "dev": true, @@ -11939,11 +11385,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, "node_modules/fastq": { "version": "1.15.0", "dev": true, @@ -12057,6 +11498,7 @@ }, "node_modules/fill-range": { "version": "7.0.1", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -12132,18 +11574,6 @@ "flat": "cli.js" } }, - "node_modules/flat-cache": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, "node_modules/flatted": { "version": "3.2.7", "dev": true, @@ -12290,19 +11720,6 @@ "dev": true, "license": "MIT" }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gauge": { "version": "4.0.4", "dev": true, @@ -12558,6 +11975,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -12617,34 +12035,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.10", "dev": true, "license": "ISC" }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/hammerjs": { - "version": "2.0.8", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/handle-thing": { "version": "2.0.1", "dev": true, @@ -12700,14 +12095,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "4.0.0", "dev": true, @@ -12716,17 +12103,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.0.3", "dev": true, @@ -12738,20 +12114,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-unicode": { "version": "2.0.1", "dev": true, @@ -13054,63 +12416,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/igniteui-angular": { - "version": "15.0.15", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@igniteui/material-icons-extended": "^2.10.0", - "@types/hammerjs": "^2.0.40", - "fflate": "^0.7.3", - "hammerjs": "^2.0.8", - "igniteui-theming": "^1.4.1", - "igniteui-trial-watermark": "^1.0.3", - "lodash-es": "^4.17.21", - "tslib": "^2.3.0", - "uuid": "^8.3.0" - }, - "peerDependencies": { - "@angular/animations": "^15.0.0", - "@angular/common": "^15.0.0", - "@angular/core": "^15.0.0", - "@angular/forms": "^15.0.0" - } - }, - "node_modules/igniteui-angular-charts": { - "version": "15.0.0", - "license": "Infragistics(R) Ultimate license (http://www.infragistics.com/legal/ultimate/license/)", - "dependencies": { - "tslib": "^2.3.1" - }, - "peerDependencies": { - "@angular/common": "^15.0.0", - "@angular/compiler": "^15.0.0", - "@angular/core": "^15.0.0", - "igniteui-angular-core": "15.0.0" - } - }, - "node_modules/igniteui-angular-core": { - "version": "15.0.0", - "license": "Infragistics(R) Ultimate license (http://www.infragistics.com/legal/ultimate/license/)", - "dependencies": { - "tslib": "^2.3.1" - }, - "peerDependencies": { - "@angular/common": "^15.0.0", - "@angular/compiler": "^15.0.0", - "@angular/core": "^15.0.0" - } - }, - "node_modules/igniteui-theming": { - "version": "1.4.1", - "license": "MIT", - "peerDependencies": { - "sass": "^1.53.0" - } - }, - "node_modules/igniteui-trial-watermark": { - "version": "1.0.3", - "license": "Apache-2.0" - }, "node_modules/ignore": { "version": "5.2.4", "dev": true, @@ -13164,12 +12469,9 @@ "node": ">=0.10.0" } }, - "node_modules/immediate": { - "version": "3.0.6", - "license": "MIT" - }, "node_modules/immutable": { "version": "4.2.4", + "dev": true, "license": "MIT" }, "node_modules/import-fresh": { @@ -13245,6 +12547,7 @@ }, "node_modules/inherits": { "version": "2.0.4", + "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -13344,19 +12647,6 @@ "node": ">=12.0.0" } }, - "node_modules/internal-slot": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/ip": { "version": "2.0.0", "dev": true, @@ -13370,52 +12660,14 @@ "node": ">= 0.10" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "dev": true, "license": "MIT" }, - "node_modules/is-bigint": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", + "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -13424,21 +12676,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-builtin-module": { "version": "3.2.1", "dev": true, @@ -13453,17 +12690,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -13487,20 +12713,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-docker": { "version": "2.2.1", "dev": true, @@ -13517,6 +12729,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13540,6 +12753,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -13561,14 +12775,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-map": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-module": { "version": "1.0.0", "dev": true, @@ -13576,23 +12782,10 @@ }, "node_modules/is-number": { "version": "7.0.0", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", "dev": true, "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.12.0" } }, "node_modules/is-obj": { @@ -13648,40 +12841,6 @@ "@types/estree": "*" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-ssh": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", @@ -13702,34 +12861,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-string": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -13771,26 +12902,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-what": { "version": "3.14.1", "dev": true, @@ -13807,11 +12918,6 @@ "node": ">=8" } }, - "node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, "node_modules/isbinaryfile": { "version": "4.0.10", "dev": true, @@ -13954,14 +13060,6 @@ "dev": true, "license": "MIT" }, - "node_modules/jasmine-spec-reporter": { - "version": "7.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "colors": "1.4.0" - } - }, "node_modules/jest": { "version": "29.5.0", "dev": true, @@ -14681,11 +13779,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/json-stringify-nice": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", @@ -14753,44 +13846,6 @@ "node": "*" } }, - "node_modules/jszip": { - "version": "3.10.1", - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/jszip/node_modules/isarray": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/jszip/node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" - }, - "node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/just-diff": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", @@ -15382,18 +14437,6 @@ "node": ">=6" } }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/libnpmaccess": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.3.tgz", @@ -15618,13 +14661,6 @@ } } }, - "node_modules/lie": { - "version": "3.3.0", - "license": "MIT", - "dependencies": { - "immediate": "~3.0.5" - } - }, "node_modules/lines-and-columns": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", @@ -15690,10 +14726,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash-es": { - "version": "4.17.21", - "license": "MIT" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "dev": true, @@ -15710,16 +14742,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "dev": true, - "license": "MIT" - }, "node_modules/log-symbols": { "version": "4.1.0", "dev": true, @@ -16388,10 +15410,6 @@ "dev": true, "license": "ISC" }, - "node_modules/minireset.css": { - "version": "0.0.7", - "license": "MIT" - }, "node_modules/minizlib": { "version": "2.1.2", "dev": true, @@ -16519,11 +15537,6 @@ "dev": true, "license": "MIT" }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/needle": { "version": "3.2.0", "dev": true, @@ -16757,6 +15770,7 @@ }, "node_modules/normalize-path": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -17307,46 +16321,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/obuf": { "version": "1.1.2", "dev": true, @@ -17416,22 +16390,6 @@ "opener": "bin/opener-bin.js" } }, - "node_modules/optionator": { - "version": "0.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/ora": { "version": "5.4.1", "dev": true, @@ -17901,6 +16859,7 @@ }, "node_modules/pako": { "version": "1.0.11", + "dev": true, "license": "(MIT AND Zlib)" }, "node_modules/parent-module": { @@ -18151,6 +17110,7 @@ }, "node_modules/picomatch": { "version": "2.3.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -18359,14 +17319,6 @@ "dev": true, "license": "MIT" }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/pretty-bytes": { "version": "5.6.0", "dev": true, @@ -18422,15 +17374,8 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", - "license": "MIT" - }, - "node_modules/progress": { - "version": "2.0.3", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } + "license": "MIT" }, "node_modules/promise-all-reject-late": { "version": "1.0.1", @@ -18943,6 +17888,7 @@ }, "node_modules/readdirp": { "version": "3.6.0", + "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -19004,33 +17950,6 @@ "dev": true, "license": "MIT" }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/regexpu-core": { "version": "5.3.1", "dev": true, @@ -19349,6 +18268,7 @@ }, "node_modules/sass": { "version": "1.58.1", + "dev": true, "license": "MIT", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -19614,6 +18534,7 @@ }, "node_modules/setimmediate": { "version": "1.0.5", + "dev": true, "license": "MIT" }, "node_modules/setprototypeof": { @@ -19763,22 +18684,6 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "dev": true, @@ -19882,6 +18787,7 @@ }, "node_modules/source-map-js": { "version": "1.0.2", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -19935,11 +18841,6 @@ "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "dev": true, - "license": "MIT" - }, "node_modules/spdx-correct": { "version": "3.1.1", "dev": true, @@ -20076,17 +18977,6 @@ "node": ">= 0.8" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/streamroller": { "version": "3.1.5", "dev": true, @@ -20257,10 +19147,6 @@ "node": ">=4" } }, - "node_modules/super-rpc": { - "version": "1.0.1", - "license": "MIT" - }, "node_modules/supports-color": { "version": "7.2.0", "dev": true, @@ -20291,21 +19177,6 @@ "node": ">=0.10" } }, - "node_modules/table": { - "version": "6.8.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/tapable": { "version": "2.2.1", "dev": true, @@ -20601,10 +19472,6 @@ "dev": true, "license": "MIT" }, - "node_modules/throttle-typescript": { - "version": "1.1.0", - "license": "MIT" - }, "node_modules/through": { "version": "2.3.8", "dev": true, @@ -20682,6 +19549,7 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -20861,25 +19729,6 @@ "version": "2.5.0", "license": "0BSD" }, - "node_modules/tsutils": { - "version": "3.21.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "dev": true, - "license": "0BSD" - }, "node_modules/tuf-js": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.5.tgz", @@ -20966,17 +19815,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "dev": true, @@ -21215,6 +20053,7 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "dev": true, "license": "MIT" }, "node_modules/utils-merge": { @@ -21227,6 +20066,7 @@ }, "node_modules/uuid": { "version": "8.3.2", + "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -21334,10 +20174,6 @@ "defaults": "^1.0.3" } }, - "node_modules/web-animations-js": { - "version": "2.3.2", - "license": "Apache-2.0" - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -21703,54 +20539,6 @@ "node": ">= 8" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/wide-align": { "version": "1.1.5", "dev": true, @@ -21764,14 +20552,6 @@ "dev": true, "license": "MIT" }, - "node_modules/word-wrap": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -24932,84 +23712,10 @@ "dev": true, "optional": true }, - "@eslint/eslintrc": { - "version": "0.4.3", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "dev": 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" - } - }, - "argparse": { - "version": "1.0.10", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "globals": { - "version": "13.20.0", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "ignore": { - "version": "4.0.6", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "dev": true - } - } - }, "@gar/promisify": { "version": "1.1.3", "dev": true }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true - }, "@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -29068,43 +27774,6 @@ "picomatch": "^2.3.1" } }, - "@schematics/angular": { - "version": "15.1.4", - "dev": true, - "peer": true, - "requires": { - "@angular-devkit/core": "15.1.4", - "@angular-devkit/schematics": "15.1.4", - "jsonc-parser": "3.2.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "15.1.4", - "dev": true, - "peer": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "6.6.7", - "source-map": "0.7.4" - } - }, - "rxjs": { - "version": "6.6.7", - "dev": true, - "peer": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "dev": true, - "peer": true - } - } - }, "@sigstore/protobuf-specs": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", @@ -29309,9 +27978,6 @@ "@types/node": "*" } }, - "@types/hammerjs": { - "version": "2.0.41" - }, "@types/http-proxy": { "version": "1.17.10", "dev": true, @@ -29402,10 +28068,6 @@ "version": "0.12.0", "dev": true }, - "@types/semver": { - "version": "7.3.13", - "dev": true - }, "@types/serve-index": { "version": "1.9.1", "dev": true, @@ -29847,15 +28509,6 @@ "negotiator": "0.6.3" } }, - "acorn": { - "version": "7.4.1", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "dev": true, - "requires": {} - }, "acorn-walk": { "version": "8.2.0", "dev": true @@ -29967,6 +28620,7 @@ }, "anymatch": { "version": "3.1.3", + "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -29994,13 +28648,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "aria-query": { - "version": "5.1.3", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, "array-differ": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", @@ -30027,10 +28674,6 @@ "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true }, - "astral-regex": { - "version": "2.0.0", - "dev": true - }, "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", @@ -30058,10 +28701,6 @@ "postcss-value-parser": "^4.2.0" } }, - "available-typed-arrays": { - "version": "1.0.5", - "dev": true - }, "axios": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", @@ -30072,13 +28711,6 @@ "proxy-from-env": "^1.1.0" } }, - "axobject-query": { - "version": "3.1.1", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, "babel-jest": { "version": "29.5.0", "dev": true, @@ -30259,7 +28891,8 @@ } }, "binary-extensions": { - "version": "2.2.0" + "version": "2.2.0", + "dev": true }, "bl": { "version": "4.1.0", @@ -30335,6 +28968,7 @@ }, "braces": { "version": "3.0.2", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -30482,6 +29116,7 @@ }, "chokidar": { "version": "3.5.3", + "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -30597,10 +29232,6 @@ "version": "2.0.19", "dev": true }, - "colors": { - "version": "1.4.0", - "dev": true - }, "columnify": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", @@ -30995,7 +29626,8 @@ } }, "core-util-is": { - "version": "1.0.3" + "version": "1.0.3", + "dev": true }, "cors": { "version": "2.8.5", @@ -31144,33 +29776,6 @@ "version": "0.7.0", "dev": true }, - "deep-equal": { - "version": "2.2.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "deep-is": { - "version": "0.1.4", - "dev": true - }, "deepmerge": { "version": "4.3.0", "dev": true @@ -31288,13 +29893,6 @@ "@leichtgewicht/ip-codec": "^2.0.1" } }, - "doctrine": { - "version": "3.0.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, "dom-serialize": { "version": "2.2.1", "dev": true, @@ -31498,21 +30096,6 @@ "is-arrayish": "^0.2.1" } }, - "es-get-iterator": { - "version": "1.1.3", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - } - }, "es-module-lexer": { "version": "0.9.3", "dev": true @@ -31558,178 +30141,6 @@ "version": "1.0.3", "dev": true }, - "escape-string-regexp": { - "version": "4.0.0", - "dev": true - }, - "eslint": { - "version": "7.32.0", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "ajv": { - "version": "6.12.6", - "dev": 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" - } - }, - "argparse": { - "version": "1.0.10", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "eslint-scope": { - "version": "5.1.1", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "dev": true - }, - "estraverse": { - "version": "4.3.0", - "dev": true - }, - "globals": { - "version": "13.20.0", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "ignore": { - "version": "4.0.6", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "dev": true - } - } - }, - "eslint-scope": { - "version": "7.1.1", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "dev": true - }, - "espree": { - "version": "7.3.1", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "dev": true - } - } - }, "esprima": { "version": "4.0.1", "dev": true @@ -31924,10 +30335,6 @@ "version": "2.1.0", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "dev": true - }, "fastq": { "version": "1.15.0", "dev": true, @@ -32017,6 +30424,7 @@ }, "fill-range": { "version": "7.0.1", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -32070,14 +30478,6 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, - "flat-cache": { - "version": "3.0.4", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, "flatted": { "version": "3.2.7", "dev": true @@ -32167,14 +30567,6 @@ "version": "1.1.1", "dev": true }, - "functional-red-black-tree": { - "version": "1.0.1", - "dev": true - }, - "functions-have-names": { - "version": "1.2.3", - "dev": true - }, "gauge": { "version": "4.0.4", "dev": true, @@ -32383,6 +30775,7 @@ }, "glob-parent": { "version": "5.1.2", + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -32407,24 +30800,10 @@ "slash": "^3.0.0" } }, - "gopd": { - "version": "1.0.1", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, "graceful-fs": { "version": "4.2.10", "dev": true }, - "grapheme-splitter": { - "version": "1.0.4", - "dev": true - }, - "hammerjs": { - "version": "2.0.8" - }, "handle-thing": { "version": "2.0.1", "dev": true @@ -32463,32 +30842,14 @@ "function-bind": "^1.1.1" } }, - "has-bigints": { - "version": "1.0.2", - "dev": true - }, "has-flag": { "version": "4.0.0", "dev": true }, - "has-property-descriptors": { - "version": "1.0.0", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, "has-symbols": { "version": "1.0.3", "dev": true }, - "has-tostringtag": { - "version": "1.0.0", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, "has-unicode": { "version": "2.0.1", "dev": true @@ -32697,39 +31058,6 @@ "version": "1.2.1", "dev": true }, - "igniteui-angular": { - "version": "15.0.15", - "requires": { - "@igniteui/material-icons-extended": "^2.10.0", - "@types/hammerjs": "^2.0.40", - "fflate": "^0.7.3", - "hammerjs": "^2.0.8", - "igniteui-theming": "^1.4.1", - "igniteui-trial-watermark": "^1.0.3", - "lodash-es": "^4.17.21", - "tslib": "^2.3.0", - "uuid": "^8.3.0" - } - }, - "igniteui-angular-charts": { - "version": "15.0.0", - "requires": { - "tslib": "^2.3.1" - } - }, - "igniteui-angular-core": { - "version": "15.0.0", - "requires": { - "tslib": "^2.3.1" - } - }, - "igniteui-theming": { - "version": "1.4.1", - "requires": {} - }, - "igniteui-trial-watermark": { - "version": "1.0.3" - }, "ignore": { "version": "5.2.4", "dev": true @@ -32768,11 +31096,9 @@ "dev": true, "optional": true }, - "immediate": { - "version": "3.0.6" - }, "immutable": { - "version": "4.2.4" + "version": "4.2.4", + "dev": true }, "import-fresh": { "version": "3.3.0", @@ -32817,7 +31143,8 @@ } }, "inherits": { - "version": "2.0.4" + "version": "2.0.4", + "dev": true }, "ini": { "version": "3.0.1", @@ -32896,15 +31223,6 @@ "wrap-ansi": "^7.0.0" } }, - "internal-slot": { - "version": "1.0.5", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, "ip": { "version": "2.0.0", "dev": true @@ -32913,46 +31231,15 @@ "version": "1.9.1", "dev": true }, - "is-arguments": { - "version": "1.1.1", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, "is-arrayish": { "version": "0.2.1", "dev": true }, - "is-bigint": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, "is-binary-path": { "version": "2.1.0", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-builtin-module": { @@ -32962,10 +31249,6 @@ "builtin-modules": "^3.3.0" } }, - "is-callable": { - "version": "1.2.7", - "dev": true - }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -32982,19 +31265,13 @@ "has": "^1.0.3" } }, - "is-date-object": { - "version": "1.0.5", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, "is-docker": { "version": "2.2.1", "dev": true }, "is-extglob": { - "version": "2.1.1" + "version": "2.1.1", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -33006,6 +31283,7 @@ }, "is-glob": { "version": "4.0.3", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -33018,23 +31296,13 @@ "version": "1.0.1", "dev": true }, - "is-map": { - "version": "2.0.2", - "dev": true - }, "is-module": { "version": "1.0.0", "dev": true }, "is-number": { - "version": "7.0.0" - }, - "is-number-object": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } + "version": "7.0.0", + "dev": true }, "is-obj": { "version": "2.0.0", @@ -33073,25 +31341,6 @@ "@types/estree": "*" } }, - "is-regex": { - "version": "1.1.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.2", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, "is-ssh": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", @@ -33105,20 +31354,6 @@ "version": "2.0.1", "dev": true }, - "is-string": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -33143,18 +31378,6 @@ "version": "0.1.0", "dev": true }, - "is-weakmap": { - "version": "2.0.1", - "dev": true - }, - "is-weakset": { - "version": "2.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, "is-what": { "version": "3.14.1", "dev": true @@ -33166,10 +31389,6 @@ "is-docker": "^2.0.0" } }, - "isarray": { - "version": "2.0.5", - "dev": true - }, "isbinaryfile": { "version": "4.0.10", "dev": true @@ -33261,13 +31480,6 @@ "version": "4.5.0", "dev": true }, - "jasmine-spec-reporter": { - "version": "7.0.0", - "dev": true, - "requires": { - "colors": "1.4.0" - } - }, "jest": { "version": "29.5.0", "dev": true, @@ -33763,10 +31975,6 @@ "version": "1.0.0", "dev": true }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true - }, "json-stringify-nice": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", @@ -33811,41 +32019,6 @@ "through": ">=2.2.7 <3" } }, - "jszip": { - "version": "3.10.1", - "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0" - }, - "readable-stream": { - "version": "2.3.8", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2" - }, - "string_decoder": { - "version": "1.1.1", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "just-diff": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", @@ -34278,14 +32451,6 @@ "version": "3.1.0", "dev": true }, - "levn": { - "version": "0.4.1", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, "libnpmaccess": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.3.tgz", @@ -34460,12 +32625,6 @@ "webpack-sources": "^3.0.0" } }, - "lie": { - "version": "3.3.0", - "requires": { - "immediate": "~3.0.5" - } - }, "lines-and-columns": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", @@ -34511,9 +32670,6 @@ "version": "4.17.21", "dev": true }, - "lodash-es": { - "version": "4.17.21" - }, "lodash.debounce": { "version": "4.0.8", "dev": true @@ -34528,14 +32684,6 @@ "version": "4.1.2", "dev": true }, - "lodash.merge": { - "version": "4.6.2", - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "dev": true - }, "log-symbols": { "version": "4.1.0", "dev": true, @@ -35003,9 +33151,6 @@ } } }, - "minireset.css": { - "version": "0.0.7" - }, "minizlib": { "version": "2.1.2", "dev": true, @@ -35092,10 +33237,6 @@ "version": "1.4.0", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "dev": true - }, "needle": { "version": "3.2.0", "dev": true, @@ -35258,7 +33399,8 @@ } }, "normalize-path": { - "version": "3.0.0" + "version": "3.0.0", + "dev": true }, "normalize-range": { "version": "0.1.2", @@ -35683,28 +33825,6 @@ "version": "1.12.3", "dev": true }, - "object-is": { - "version": "1.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, "obuf": { "version": "1.1.2", "dev": true @@ -35746,18 +33866,6 @@ "version": "1.5.2", "dev": true }, - "optionator": { - "version": "0.9.1", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, "ora": { "version": "5.4.1", "dev": true, @@ -36099,7 +34207,8 @@ } }, "pako": { - "version": "1.0.11" + "version": "1.0.11", + "dev": true }, "parent-module": { "version": "1.0.1", @@ -36275,7 +34384,8 @@ "dev": true }, "picomatch": { - "version": "2.3.1" + "version": "2.3.1", + "dev": true }, "pify": { "version": "5.0.0", @@ -36394,10 +34504,6 @@ "version": "4.2.0", "dev": true }, - "prelude-ls": { - "version": "1.2.1", - "dev": true - }, "pretty-bytes": { "version": "5.6.0", "dev": true @@ -36430,10 +34536,7 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.1" - }, - "progress": { - "version": "2.0.3", + "version": "2.0.1", "dev": true }, "promise-all-reject-late": { @@ -36806,6 +34909,7 @@ }, "readdirp": { "version": "3.6.0", + "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -36852,19 +34956,6 @@ "version": "2.2.11", "dev": true }, - "regexp.prototype.flags": { - "version": "1.4.3", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "dev": true - }, "regexpu-core": { "version": "5.3.1", "dev": true, @@ -37053,6 +35144,7 @@ }, "sass": { "version": "1.58.1", + "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -37229,7 +35321,8 @@ "dev": true }, "setimmediate": { - "version": "1.0.5" + "version": "1.0.5", + "dev": true }, "setprototypeof": { "version": "1.2.0", @@ -37337,15 +35430,6 @@ "version": "3.0.0", "dev": true }, - "slice-ansi": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, "smart-buffer": { "version": "4.2.0", "dev": true @@ -37417,7 +35501,8 @@ "dev": true }, "source-map-js": { - "version": "1.0.2" + "version": "1.0.2", + "dev": true }, "source-map-loader": { "version": "4.0.1", @@ -37451,10 +35536,6 @@ } } }, - "sourcemap-codec": { - "version": "1.4.8", - "dev": true - }, "spdx-correct": { "version": "3.1.1", "dev": true, @@ -37561,13 +35642,6 @@ "version": "2.0.1", "dev": true }, - "stop-iteration-iterator": { - "version": "1.0.0", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, "streamroller": { "version": "3.1.5", "dev": true, @@ -37682,9 +35756,6 @@ "through": "^2.3.4" } }, - "super-rpc": { - "version": "1.0.1" - }, "supports-color": { "version": "7.2.0", "dev": true, @@ -37700,17 +35771,6 @@ "version": "4.0.0", "dev": true }, - "table": { - "version": "6.8.1", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, "tapable": { "version": "2.2.1", "dev": true @@ -37901,9 +35961,6 @@ "version": "0.2.0", "dev": true }, - "throttle-typescript": { - "version": "1.1.0" - }, "through": { "version": "2.3.8", "dev": true @@ -37967,6 +36024,7 @@ }, "to-regex-range": { "version": "5.0.1", + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -38066,19 +36124,6 @@ "tslib": { "version": "2.5.0" }, - "tsutils": { - "version": "3.21.0", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "dev": true - } - } - }, "tuf-js": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.5.tgz", @@ -38147,13 +36192,6 @@ } } }, - "type-check": { - "version": "0.4.0", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, "type-detect": { "version": "4.0.8", "dev": true @@ -38287,14 +36325,16 @@ "dev": true }, "util-deprecate": { - "version": "1.0.2" + "version": "1.0.2", + "dev": true }, "utils-merge": { "version": "1.0.1", "dev": true }, "uuid": { - "version": "8.3.2" + "version": "8.3.2", + "dev": true }, "v8-compile-cache": { "version": "2.3.0", @@ -38373,9 +36413,6 @@ "defaults": "^1.0.3" } }, - "web-animations-js": { - "version": "2.3.2" - }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -38607,39 +36644,6 @@ "isexe": "^2.0.0" } }, - "which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-collection": { - "version": "1.0.1", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-typed-array": { - "version": "1.1.9", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - } - }, "wide-align": { "version": "1.1.5", "dev": true, @@ -38651,10 +36655,6 @@ "version": "2.0.0", "dev": true }, - "word-wrap": { - "version": "1.2.3", - "dev": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/Infrastructure/LocalProcessCommunicator.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/Infrastructure/LocalProcessCommunicator.cs deleted file mode 100644 index 6c616f58b..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/Infrastructure/LocalProcessCommunicator.cs +++ /dev/null @@ -1,120 +0,0 @@ -// /* -// * Morgan Stanley makes this available to you under the Apache License, -// * Version 2.0 (the "License"). You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0. -// * -// * See the NOTICE file distributed with this work for additional information -// * regarding copyright ownership. Unless required by applicable law or agreed -// * to in writing, software distributed under the License is distributed on an -// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// * or implied. See the License for the specific language governing permissions -// * and limitations under the License. -// */ - -using LocalCollector; -using LocalCollector.Communicator; -using LocalCollector.Connections; -using LocalCollector.Modules; -using LocalCollector.Registrations; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorerMessageRouterTopics; -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Threading.Tasks; - -namespace WPFDataGrid.Infrastructure; - -internal class LocalProcessCommunicator : ICommunicator -{ - private readonly IMessageRouter _messageRouter; - private readonly ILogger _logger; - - public LocalProcessCommunicator(IMessageRouter messageRouter, - ILogger? logger = null) - { - _messageRouter = messageRouter; - _logger = logger ?? NullLogger.Instance; - } - - public async ValueTask AddConnectionCollection(IEnumerable>> connections) - { - try - { - var serializedConnections = JsonSerializer.Serialize(connections); - await _messageRouter.PublishAsync(Topics.addingConnections, serializedConnections); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing to topic: {Topics.addingConnections}... {exception}"); - } - } - - public async ValueTask AddRuntimeInfo(IEnumerable> listOfRuntimeInfo) - { - try - { - var serializedRuntimeInfo = JsonSerializer.Serialize(listOfRuntimeInfo); - await _messageRouter.PublishAsync(Topics.updatingRuntime, serializedRuntimeInfo); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing to topic: {Topics.updatingRuntime}... {exception}"); - } - } - - public async ValueTask UpdateConnectionInformation(IEnumerable> connections) - { - try - { - var serializedConnections = JsonSerializer.Serialize(connections); - await _messageRouter.PublishAsync(Topics.updatingConnection, serializedConnections); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing to topic: {Topics.updatingConnection}... {exception}"); - } - } - - public async ValueTask UpdateEnvironmentVariableInformation(IEnumerable>>> environmentVariables) - { - try - { - var serializedEnvs = JsonSerializer.Serialize(environmentVariables); - await _messageRouter.PublishAsync(Topics.updatingEnvironmentVariables, serializedEnvs); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing to topic: {Topics.updatingEnvironmentVariables}... {exception}"); - } - } - - public async ValueTask UpdateModuleInformation(IEnumerable>> modules) - { - try - { - var serializedModules = JsonSerializer.Serialize(modules); - await _messageRouter.PublishAsync(Topics.updatingModules, serializedModules); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing to topic: {Topics.updatingModules}... {exception}"); - } - } - - public async ValueTask UpdateRegistrationInformation(IEnumerable>> registrations) - { - try - { - var serializedRegistrations = JsonSerializer.Serialize(registrations); - await _messageRouter.PublishAsync(Topics.updatingRegistrations, serializedRegistrations); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while subscribing to topic: {Topics.updatingRegistrations}... {exception}"); - } - } -} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/WPFDataGrid.csproj b/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/WPFDataGrid.csproj index 1fd74f313..9c1cbfbe9 100644 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/WPFDataGrid.csproj +++ b/prototypes/multi-module-prototype/examples/multi-module-example/ComposeUI.Example.WPFDataGrid/WPFDataGrid.csproj @@ -23,7 +23,5 @@ - - diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype.sln b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype.sln index b1ba8e006..dbd997ce1 100644 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype.sln +++ b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype.sln @@ -21,19 +21,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPFDataGrid.TestApp", "Comp EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Process Explorer", "Process Explorer", "{BF3D9176-E2B0-4C87-9691-8288C257BFAF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocalCollector", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\process explorer\backend\LocalCollector\LocalCollector.csproj", "{FDD9C089-5DC8-4194-AA82-51E915D249AF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModuleProcessMonitor", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\process explorer\backend\ModuleProcessMonitor\ModuleProcessMonitor.csproj", "{B41C1EEC-7EB1-43BB-995D-5E0E2809B16B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\process explorer\backend\ProcessExplorer\ProcessExplorer.csproj", "{89A8A63B-BC4E-4443-AC40-4F2D79BAED5D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuperRPC-POC", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\process explorer\backend\SuperRPC-POC\SuperRPC-POC.csproj", "{9AF6AF79-0261-4C1B-A904-00DA29A04F12}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{E761C6B7-625B-47D8-811B-A67B3E7221D5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorerMessageRouterTopics", "ProcessExplorerMessageRouterTopics\ProcessExplorerMessageRouterTopics.csproj", "{B00789CA-40D7-462D-8A1D-11C672B30512}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Abstractions", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\MorganStanley.ComposeUI.ProcessExplorer\dotnet\src\ProcessExplorer.Abstractions\ProcessExplorer.Abstractions.csproj", "{81560FF4-912B-4993-A132-D4E8B4F3AC83}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{DFABC3EE-C089-4E76-AE83-76FBD6C407C6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Core", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\MorganStanley.ComposeUI.ProcessExplorer\dotnet\src\ProcessExplorer.Core\ProcessExplorer.Core.csproj", "{1E6E6698-CA30-4B30-B6A6-F58D9C7E4C90}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{E761C6B7-625B-47D8-811B-A67B3E7221D5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessExplorer.Server", "..\..\..\..\Tryouts\Plugins\ApplicationPlugins\MorganStanley.ComposeUI.ProcessExplorer\dotnet\src\ProcessExplorer.Server\ProcessExplorer.Server.csproj", "{44D71CFD-7E68-46E5-8A3C-D18CEB80E11E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -73,44 +67,30 @@ Global {21BA0993-6F19-4549-8884-CB4C7FAE34A8}.Debug|Any CPU.Build.0 = Debug|Any CPU {21BA0993-6F19-4549-8884-CB4C7FAE34A8}.Release|Any CPU.ActiveCfg = Release|Any CPU {21BA0993-6F19-4549-8884-CB4C7FAE34A8}.Release|Any CPU.Build.0 = Release|Any CPU - {FDD9C089-5DC8-4194-AA82-51E915D249AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FDD9C089-5DC8-4194-AA82-51E915D249AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FDD9C089-5DC8-4194-AA82-51E915D249AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FDD9C089-5DC8-4194-AA82-51E915D249AF}.Release|Any CPU.Build.0 = Release|Any CPU - {B41C1EEC-7EB1-43BB-995D-5E0E2809B16B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B41C1EEC-7EB1-43BB-995D-5E0E2809B16B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B41C1EEC-7EB1-43BB-995D-5E0E2809B16B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B41C1EEC-7EB1-43BB-995D-5E0E2809B16B}.Release|Any CPU.Build.0 = Release|Any CPU - {89A8A63B-BC4E-4443-AC40-4F2D79BAED5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89A8A63B-BC4E-4443-AC40-4F2D79BAED5D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89A8A63B-BC4E-4443-AC40-4F2D79BAED5D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89A8A63B-BC4E-4443-AC40-4F2D79BAED5D}.Release|Any CPU.Build.0 = Release|Any CPU - {9AF6AF79-0261-4C1B-A904-00DA29A04F12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9AF6AF79-0261-4C1B-A904-00DA29A04F12}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9AF6AF79-0261-4C1B-A904-00DA29A04F12}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9AF6AF79-0261-4C1B-A904-00DA29A04F12}.Release|Any CPU.Build.0 = Release|Any CPU - {B00789CA-40D7-462D-8A1D-11C672B30512}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B00789CA-40D7-462D-8A1D-11C672B30512}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B00789CA-40D7-462D-8A1D-11C672B30512}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B00789CA-40D7-462D-8A1D-11C672B30512}.Release|Any CPU.Build.0 = Release|Any CPU + {81560FF4-912B-4993-A132-D4E8B4F3AC83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81560FF4-912B-4993-A132-D4E8B4F3AC83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81560FF4-912B-4993-A132-D4E8B4F3AC83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81560FF4-912B-4993-A132-D4E8B4F3AC83}.Release|Any CPU.Build.0 = Release|Any CPU + {1E6E6698-CA30-4B30-B6A6-F58D9C7E4C90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E6E6698-CA30-4B30-B6A6-F58D9C7E4C90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E6E6698-CA30-4B30-B6A6-F58D9C7E4C90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E6E6698-CA30-4B30-B6A6-F58D9C7E4C90}.Release|Any CPU.Build.0 = Release|Any CPU + {44D71CFD-7E68-46E5-8A3C-D18CEB80E11E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44D71CFD-7E68-46E5-8A3C-D18CEB80E11E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44D71CFD-7E68-46E5-8A3C-D18CEB80E11E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44D71CFD-7E68-46E5-8A3C-D18CEB80E11E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {2D16F7EF-D833-4D9C-90C0-C633F8E33A2B} = {DFABC3EE-C089-4E76-AE83-76FBD6C407C6} - {6019D5A5-3D0C-4A30-8025-B8F30050BEB6} = {DFABC3EE-C089-4E76-AE83-76FBD6C407C6} - {11D505AF-310E-4536-A6DA-3E8DB053D1D6} = {DFABC3EE-C089-4E76-AE83-76FBD6C407C6} - {47CA77F0-3D59-47A6-AE1F-A2BAE2F72222} = {DFABC3EE-C089-4E76-AE83-76FBD6C407C6} {C20FA602-71E5-4383-8F8F-B966873EFA69} = {E761C6B7-625B-47D8-811B-A67B3E7221D5} {EFF70E7E-C320-4F47-8A13-C1FE5C8F2982} = {E761C6B7-625B-47D8-811B-A67B3E7221D5} {21BA0993-6F19-4549-8884-CB4C7FAE34A8} = {E761C6B7-625B-47D8-811B-A67B3E7221D5} {BF3D9176-E2B0-4C87-9691-8288C257BFAF} = {E761C6B7-625B-47D8-811B-A67B3E7221D5} - {FDD9C089-5DC8-4194-AA82-51E915D249AF} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} - {B41C1EEC-7EB1-43BB-995D-5E0E2809B16B} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} - {89A8A63B-BC4E-4443-AC40-4F2D79BAED5D} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} - {9AF6AF79-0261-4C1B-A904-00DA29A04F12} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} - {B00789CA-40D7-462D-8A1D-11C672B30512} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} + {81560FF4-912B-4993-A132-D4E8B4F3AC83} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} + {1E6E6698-CA30-4B30-B6A6-F58D9C7E4C90} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} + {44D71CFD-7E68-46E5-8A3C-D18CEB80E11E} = {BF3D9176-E2B0-4C87-9691-8288C257BFAF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {98497725-4038-46B9-910E-2BADC6FDC7E4} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/IProcessInfoHandler.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/IProcessInfoHandler.cs deleted file mode 100644 index 386a8fd52..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/IProcessInfoHandler.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using ModuleProcessMonitor.Processes; -using MorganStanley.ComposeUI.Tryouts.Core.Abstractions.Modules; - -namespace ModulesPrototype; - -public interface IProcessInfoHandler -{ - ValueTask SendInitProcessInfoAsync(IEnumerable processInfo); - void SendAddProcessInfo(ProcessInfoData processInfo); - ValueTask EnableProcessMonitorAsync(); - ValueTask DisableProcessMonitorAsync(); - ValueTask SendModifiedSubsystemStateAsync(Guid instanceId, string state); - ValueTask InitializeSubsystemControllerRouteAsync(); - ValueTask SendRegisteredSubsystemsAsync(string subsystems); - void SetSubsystemHandler(IModuleLoader moduleLoader, ILoggerFactory? loggerFactory = null); -} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/Messages/SubsystemHandlerRouterMessage.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/Messages/SubsystemHandlerRouterMessage.cs deleted file mode 100644 index cf124f51a..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/Messages/SubsystemHandlerRouterMessage.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System; -using System.Collections.Generic; -using System.Text.Json; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Subsystems; -using MorganStanley.ComposeUI.Messaging; -using ProcessExplorerMessageRouterTopics; - -namespace ModulesPrototype.Infrastructure.Messages; - -internal class SubsystemHandlerRouterMessage : IObserver -{ - private readonly ILogger _logger; - private readonly ISubsystemLauncher _subsystemLauncher; - - public SubsystemHandlerRouterMessage(ILogger? logger, - ISubsystemLauncher subsystemLauncher) - { - _logger = logger ?? NullLogger.Instance; - _subsystemLauncher = subsystemLauncher; - } - - public void OnCompleted() - { - _logger.LogInformation("Received all of the information for the current message"); - } - - public void OnError(Exception exception) - { - _logger.LogError($"Some error(s) occurred while receiving the process information from module loader... : {exception}"); - } - - public void OnNext(TopicMessage value) - { - var payload = value.Payload; - if (payload is null) - { - return; - } - - var topic = value.Topic; - try - { - switch (topic) - { - case Topics.launchingSubsystemWithDelay: - var subsystem = JsonSerializer.Deserialize>(payload.GetString()); - - _subsystemLauncher.LaunchSubsystemAfterTime(subsystem.Key, subsystem.Value); - - break; - - case Topics.launchingSubsystems: - var subsystemsToStart = JsonSerializer.Deserialize>(payload.GetString()); - - if (subsystemsToStart != null) _subsystemLauncher.LaunchSubsystems(subsystemsToStart); - - break; - - case Topics.restartingSubsystems: - var subsystemsToRestart = JsonSerializer.Deserialize>(payload.GetString()); - - if (subsystemsToRestart != null) _subsystemLauncher.RestartSubsystems(subsystemsToRestart); - - break; - - case Topics.terminatingSubsystems: - var subsystemsToShutDown = JsonSerializer.Deserialize>(payload.GetString()); - - if (subsystemsToShutDown != null) _subsystemLauncher.ShutdownSubsystems(subsystemsToShutDown); - - break; - } - } - catch(Exception exception) - { - _logger.LogError($"Errors occurred while sending launch/restart/shutdown command to the SubsystemLauncher. {exception}."); - } - } -} - diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/ProcessInfoHandler.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/ProcessInfoHandler.cs deleted file mode 100644 index d42749bf0..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/ProcessInfoHandler.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Processes; -using ModuleProcessMonitor.Subsystems; -using MorganStanley.ComposeUI.Messaging; -using MorganStanley.ComposeUI.Tryouts.Core.Abstractions.Modules; -using ProcessExplorerMessageRouterTopics; - -namespace ModulesPrototype.Infrastructure; - -public class ProcessInfoHandler : IProcessInfoHandler -{ - private readonly ILogger _logger; - private readonly IMessageRouter _messageRouter; - private IModuleLoader? _moduleLoader; - private ISubsystemLauncher? _subsystemLauncher; - private ISubsystemControllerCommunicator? _subsystemControllerCommunicator; - - public ProcessInfoHandler(ILogger? logger, - IMessageRouter messageRouter) - { - _logger = logger ?? NullLogger.Instance; - _messageRouter = messageRouter; - } - - public async ValueTask SendInitProcessInfoAsync(IEnumerable processInfo) - { - _logger.LogInformation("Sending the collection of processInformation...."); - - try - { - Thread.Sleep(1000); - - if (processInfo.Any()) - { - var listOfProcessInfoData = processInfo - .Select(process => process?.ProcessInfo); - - var serializedListOfProcessInfo = JsonSerializer.Serialize(listOfProcessInfoData); - - await _messageRouter.PublishAsync(Topics.watchingProcessChanges, serializedListOfProcessInfo); - } - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while publishing the list of processInfo through topic : {Topics.watchingProcessChanges}.. : {exception}"); - } - } - - public void SendAddProcessInfo(ProcessInfoData processInfo) - { - _logger.LogInformation("Sending a process...."); - - try - { - var serializedProcessInfo = JsonSerializer.Serialize(processInfo); - - //fire - and - forget - _messageRouter.PublishAsync(Topics.changedProcessInfo, serializedProcessInfo); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while publishing processInfo through topic : {Topics.changedProcessInfo}.. : {exception}"); - } - } - - public async ValueTask EnableProcessMonitorAsync() - { - _logger.LogInformation("Sending key to watch processes...."); - - try - { - await _messageRouter.PublishAsync(Topics.enableProcessWatcher, string.Empty); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while publishing the command to set processMonitor's watcher through topic : {Topics.enableProcessWatcher}.. : {exception}"); - } - } - - public async ValueTask DisableProcessMonitorAsync() - { - _logger.LogInformation("Sending key to unwatch processes...."); - - try - { - await _messageRouter.PublishAsync(Topics.disableProcessWatcher, string.Empty); - } - catch (Exception exception) - { - _logger.LogError($"Some error(s) occurred while publishing the command to unset processMonitor's watcher through topic : {Topics.disableProcessWatcher}.. : {exception}"); - } - } - - public async ValueTask SendModifiedSubsystemStateAsync(Guid instanceId, string state) - { - try - { - if (_subsystemLauncher == null) return; - - await _subsystemLauncher.ModifySubsystemState(instanceId, state); - } - catch (Exception exception) - { - _logger.LogError($"Some errors occurred while sending modify subsystem state request. {exception}"); - } - } - - public async ValueTask InitializeSubsystemControllerRouteAsync() - { - try - { - if (_subsystemControllerCommunicator == null) return; - - await _subsystemControllerCommunicator.InitializeCommunicationRoute(); - } - catch (Exception exception) - { - _logger.LogError($"Some errors occurred while Initializing user defined communication route. {exception}"); - } - } - - public async ValueTask SendRegisteredSubsystemsAsync(string subsystems) - { - try - { - Thread.Sleep(5000); - if (_subsystemLauncher == null) return; - - _subsystemLauncher.SetSubsystems(subsystems); - await _subsystemLauncher.InitSubsystems(); - } - catch (Exception exception) - { - _logger.LogError($"Some errors occurred while sending subsystems to the Process Explorer backend. {exception}"); - } - } - - public void SetSubsystemHandler(IModuleLoader moduleLoader, - ILoggerFactory? loggerFactory = null) - { - if (loggerFactory == null) return; - _moduleLoader = moduleLoader; - var subsystemServiceProvider = new ServiceCollection() - .AddSubsystemHandler(builder => - { - builder.Configure(loggerFactory, - _messageRouter, - _moduleLoader); - }) - .BuildServiceProvider(); - - _subsystemLauncher = subsystemServiceProvider - .GetRequiredService(); - - _subsystemControllerCommunicator = subsystemServiceProvider - .GetRequiredService(); - } -} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/SubsystemControllerCommunicator.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/SubsystemControllerCommunicator.cs deleted file mode 100644 index f8f8fd574..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/SubsystemControllerCommunicator.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using ModuleProcessMonitor.Subsystems; -using ModulesPrototype.Infrastructure.Messages; -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ProcessExplorerMessageRouterTopics; -using MorganStanley.ComposeUI.Messaging; - -namespace ModulesPrototype.Infrastructure; - -internal class SubsystemControllerCommunicator : ISubsystemControllerCommunicator -{ - private readonly IMessageRouter _messageRouter; - private readonly IObserver _subsystemHandlerObserver; - private readonly ILogger _logger; - - public SubsystemControllerCommunicator(ILogger? logger, - IMessageRouter messageRouter, - SubsystemHandlerRouterMessage subsystemHandlerObserver) - { - _logger = logger ?? NullLogger.Instance; - _messageRouter = messageRouter; - _subsystemHandlerObserver = subsystemHandlerObserver; - } - - public async ValueTask InitializeCommunicationRoute() - { - //subscribing to topics, commands from UI - try - { - await _messageRouter.SubscribeAsync(Topics.launchingSubsystemWithDelay, _subsystemHandlerObserver); - await _messageRouter.SubscribeAsync(Topics.launchingSubsystems, _subsystemHandlerObserver); - await _messageRouter.SubscribeAsync(Topics.restartingSubsystems, _subsystemHandlerObserver); - await _messageRouter.SubscribeAsync(Topics.terminatingSubsystems, _subsystemHandlerObserver); - } - catch (Exception exception) - { - _logger.LogError($"Some errors occurred while subscribing... {exception}"); - } - } -} - diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/SubsystemLauncher.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/SubsystemLauncher.cs deleted file mode 100644 index b2b41ea25..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Infrastructure/SubsystemLauncher.cs +++ /dev/null @@ -1,295 +0,0 @@ -// Morgan Stanley makes this available to you under the Apache License, -// Version 2.0 (the "License"). You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0. -// -// See the NOTICE file distributed with this work for additional information -// regarding copyright ownership. Unless required by applicable law or agreed -// to in writing, software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions -// and limitations under the License. - -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using ModuleProcessMonitor.Subsystems; -using MorganStanley.ComposeUI.Messaging; -using MorganStanley.ComposeUI.Tryouts.Core.Abstractions.Modules; -using ProcessExplorerMessageRouterTopics; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -namespace ModulesPrototype.Infrastructure; - -internal class SubsystemLauncher : ISubsystemLauncher -{ - private readonly ILogger _logger; - private readonly Dictionary _subsystems; - private readonly IModuleLoader _moduleLoader; - private readonly IMessageRouter? _messageRouter; - private readonly object _subsystemLocker = new(); - private delegate ValueTask RequestSubsystemAction(Guid subsystemId); - - public SubsystemLauncher(ILogger? logger, - IMessageRouter? messageRouter, - IModuleLoader moduleLoader) - { - _logger = logger ?? NullLogger.Instance; - _moduleLoader = moduleLoader; - _messageRouter = messageRouter; - _subsystems = new Dictionary(); - } - - public void SetSubsystems(string serializedSubsystems) - { - try - { - var subsystems = JsonSerializer.Deserialize>(serializedSubsystems); - - if (subsystems == null) - { - _logger.LogWarning($"Cannot initialize subsystems. Null argumentum: {nameof(subsystems)}."); - return; - } - - lock (_subsystemLocker) - { - if (subsystems.Any()) - { - foreach (var subsystem in subsystems) - { - _subsystems[subsystem.Key] = subsystem.Value; - } - } - } - } - catch (Exception exception) - { - _logger.LogError($@"Some error(s) occurred while initializing subsystems for Process Explorer backend. {exception}"); - } - } - - public async ValueTask InitSubsystems() - { - if (_messageRouter == null) - { - throw new ArgumentNullException($"Argument : {nameof(_messageRouter)} is null."); - } - - _logger.LogInformation($"Sending the collection of subsystems to Process Explorer to show on the UI."); - - try - { - if (_subsystems.Any()) - { - var payload = JsonSerializer.Serialize(_subsystems); - await _messageRouter.PublishAsync(Topics.initilaizingSubsystems, payload); - } - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.initilaizingSubsystems}. {exception}"); - } - } - - public async ValueTask AddSubsystem(Guid subsystemId, SubsystemInfo subsystem) - { - if (_messageRouter == null) - { - throw new ArgumentNullException($"Argument : {nameof(_messageRouter)} is null."); - } - - _logger.LogInformation($"Adding subsystem to the collection with ID : {subsystemId}."); - - var subsystemExists = false; - - lock (_subsystemLocker) - { - subsystemExists = _subsystems.Any(sub => sub.Key == subsystemId); - } - - if (subsystemExists) - { - _moduleLoader.RequestStartProcess(new LaunchRequest { instanceId = subsystemId, name = subsystem.Name }); - - try - { - var serializableSubsystem = new KeyValuePair(subsystemId, subsystem); - var payload = JsonSerializer.Serialize(serializableSubsystem); - await _messageRouter.PublishAsync(Topics.addingSubsystem, payload); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.addingSubsystem}. {exception}"); - } - } - } - - public async ValueTask ModifySubsystemState(Guid subsystemId, string state) - { - if (_messageRouter == null) - { - throw new ArgumentNullException($"Argument : {nameof(_messageRouter)} is null."); - } - - _logger.LogInformation($"Modifying the state of subsystem with Id: {subsystemId} and to state: {state}."); - - try - { - var payload = JsonSerializer.Serialize(new KeyValuePair(subsystemId, state)); - await _messageRouter.PublishAsync(Topics.modifyingSubsystem, payload); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.modifyingSubsystem}. {exception}"); - } - } - - public async ValueTask RemoveSubsystem(Guid subsystemId) - { - if (_messageRouter == null) - { - throw new ArgumentNullException($"Argument : {nameof(_messageRouter)} is null."); - } - - _moduleLoader.RequestStopProcess(new StopRequest { instanceId = subsystemId }); - - try - { - var payload = JsonSerializer.Serialize(subsystemId); - await _messageRouter.PublishAsync(Topics.removingSubsystem, payload); - } - catch (Exception exception) - { - _logger.LogInformation($"Some error(s) occurred while publishing to topic: {Topics.removingSubsystem}. {exception}"); - } - } - - private async ValueTask>> HandleSubsystemAction(IEnumerable subsystems, RequestSubsystemAction action) - { - var result = new Dictionary(); - - foreach (var subsystem in subsystems) - { - KeyValuePair existedSubsystem; - - lock (_subsystemLocker) - { - existedSubsystem = _subsystems - .FirstOrDefault(sub => - sub.Key == subsystem); - } - - var resultSubsystemState = await action(existedSubsystem.Key); - - result.Add(existedSubsystem.Key, resultSubsystemState); - } - - return result; - } - - public async ValueTask LaunchSubsystem(Guid subsystemId) - { - try - { - KeyValuePair subsystem; - - lock (_subsystemLocker) - { - subsystem = _subsystems - .First(sub => sub.Key == subsystemId); - } - - _logger.LogInformation($"Starting subsystem with Id: {subsystem.Key}."); - - if (subsystem.Value.State != SubsystemState.Started) - { - //TODO(Lilla): Send to the PE backend the given name in the manifest. - _moduleLoader.RequestStartProcess(new LaunchRequest { instanceId = subsystem.Key, name = subsystem.Value.Name }); - } - else - { - _logger.LogInformation($"Subsystem with id: {subsystem.Key} is already started."); - } - - return SubsystemState.Started; - } - catch (Exception exception) - { - _logger.LogError($"Failed to launch subsystem with Id: {subsystemId}. {exception}"); - } - - return SubsystemState.Stopped; - } - - public ValueTask LaunchSubsystemAfterTime(Guid subsystemId, int periodOfTime) - { - Thread.Sleep(periodOfTime); - return LaunchSubsystem(subsystemId); - } - - public ValueTask>> LaunchSubsystems(IEnumerable subsystems) - { - return HandleSubsystemAction(subsystems, LaunchSubsystem); - } - - public async ValueTask RestartSubsystem(Guid subsystemId) - { - //Sending stop and launch request - await ShutdownSubsystem(subsystemId); - - var startedStateResult = await LaunchSubsystem(subsystemId); - if (startedStateResult == SubsystemState.Stopped) - { - _logger.LogError( - $"FAILED to launch subsystem with Id: {subsystemId} after stopping it... (Restart failed).."); - - } - - return startedStateResult; - } - - public ValueTask>> RestartSubsystems(IEnumerable subsystems) - { - return HandleSubsystemAction(subsystems, RestartSubsystem); - } - - public async ValueTask ShutdownSubsystem(Guid subsystemId) - { - try - { - KeyValuePair subsystem; - lock (_subsystemLocker) - { - subsystem = _subsystems.First(sub => sub.Key == subsystemId); - } - - _logger.LogInformation($"Stopping subsystem with Id: {subsystem.Key}."); - - if (subsystem.Value.State != SubsystemState.Stopped) - { - _moduleLoader.RequestStopProcess(new StopRequest { instanceId = subsystem.Key }); - } - else - { - _logger.LogInformation($"Subsystem with id: {subsystem.Key} is already stopped."); - } - - return SubsystemState.Stopped; - } - catch (Exception exception) - { - _logger.LogError($"Failed to stop subsystem with Id: {subsystemId}. {exception}"); - throw new Exception($"Some error(s) occurred while shutdowning the subsystem with Id :{subsystemId}, {exception}."); - } - } - - public ValueTask>> ShutdownSubsystems(IEnumerable subsystems) - { - return HandleSubsystemAction(subsystems, ShutdownSubsystem); - } -} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ModulesPrototype.csproj b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ModulesPrototype.csproj index 554578f3e..f1b8e6d32 100644 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ModulesPrototype.csproj +++ b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ModulesPrototype.csproj @@ -42,8 +42,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 + - - \ No newline at end of file diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Program.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Program.cs index 887b30caf..4c5b879e6 100644 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Program.cs +++ b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/Program.cs @@ -26,9 +26,11 @@ using MorganStanley.ComposeUI.Messaging.Server.WebSocket; using Nito.AsyncEx; using System.Linq; -using ModuleProcessMonitor.Processes; -using System.Collections.ObjectModel; -using ModuleProcessMonitor; +using ProcessExplorer.Server.DependencyInjection; +using ProcessExplorer.Server.Server.Abstractions; +using ProcessExplorer.Abstractions.Subsystems; +using ProcessExplorer.Abstractions; +using ProcessExplorer.Core.DependencyInjection; namespace ModulesPrototype; @@ -68,8 +70,22 @@ public static async Task Main(string[] args) var loader = factory.Create(catalogue); var moduleCounter = new AsyncCountdownEvent(0); + var processExplorer = new HostBuilder() + .ConfigureLogging(l => l.AddConsole().SetMinimumLevel(LogLevel.Debug)) + .ConfigureServices( + (context, services) => services + .ConfigureSubsystemLauncher(loader.RequestStartProcess, loader.RequestStopProcess, CreateLaunchRequest, CreateStopRequest) + .AddProcessExplorerWindowsServerWithGrpc(pe => pe.UseGrpc()) + .Configure(op => + { + op.Port = 5056; + op.MainProcessId = Process.GetCurrentProcess().Id; + op.EnableProcessExplorer = true; + })) + .Build(); - var processInfo = new ObservableCollection(); + await processExplorer.StartAsync(cts.Token); + var infoAggregator = processExplorer.Services.GetRequiredService(); loader.LifecycleEvents.Subscribe( e => @@ -95,31 +111,55 @@ public static async Task Main(string[] args) { moduleCounter.Signal(); } + infoAggregator.ScheduleSubsystemStateChanged(e.ProcessInfo.instanceId, SubsystemState.Stopped.ToString()); } - var proc = new ProcessInformation(e.ProcessInfo.name, - e.ProcessInfo.instanceId, - e.ProcessInfo.uiType, - e.ProcessInfo.uiHint!, - (int)e.ProcessInfo.pid!); - - processInfo.Add(proc); + infoAggregator.ScheduleSubsystemStateChanged(e.ProcessInfo.instanceId, SubsystemState.Started.ToString()); }); var instances = new Dictionary(); foreach (var module in manifest) { var instanceId = Guid.NewGuid(); - instances.Add(instanceId, (Module)module.Value); + + instances.Add(instanceId, new() + { + Name = module.Value.Name, + StartupType = module.Value.StartupType, + UIType = module.Value.UIType, + Path = module.Value.Path ?? string.Empty, + Url = module.Value.Url, + Arguments = module.Value.Arguments, + Port = module.Value.Port, + }); + moduleCounter.AddCount(); } foreach (var module in instances) { - module.Value.State = ModuleState.Started; - loader.RequestStartProcess(new LaunchRequest { name = module.Value.Name, instanceId = module.Key }); + if (module.Value.Name == "dataservice") + { + instances.TryGetValue(module.Key, out var instance); + instance = new() + { + StartupType = module.Value.StartupType, + Arguments = module.Value.Arguments, + State = SubsystemState.Started.ToString(), + Name = module.Value.Name, + Path = module.Value.Path, + Port = module.Value.Port, + UIType = module.Value.UIType, + Url = module.Value.Url, + }; + + loader.RequestStartProcess(new LaunchRequest { name = module.Value.Name, instanceId = module.Key }); + } } + if(infoAggregator.SubsystemController != null) + await infoAggregator.SubsystemController.InitializeSubsystems(instances.Select(kvp => new KeyValuePair(kvp.Key, SubsystemInfo.FromModule(kvp.Value)))); + logger.LogInformation("ComposeUI application running, press Ctrl+C to exit"); await stopTaskSource.Task; @@ -152,4 +192,21 @@ private static int StartBrowser(string url) pr2.Start(); return pr2.Id; } + + static LaunchRequest CreateLaunchRequest(Guid id, string name) + { + return new LaunchRequest() + { + instanceId = id, + name = name, + }; + } + + static StopRequest CreateStopRequest(Guid id) + { + return new StopRequest() + { + instanceId = id, + }; + } } diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ServiceCollectionSubsystemLauncherExtensions.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ServiceCollectionSubsystemLauncherExtensions.cs deleted file mode 100644 index 65528c176..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/ServiceCollectionSubsystemLauncherExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -// ******************************************************************************************************** -// -// Morgan Stanley makes this available to you under the Apache License, Version 2.0 (the "License"). -// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. -// See the NOTICE file distributed with this work for additional information regarding copyright ownership. -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and limitations under the License. -// -// ******************************************************************************************************** - - -using Microsoft.Extensions.DependencyInjection; -using ModuleProcessMonitor.Subsystems; -using ModulesPrototype.Infrastructure; -using ModulesPrototype.Infrastructure.Messages; -using System; - -namespace ModulesPrototype; - -internal static class ServiceCollectionSubsystemLauncherExtensions -{ - public static IServiceCollection AddSubsystemHandler( - this IServiceCollection serviceCollection, - Action configureAction) - { - if(serviceCollection == null) - throw new ArgumentNullException(nameof(serviceCollection)); - - if(configureAction == null) - throw new ArgumentNullException(nameof(configureAction)); - - var builder = new SubsystemLauncherBuilder(serviceCollection); - configureAction(builder); - - serviceCollection.Add( - new ServiceDescriptor(typeof(ISubsystemLauncher), typeof(SubsystemLauncher), builder.ServiceLifetime)); - - serviceCollection.Add( - new ServiceDescriptor(typeof(SubsystemHandlerRouterMessage), typeof(SubsystemHandlerRouterMessage), builder.ServiceLifetime)); - - serviceCollection.Add( - new ServiceDescriptor(typeof(ISubsystemControllerCommunicator), typeof(SubsystemControllerCommunicator), builder.ServiceLifetime)); - - return serviceCollection; - } -} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/SubsystemLauncherBuilder.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/SubsystemLauncherBuilder.cs deleted file mode 100644 index 36954c03e..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ModulesPrototype/SubsystemLauncherBuilder.cs +++ /dev/null @@ -1,64 +0,0 @@ -// ******************************************************************************************************** -// -// Morgan Stanley makes this available to you under the Apache License, Version 2.0 (the "License"). -// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. -// See the NOTICE file distributed with this work for additional information regarding copyright ownership. -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and limitations under the License. -// -// ******************************************************************************************************** - - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; -using ModulesPrototype.Infrastructure; -using ModulesPrototype.Infrastructure.Messages; -using MorganStanley.ComposeUI.Messaging; -using MorganStanley.ComposeUI.Tryouts.Core.Abstractions.Modules; - -namespace ModulesPrototype; - -internal class SubsystemLauncherBuilder -{ - private IServiceCollection _serviceCollection; - private ILoggerFactory? _loggerFactory; - - public SubsystemLauncherBuilder(IServiceCollection serviceCollection) - { - this._serviceCollection = serviceCollection; - } - - public SubsystemLauncherBuilder Configure(ILoggerFactory? loggerFactory, - IMessageRouter messageRouter, - IModuleLoader moduleLoader) - { - if (loggerFactory != null) - { - _serviceCollection.RemoveAll(); - _serviceCollection.AddSingleton(loggerFactory); - _loggerFactory = loggerFactory; - - _serviceCollection.RemoveAll>(); - _serviceCollection.AddSingleton>(_loggerFactory.CreateLogger()); - - _serviceCollection.RemoveAll>(); - _serviceCollection.AddSingleton>(_loggerFactory.CreateLogger()); - - _serviceCollection.RemoveAll>(); - _serviceCollection.AddSingleton>(_loggerFactory.CreateLogger()); - - } - - _serviceCollection.RemoveAll(); - _serviceCollection.AddSingleton(messageRouter); - - _serviceCollection.RemoveAll(); - _serviceCollection.AddSingleton(moduleLoader); - - return this; - } - - internal ServiceLifetime ServiceLifetime { get; } -} diff --git a/prototypes/multi-module-prototype/examples/multi-module-example/ProcessExplorerMessageRouterTopics/Topics.cs b/prototypes/multi-module-prototype/examples/multi-module-example/ProcessExplorerMessageRouterTopics/Topics.cs deleted file mode 100644 index 6b2c7d41f..000000000 --- a/prototypes/multi-module-prototype/examples/multi-module-example/ProcessExplorerMessageRouterTopics/Topics.cs +++ /dev/null @@ -1,37 +0,0 @@ -// /* -// * Morgan Stanley makes this available to you under the Apache License, -// * Version 2.0 (the "License"). You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0. -// * -// * See the NOTICE file distributed with this work for additional information -// * regarding copyright ownership. Unless required by applicable law or agreed -// * to in writing, software distributed under the License is distributed on an -// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// * or implied. See the License for the specific language governing permissions -// * and limitations under the License. -// */ - -namespace ProcessExplorerMessageRouterTopics; - -public static class Topics -{ - public const string addingConnections = "local-connections-information-update"; - public const string updatingRuntime = "local-runtime-information-update"; - public const string updatingConnection = "local-connection-update"; - public const string updatingEnvironmentVariables = "local-environment-variables-update"; - public const string updatingModules = "local-modules-information-update"; - public const string updatingRegistrations = "local-registration-information-update"; - public const string enableProcessWatcher = "process-monitor-enable"; - public const string disableProcessWatcher = "process-monitor-disable"; - public const string initilaizingSubsystems = "process-explorer-init-subsystems"; - public const string addingSubsystem = "process-explorer-add-subsystem"; - public const string modifyingSubsystem = "process-explorer-modify-subsystem"; - public const string removingSubsystem = "process-explorer-remove-subsystem"; - public const string changedProcessInfo = "process-explorer-changed-element"; - public const string watchingProcessChanges = "process-explorer"; - public const string launchingSubsystemWithDelay = "process-explorer-launch-subsystem-delay"; - public const string launchingSubsystems = "process-explorer-launch-subsystems"; - public const string restartingSubsystems = "process-explorer-restart-subsystems"; - public const string terminatingSubsystems = "process-explorer-shutdown-subsystems"; -}