From 67ded31cba74b21d63956ecb85ac15b074b17abb Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 30 May 2026 08:12:12 +0200 Subject: [PATCH 1/6] Increase secrets unit coverage (#7545) --- .../SecretModelMapperTests.cs | 32 +++++++++++ .../SecretStoreTests.cs | 57 +++++++++++++++++++ .../SecretValueProtectorTests.cs | 52 +++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 test/unit/Elsa.Secrets.UnitTests/SecretModelMapperTests.cs create mode 100644 test/unit/Elsa.Secrets.UnitTests/SecretValueProtectorTests.cs diff --git a/test/unit/Elsa.Secrets.UnitTests/SecretModelMapperTests.cs b/test/unit/Elsa.Secrets.UnitTests/SecretModelMapperTests.cs new file mode 100644 index 000000000..da588bfc6 --- /dev/null +++ b/test/unit/Elsa.Secrets.UnitTests/SecretModelMapperTests.cs @@ -0,0 +1,32 @@ +using Elsa.Secrets.Models; +using Elsa.Secrets.Services; +using Xunit; + +namespace Elsa.Secrets.UnitTests; + +public class SecretModelMapperTests +{ + [Fact] + public void ToModel_ReportsExpired_WhenActiveSecretHasOnlyExpiredVersions() + { + var secret = new Secret + { + Name = "smtp:password", + DisplayName = "SMTP password", + Versions = + { + new SecretVersion + { + Version = 1, + ExpiresAt = DateTimeOffset.UtcNow.AddMinutes(-1) + } + } + }; + + var model = secret.ToModel(); + + Assert.Equal(SecretStatus.Expired, model.Status); + Assert.Null(model.CurrentVersion); + Assert.Null(model.ExpiresAt); + } +} diff --git a/test/unit/Elsa.Secrets.UnitTests/SecretStoreTests.cs b/test/unit/Elsa.Secrets.UnitTests/SecretStoreTests.cs index fbcf9b67f..a4a00effe 100644 --- a/test/unit/Elsa.Secrets.UnitTests/SecretStoreTests.cs +++ b/test/unit/Elsa.Secrets.UnitTests/SecretStoreTests.cs @@ -40,6 +40,51 @@ public class SecretStoreTests Assert.Equal("configured-secret", value); } + [Fact] + public async Task ConfigurationStore_FallsBackToRootConfigurationKey() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary { ["SmtpPassword"] = "root-configured-secret" }) + .Build(); + var fixture = new SecretTestFixture(configuration); + + var secret = await fixture.Manager.CreateAsync(new CreateSecretRequest + { + Name = "smtp:password", + StoreName = SecretStoreNames.Configuration, + ConfigurationKey = " SmtpPassword " + }); + var value = await fixture.Resolver.ResolveAsync("smtp:password"); + + Assert.Equal("root-configured-secret", value); + Assert.Null(secret.Versions.Single().Payload.Value); + Assert.Equal("SmtpPassword", secret.Versions.Single().Payload.Metadata["configurationKey"]); + } + + [Fact] + public async Task ConfigurationStore_RotateAsync_UsesReplacementConfigurationKey() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + ["Elsa:Secrets:OldPassword"] = "old-configured-secret", + ["Elsa:Secrets:NewPassword"] = "new-configured-secret" + }) + .Build(); + var fixture = new SecretTestFixture(configuration); + + await fixture.Manager.CreateAsync(new CreateSecretRequest + { + Name = "smtp:password", + StoreName = SecretStoreNames.Configuration, + ConfigurationKey = "OldPassword" + }); + await fixture.Manager.RotateAsync("smtp:password", new RotateSecretRequest { ConfigurationKey = "NewPassword" }); + var value = await fixture.Resolver.ResolveAsync("smtp:password"); + + Assert.Equal("new-configured-secret", value); + } + [Fact] public async Task ConfigurationStore_TestAsync_ReturnsFalseWhenConfiguredValueIsMissing() { @@ -57,6 +102,18 @@ public class SecretStoreTests Assert.Equal("Secret value is unavailable.", result.Error); } + [Fact] + public void Registries_Throw_WhenTypeOrStoreIsMissing() + { + var fixture = new SecretTestFixture(); + + var missingType = Assert.Throws(() => fixture.TypeRegistry.Get("missing-type")); + var missingStore = Assert.Throws(() => fixture.StoreRegistry.Get("missing-store")); + + Assert.Contains("missing-type", missingType.Message); + Assert.Contains("missing-store", missingStore.Message); + } + [Fact] public async Task FileRepository_PersistsSecretAggregate() { diff --git a/test/unit/Elsa.Secrets.UnitTests/SecretValueProtectorTests.cs b/test/unit/Elsa.Secrets.UnitTests/SecretValueProtectorTests.cs new file mode 100644 index 000000000..47ec88f96 --- /dev/null +++ b/test/unit/Elsa.Secrets.UnitTests/SecretValueProtectorTests.cs @@ -0,0 +1,52 @@ +using Elsa.Secrets.Options; +using Elsa.Secrets.Services; +using Xunit; + +namespace Elsa.Secrets.UnitTests; + +public class SecretValueProtectorTests +{ + [Fact] + public void Protect_AndUnprotect_RoundTripsValue() + { + var protector = CreateProtector("0123456789abcdef0123456789abcdef"u8.ToArray()); + + var protectedValue = protector.Protect("plain-text-secret"); + var value = protector.Unprotect(protectedValue); + + Assert.NotEqual("plain-text-secret", protectedValue); + Assert.Equal("plain-text-secret", value); + } + + [Theory] + [InlineData(null)] + [InlineData(0)] + [InlineData(15)] + [InlineData(17)] + public void Protect_RejectsMissingOrInvalidEncryptionKey(int? keyLength) + { + var protector = CreateProtector(keyLength == null ? null : new byte[keyLength.Value]); + + var exception = Assert.Throws(() => protector.Protect("secret")); + + Assert.Contains("encryption key", exception.Message, StringComparison.OrdinalIgnoreCase); + } + + [Theory] + [InlineData("")] + [InlineData("v2.payload")] + [InlineData("v1.payload")] + public void Unprotect_RejectsUnsupportedPayloadFormat(string protectedValue) + { + var protector = CreateProtector("0123456789abcdef0123456789abcdef"u8.ToArray()); + + var exception = Assert.Throws(() => protector.Unprotect(protectedValue)); + + Assert.Contains("not supported", exception.Message, StringComparison.OrdinalIgnoreCase); + } + + private static DefaultSecretValueProtector CreateProtector(byte[]? key) + { + return new DefaultSecretValueProtector(Microsoft.Extensions.Options.Options.Create(new SecretsOptions { EncryptionKey = key })); + } +} From 842cf7c16299da0886d79ae2e6de81a4d88e5cbf Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 30 May 2026 22:52:01 +0200 Subject: [PATCH 2/6] [codex] Fix console log metadata and type resolution (#7542) * Avoid null endpoint DTO metadata in tests * Enforce console logs hub read permission * Remove unused console logs hub import * Support mapped endpoint metadata in auth tests * Reduce console log capture throughput impact * Address Copilot console logs review * Refactor task scheduling to support tenant-level background work and enhance logging functionality. * Introduce ConsoleStreamHook for stdout/stderr tee and enhance logging validation. Adjust test cases and startup warnings for distributed lock provider usage. * Refactor console logging pipeline with capture optimization and new ConsoleLogsHost; update tests accordingly. * Add Ansi SGR parser for console logs and associated unit tests * Remove ANSI color renderings and parsers; integrate ConsoleLogScopeAccessor for improved logging context with workflow instance ID support. * Address console logs code quality feedback * Address PR review feedback * Preserve console logs extension points * Stabilize console logs host lifecycle * Address final automated review comments * Tighten console log capture shutdown * Address console log review feedback * Address follow-up review feedback * Cover final review feedback * Avoid recursive console provider initialization * Guard console host lease shutdown * Preserve console log scope and provider lifetime * Correlate console log scope fallback * Tighten console scope correlation * Expose host services during provider construction * Redact ANSI-normalized console lines * Add OpenTelemetry diagnostics backend foundation * Add OTLP HTTP ingestion parsing * Document OpenTelemetry diagnostics setup * Enforce OpenTelemetry hub permissions * Remove `ConsoleCaptureTee` and related services and tests * Add OpenTelemetry HTTP ingestion integration test * Use pipeline contributors for console log context * Update CShells package versions to 0.0.24-preview.132 * Add OpenTelemetry ingestion security tests * Add OpenTelemetry API authorization tests * Filter live console logs by workflow instance * Add OpenTelemetry hub tests * Add OpenTelemetry gRPC metadata hook * Assert OpenTelemetry workflow tags survive ingestion * Mark OpenTelemetry core build verified * Enhance console logging with activity execution metadata and extend test coverage. * Address console logs stream consumption comment * Wire OpenTelemetry diagnostics into core sample * Address Core diagnostics review feedback * Address Core Copilot follow-up feedback * Add OpenTelemetry metric instrument names * Address Core Copilot provider feedback * Address Core Copilot diagnostics follow-up * Address Core Copilot live feed feedback * Address Core Copilot store feedback * Integrate OpenTelemetry for logging, tracing, and metrics in ModularServer and update launch settings and docker-compose configuration. * Refactor to replace `ConsoleLogStream.Core` with `ConsoleLogStreaming.Core` across codebase and update `ConsoleStreamHook` installation. * Add diagnostics OpenTelemetry backend * Fix OpenTelemetry live hub subscription * Fix modular OpenTelemetry exporter endpoints * Add CShells logging configuration in appsettings.json * Remove obsolete unit tests and helper classes * Restore default activity exception handling * Simplify type serialization and alias management This commit refactors the internal type serialization and alias management system to reduce boilerplate, improve robustness, and simplify the developer experience: - Removed numerous explicit `ExpressionOptions` type alias registrations across various modules. - Updated `TypeJsonConverter` and polymorphic serialization to reliably handle types using assembly-qualified names when a short alias is not explicitly registered. - Streamlined `ExcludeFromHashConverter` to strictly adhere to `ExcludeFromHashAttribute` for hash calculations, removing complex `JsonIgnoreCondition` logic. - Eliminated several helper classes (`WorkflowJsonTypeResolver`, `WorkflowTypeValidator`, `IWorkflowTypeRegistry`, `WorkflowFactoryDictionary`, `JavaScriptExceptionTypeAliasRegistrar`, `WorkflowRuntimeTypeAliasRegistrar`) and their associated unit tests, simplifying the codebase. Additionally, this commit introduces a comprehensive markdown document (`product-website-feature-source.md`) outlining Elsa's core features, Studio capabilities, extension ecosystem, and architectural selling points, intended as source material for the product website. * Refine type serialization for improved robustness and alias handling This commit further enhances the type serialization and deserialization mechanisms: * Centralizes type resolution and alias management through `IWellKnownTypeRegistry` and `WorkflowJsonTypeResolver`. * Prioritizes registered type aliases when serializing type metadata in `PolymorphicObjectConverter`, resulting in more concise JSON output. * Enhances deserialization in `PolymorphicObjectConverter` and `VariableMapper` to gracefully handle unknown or non-instantiable types, providing fallbacks and logging warnings. * Simplifies `TypeJsonConverter` by delegating complex type resolution logic to the `WorkflowJsonTypeResolver`. * Adds `JsonArray` to the well-known type aliases for direct recognition. * Fix console logs packaging and workflow type resolution * Fix console log metadata and type resolution * Address Copilot review feedback * Enhance type resolution, improve console log handling, and update tests - Streamlined `WorkflowDictionaryExtensions` for better workflow registration validation. - Refined `ConsoleLogsAuthorizationTests` with the new `SetJsonRequest` helper to improve test requests handling. - Updated `OrderDefinition` to ignore JSON serialization for `KeySelector`. - Enhanced `WorkflowRuntimeFeature` for improved workflow registration and type alias configuration. - Added tests to ensure `ConsoleLogProvider` metadata filtration in various scenarios. - Improved type serialization logic in `WorkflowJsonTypeResolver`. - Updated README to fix references related to diagnostics. - Optimized `ExcludeFromHashConverter` for property serialization conditions. - Modified `TriggerIndexer` for streamlined trigger management. - Tested payload checks in `PublishEventTests`. - Adjusted `Endpoint` in `ConsoleLogs` for automatic JSON request handling. - Ensured registration of workflow type aliases in `WorkflowsFeature`. * Restore CLR workflow registration compatibility * Align JSON island serialization fixtures * Add Console Logs Services and Enhance Endpoint Handling - Introduced `ActivityExecutionsEndpointTests` to validate route exposure. - Added `ConsoleLogCaptureHostedService` for console log streaming. - Implemented `ConsoleStreamJsonConverter` for JSON conversion of console streams. - Developed `ElsaConsoleLogRecentBuffer` to handle recent log buffering. - Updated `ConsoleLogsAuthorizationTests` with new test cases for stream filter mapping. - Consolidated console log provider dependencies and registration, including recent buffering. - Enhanced `ElsaConsoleLogProvider` to use recent buffer for filtering. - Adjusted `Program.cs` for streamlined logging service setup. * Enhance type resolution and test coverage; streamline console log integration - Added `ConsoleStreamHook` for streamlined log streaming. - Updated `WorkflowJsonTypeResolverTests` to improve type resolution and test new scenarios. - Simplified type resolution by removing trusted assembly checks. * Fix CI smoke and package restore failures * Fix Docker smoke image project paths * Fix Docker Python runtime packages * Fix Docker CA smoke teardown * Refresh Elsa roadmap * Implement background processors and mediation coordination - Added `BackgroundCommandProcessor`, `BackgroundJobProcessor`, and `BackgroundNotificationProcessor` classes for handling commands, jobs, and notifications, respectively. - Introduced `MediatorBackgroundProcessingCoordinator` to coordinate the execution of all background processors. - Implemented `MediatorBackgroundTask` for wrapping `MediatorBackgroundProcessingCoordinator` in `BackgroundTask`. - Added unit tests for `MediatorBackgroundTask` to ensure proper start and stop behavior. - Refactored `BackgroundCommandSenderHostedService` to utilize `BackgroundCommandProcessor`. - Introduced 'elsa-roadmap-refresh' skill configuration for roadmap updates. * Address workflow type resolution review feedback * Address follow-up review feedback * Restore recent console logs execute path * Address Copilot follow-up review * Decouple workflow JSON aliases from expressions * Fix workflow management unit test setup * Fix console logs recent endpoint handler shape * Respect workflow JSON strict type aliases * Remove unused console log contracts reference * Address Copilot review feedback * Address Copilot follow-up comments * Synchronize ring buffer dropped count * Address background processor strategy replay --- .agents/skills/elsa-roadmap-refresh/SKILL.md | 126 ++++ .../elsa-roadmap-refresh/agents/openai.yaml | 4 + .specify/feature.json | 2 +- AGENTS.md | 2 +- Directory.Packages.props | 4 + Elsa.sln | 47 +- NuGet.Config | 5 + ROADMAP.md | 60 +- doc/website/product-website-feature-source.md | 438 +++++++++++ doc/wiki/opentelemetry-workflows.md | 58 +- docker/ElsaServer-Datadog.Dockerfile | 11 +- docker/ElsaServer.Dockerfile | 9 +- docker/ElsaServerAndStudio.Dockerfile | 20 +- docker/ElsaStudio.Dockerfile | 11 +- docker/docker-compose.yml | 10 + scripts/test-ca-trust.sh | 34 +- .../checklists/requirements.md | 31 + .../contracts/otlp-ingest.md | 50 ++ .../contracts/provider-contract.md | 48 ++ .../contracts/rest-api.md | 67 ++ .../contracts/signalr-hub.md | 39 + specs/008-diagnostics-otel/data-model.md | 104 +++ specs/008-diagnostics-otel/plan.md | 149 ++++ specs/008-diagnostics-otel/quickstart.md | 72 ++ specs/008-diagnostics-otel/research.md | 54 ++ specs/008-diagnostics-otel/spec.md | 158 ++++ specs/008-diagnostics-otel/tasks.md | 123 +++ .../Elsa.ModularServer.Web.csproj | 5 + src/apps/Elsa.ModularServer.Web/Program.cs | 72 +- .../Properties/launchSettings.json | 34 +- .../Elsa.ModularServer.Web/appsettings.json | 16 +- .../Contracts/IActivityExecutionsApi.cs | 4 +- .../CommandStrategies/BackgroundStrategy.cs | 13 +- .../DependencyInjectionExtensions.cs | 21 +- .../BackgroundCommandSenderHostedService.cs | 101 +-- .../BackgroundEventPublisherHostedService.cs | 109 +-- .../HostedServices/JobRunnerHostedService.cs | 68 +- .../BackgroundProcessingStrategy.cs | 11 +- .../Services/BackgroundCommandProcessor.cs | 101 +++ .../Services/BackgroundJobProcessor.cs | 71 ++ .../BackgroundNotificationProcessor.cs | 98 +++ .../Features/AlterationsFeature.cs | 4 +- .../ShellFeatures/AlterationsFeature.cs | 18 +- .../Elsa.Common/Entities/OrderDefinition.cs | 6 - .../ShellFeatures/MediatorFeature.cs | 11 +- ...MediatorBackgroundProcessingCoordinator.cs | 91 +++ .../ShellHandlers/MediatorBackgroundTask.cs | 10 + .../AssemblyInfo.cs | 3 + .../Contracts/ConsoleStreamJsonConverter.cs | 57 ++ .../Contracts/ElsaConsoleLogFilter.cs | 32 +- .../Elsa.Diagnostics.ConsoleLogs.csproj | 6 +- .../Endpoints/ConsoleLogs/Recent/Endpoint.cs | 51 +- .../Endpoints/ConsoleLogs/Sources/Endpoint.cs | 5 +- ...leLogContextServiceCollectionExtensions.cs | 5 +- ...eLogProviderServiceCollectionExtensions.cs | 40 + .../EndpointRouteBuilderExtensions.cs | 11 +- .../HostServiceCollectionExtensions.cs | 13 +- .../Extensions/ServiceCollectionExtensions.cs | 15 +- .../Elsa.Diagnostics.ConsoleLogs/README.md | 2 +- .../ElsaConsoleLogSubscriptionManager.cs | 76 +- .../RealTime/ElsaConsoleLogsHub.cs | 22 +- .../ConsoleLogCaptureHostedService.cs | 11 + .../Services/ConsoleLogCaptureShellLease.cs | 69 ++ .../Services/ConsoleLogContextAccessor.cs | 5 +- .../ConsoleLogContextAccessorExtensions.cs | 2 - .../Services/ConsoleLogFilterMapper.cs | 3 - .../Services/ElsaConsoleLogOptions.cs | 12 +- .../Services/ElsaConsoleLogProvider.cs | 110 +++ .../Services/ElsaConsoleLogRecentBuffer.cs | 69 ++ .../ElsaConsoleLogStreamHubAuthorizer.cs | 8 +- .../ShellFeatures/ConsoleLogsFeature.cs | 9 +- .../Elsa.Diagnostics.ConsoleLogs/Usings.cs | 2 +- .../AssemblyInfo.cs | 3 + .../ICollectorConfigurationProvider.cs | 8 + .../Contracts/IOpenTelemetryIngestor.cs | 8 + .../Contracts/IOpenTelemetryLiveFeed.cs | 9 + .../Contracts/IOpenTelemetryProvider.cs | 14 + .../Contracts/IOpenTelemetryRedactor.cs | 8 + .../Contracts/IOpenTelemetrySourceRegistry.cs | 10 + .../Contracts/IOpenTelemetryStore.cs | 14 + .../Elsa.Diagnostics.OpenTelemetry.csproj | 16 + .../CollectorConfiguration/Endpoint.cs | 22 + .../Endpoints/OpenTelemetry/Logs/Endpoint.cs | 22 + .../OpenTelemetry/Metrics/Endpoint.cs | 22 + .../OpenTelemetry/Resources/Endpoint.cs | 22 + .../OpenTelemetry/Storage/Endpoint.cs | 22 + .../Endpoints/OpenTelemetry/Trace/Endpoint.cs | 29 + .../OpenTelemetry/Traces/Endpoint.cs | 22 + .../EndpointRouteBuilderExtensions.cs | 114 +++ .../Extensions/ModuleExtensions.cs | 14 + .../Extensions/ServiceCollectionExtensions.cs | 33 + .../Features/OpenTelemetryFeature.cs | 23 + .../FodyWeavers.xml | 4 + .../HttpProtobuf/OtlpHttpProtobufParser.cs | 701 ++++++++++++++++++ .../Ingestion/OtlpIngestionSecurity.cs | 44 ++ .../Models/OpenTelemetryContracts.cs | 86 +++ .../Models/OpenTelemetryModels.cs | 127 ++++ .../OpenTelemetryDiagnosticsOptions.cs | 43 ++ .../Permissions/OpenTelemetryPermissions.cs | 7 + .../InMemory/InMemoryOpenTelemetryLiveFeed.cs | 166 +++++ .../InMemory/InMemoryOpenTelemetryStore.cs | 227 ++++++ .../Providers/InMemory/RingBuffer.cs | 46 ++ .../Elsa.Diagnostics.OpenTelemetry/README.md | 41 + .../RealTime/IOpenTelemetryClient.cs | 8 + .../RealTime/OpenTelemetryHub.cs | 50 ++ .../OpenTelemetrySubscriptionManager.cs | 82 ++ .../CollectorConfigurationProvider.cs | 34 + .../Services/DefaultOpenTelemetryProvider.cs | 21 + .../Services/OpenTelemetryIngestor.cs | 14 + .../Services/OpenTelemetryRedactor.cs | 84 +++ .../Services/OpenTelemetrySourceRegistry.cs | 59 ++ .../ShellFeatures/OpenTelemetryFeature.cs | 101 +++ .../Features/JavaScriptFeature.cs | 4 +- .../JavaScriptExceptionTypeAliasRegistrar.cs | 21 - .../ShellFeatures/JavaScriptFeature.cs | 2 - .../Options/ExpressionOptions.cs | 2 +- src/modules/Elsa.Http/Features/HttpFeature.cs | 4 +- .../Elsa.Http/ShellFeatures/HttpFeature.cs | 4 +- .../WorkflowDefinitionPersistenceFeature.cs | 4 +- .../Management/WorkflowDefinitionStore.cs | 4 +- .../Features/SchedulingFeature.cs | 4 +- .../ShellFeatures/SchedulingFeature.cs | 11 + .../ActivityExecutions/Get/Endpoint.cs | 14 +- .../Serialization/FlowchartJsonConverter.cs | 11 +- .../WorkflowJsonOptionsExtensions.cs | 66 ++ .../Features/FlowchartFeature.cs | 8 +- .../Features/WorkflowsFeature.cs | 43 +- .../Converters/ExcludeFromHashConverter.cs | 2 + .../Converters/OutputJsonConverter.cs | 15 +- .../PolymorphicDictionaryConverter.cs | 8 +- .../Converters/PolymorphicObjectConverter.cs | 26 +- .../PolymorphicObjectConverterFactory.cs | 24 +- .../Converters/TypeJsonConverter.cs | 35 +- .../Converters/VariableConverter.cs | 16 +- .../Converters/VariableConverterFactory.cs | 24 +- .../Helpers/WorkflowJsonTypeResolver.cs | 190 +++-- .../Options/WorkflowJsonOptions.cs | 91 +++ .../Serializers/BookmarkPayloadSerializer.cs | 15 +- .../JsonWorkflowStateSerializer.cs | 27 +- .../Serializers/SafeSerializer.cs | 4 +- .../Elsa.Workflows.Core/Services/Hasher.cs | 14 +- .../Services/VariableMapper.cs | 43 +- .../ShellFeatures/FlowchartFeature.cs | 5 +- .../ShellFeatures/WorkflowsFeature.cs | 12 +- .../ManagementServiceCollectionExtensions.cs | 7 +- .../Extensions/ModuleExtensions.cs | 10 +- .../WorkflowManagementFeatureExtensions.cs | 6 +- .../Features/WorkflowManagementFeature.cs | 4 +- .../Mappers/VariableDefinitionMapper.cs | 26 +- .../WorkflowManagementFeature.cs | 5 +- .../WorkflowTriggerEqualityComparer.cs | 21 +- .../Discovery/WorkflowTypeScanner.cs | 14 + .../DependencyInjectionExtensions.cs | 46 +- .../WorkflowDictionaryExtensions.cs | 20 +- .../Features/WorkflowRuntimeFeature.cs | 31 +- .../Helpers/IWorkflowTypeRegistry.cs | 8 - .../Helpers/WorkflowFactoryDictionary.cs | 16 - .../Helpers/WorkflowTypeValidator.cs | 17 - .../Services/TriggerIndexer.cs | 6 +- .../ShellFeatures/WorkflowRuntimeFeature.cs | 27 +- .../WorkflowRuntimeTypeAliasRegistrar.cs | 35 - test/TlsSmoke/Directory.Build.props | 5 + test/TlsSmoke/Program.cs | 16 + test/TlsSmoke/TlsSmoke.csproj | 10 + .../BulkDispatchWorkflowsTests.cs | 18 +- .../Primitives/Event/PublishEventTests.cs | 7 +- .../ConsoleLogsAuthorizationTests.cs | 195 +++-- .../ConsoleLogsHubSourceStatusTests.cs | 101 ++- .../ConsoleLogsModuleTests.cs | 1 + .../ConsoleLogsRecentEndpointTests.cs | 2 +- .../ConsoleLogsSourcesEndpointTests.cs | 2 +- ...ostics.ConsoleLogs.IntegrationTests.csproj | 1 + ...tics.OpenTelemetry.IntegrationTests.csproj | 14 + .../OpenTelemetryAuthorizationTests.cs | 102 +++ .../OpenTelemetryHubTests.cs | 238 ++++++ .../OtlpHttpIngestionTests.cs | 189 +++++ .../OtlpIngestionSecurityTests.cs | 101 +++ .../Usings.cs | 1 + .../JavaScriptFeatureTests.cs | 31 - .../Serialization/JsonSerialization/Tests.cs | 7 +- .../Serialization/Polymorphism/Tests.cs | 10 +- .../Serialization/Polymorphism/data.json | 2 +- .../Entities/OrderDefinitionTests.cs | 22 - .../MediatorBackgroundTaskTests.cs | 101 +++ .../ConsoleHostStateCollection.cs | 6 +- .../ConsoleLogContextAccessorTests.cs | 58 +- .../ConsoleLogsRegistrationTests.cs | 406 ++++++++-- ...a.Diagnostics.ConsoleLogs.UnitTests.csproj | 1 + .../ElsaConsoleLogSubscriptionManagerTests.cs | 156 ++++ .../RecentConsoleLogsEndpointTests.cs | 16 + .../Usings.cs | 2 +- ...Diagnostics.OpenTelemetry.UnitTests.csproj | 12 + .../InMemory/RingBufferTests.cs | 20 + .../Ingestion/OtlpHttpProtobufParserTests.cs | 142 ++++ .../Ingestion/OtlpIngestionSecurityTests.cs | 68 ++ .../InMemoryOpenTelemetryStoreTests.cs | 110 +++ .../OpenTelemetryMetricQueryTests.cs | 45 ++ .../OpenTelemetryStoreTestContext.cs | 59 ++ .../Providers/OpenTelemetryTraceQueryTests.cs | 38 + .../Providers/OtlpLogQueryTests.cs | 28 + .../Services/CollectorConfigurationTests.cs | 41 + .../Services/OpenTelemetryRedactorTests.cs | 39 + .../ShellFeatures/HttpFeatureTests.cs | 29 - .../BackgroundCommandProcessorTests.cs | 108 +++ .../BackgroundNotificationProcessorTests.cs | 145 ++++ .../ActivityExecutionsEndpointTests.cs | 27 + .../Converters/ActivityJsonConverterTests.cs | 6 +- .../ExcludeFromHashConverterTests.cs | 180 ----- .../WorkflowJsonTypeResolverTests.cs | 460 +++++------- .../Services/VariableMapperTests.cs | 44 +- .../Mappers/VariableDefinitionMapperTests.cs | 82 ++ ...rkflowDefinitionExporterRegressionTests.cs | 7 +- .../WorkflowTriggerEqualityComparerTests.cs | 93 +-- ...erviceCollectionWorkflowExtensionsTests.cs | 29 + .../Features/WorkflowRuntimeFeatureTests.cs | 213 ------ 215 files changed, 8517 insertions(+), 1999 deletions(-) create mode 100644 .agents/skills/elsa-roadmap-refresh/SKILL.md create mode 100644 .agents/skills/elsa-roadmap-refresh/agents/openai.yaml create mode 100644 doc/website/product-website-feature-source.md create mode 100644 specs/008-diagnostics-otel/checklists/requirements.md create mode 100644 specs/008-diagnostics-otel/contracts/otlp-ingest.md create mode 100644 specs/008-diagnostics-otel/contracts/provider-contract.md create mode 100644 specs/008-diagnostics-otel/contracts/rest-api.md create mode 100644 specs/008-diagnostics-otel/contracts/signalr-hub.md create mode 100644 specs/008-diagnostics-otel/data-model.md create mode 100644 specs/008-diagnostics-otel/plan.md create mode 100644 specs/008-diagnostics-otel/quickstart.md create mode 100644 specs/008-diagnostics-otel/research.md create mode 100644 specs/008-diagnostics-otel/spec.md create mode 100644 specs/008-diagnostics-otel/tasks.md create mode 100644 src/common/Elsa.Mediator/Services/BackgroundCommandProcessor.cs create mode 100644 src/common/Elsa.Mediator/Services/BackgroundJobProcessor.cs create mode 100644 src/common/Elsa.Mediator/Services/BackgroundNotificationProcessor.cs create mode 100644 src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundProcessingCoordinator.cs create mode 100644 src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundTask.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/AssemblyInfo.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ConsoleStreamJsonConverter.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogProviderServiceCollectionExtensions.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureHostedService.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureShellLease.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogProvider.cs create mode 100644 src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogRecentBuffer.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/AssemblyInfo.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/ICollectorConfigurationProvider.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryIngestor.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryLiveFeed.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryProvider.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryRedactor.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetrySourceRegistry.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryStore.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/CollectorConfiguration/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Logs/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Metrics/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Resources/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Storage/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Trace/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Traces/Endpoint.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/EndpointRouteBuilderExtensions.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ModuleExtensions.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ServiceCollectionExtensions.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Features/OpenTelemetryFeature.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/FodyWeavers.xml create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/HttpProtobuf/OtlpHttpProtobufParser.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/OtlpIngestionSecurity.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryContracts.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryModels.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Options/OpenTelemetryDiagnosticsOptions.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Permissions/OpenTelemetryPermissions.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/RingBuffer.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/README.md create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/IOpenTelemetryClient.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetryHub.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetrySubscriptionManager.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Services/CollectorConfigurationProvider.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Services/DefaultOpenTelemetryProvider.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryIngestor.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryRedactor.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetrySourceRegistry.cs create mode 100644 src/modules/Elsa.Diagnostics.OpenTelemetry/ShellFeatures/OpenTelemetryFeature.cs delete mode 100644 src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs create mode 100644 src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs create mode 100644 src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs create mode 100644 src/modules/Elsa.Workflows.Runtime/Discovery/WorkflowTypeScanner.cs delete mode 100644 src/modules/Elsa.Workflows.Runtime/Helpers/IWorkflowTypeRegistry.cs delete mode 100644 src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowFactoryDictionary.cs delete mode 100644 src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowTypeValidator.cs delete mode 100644 src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs create mode 100644 test/TlsSmoke/Directory.Build.props create mode 100644 test/TlsSmoke/Program.cs create mode 100644 test/TlsSmoke/TlsSmoke.csproj create mode 100644 test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj create mode 100644 test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryAuthorizationTests.cs create mode 100644 test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs create mode 100644 test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpHttpIngestionTests.cs create mode 100644 test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpIngestionSecurityTests.cs create mode 100644 test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Usings.cs delete mode 100644 test/integration/Elsa.JavaScript.IntegrationTests/JavaScriptFeatureTests.cs delete mode 100644 test/unit/Elsa.Common.UnitTests/Entities/OrderDefinitionTests.cs create mode 100644 test/unit/Elsa.Common.UnitTests/ShellHandlers/MediatorBackgroundTaskTests.cs create mode 100644 test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs create mode 100644 test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/RecentConsoleLogsEndpointTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/InMemory/RingBufferTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpHttpProtobufParserTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpIngestionSecurityTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/InMemoryOpenTelemetryStoreTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryMetricQueryTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryStoreTestContext.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryTraceQueryTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OtlpLogQueryTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/CollectorConfigurationTests.cs create mode 100644 test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/OpenTelemetryRedactorTests.cs delete mode 100644 test/unit/Elsa.Http.UnitTests/ShellFeatures/HttpFeatureTests.cs create mode 100644 test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs create mode 100644 test/unit/Elsa.Mediator.UnitTests/BackgroundNotificationProcessorTests.cs create mode 100644 test/unit/Elsa.Workflows.Api.UnitTests/ActivityExecutions/ActivityExecutionsEndpointTests.cs delete mode 100644 test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ExcludeFromHashConverterTests.cs create mode 100644 test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs create mode 100644 test/unit/Elsa.Workflows.Runtime.UnitTests/Extensions/ServiceCollectionWorkflowExtensionsTests.cs delete mode 100644 test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs diff --git a/.agents/skills/elsa-roadmap-refresh/SKILL.md b/.agents/skills/elsa-roadmap-refresh/SKILL.md new file mode 100644 index 000000000..412af9514 --- /dev/null +++ b/.agents/skills/elsa-roadmap-refresh/SKILL.md @@ -0,0 +1,126 @@ +--- +name: elsa-roadmap-refresh +description: Refresh the Elsa roadmap from current evidence. Use when Codex needs to update ROADMAP.md or the public roadmap issue by researching elsa-core, elsa-studio, and elsa-extensions source code, specs, releases, commits, issues, pull requests, and discussions; classify shipped foundations, partial/productization work, roadmap candidates, stale items, and recommendations; then update the roadmap checklist and GitHub issue coherently. +--- + +# Elsa Roadmap Refresh + +## Purpose + +Use this skill to refresh Elsa's roadmap from evidence across the Elsa product surface: + +- `elsa-workflows/elsa-core` +- `elsa-workflows/elsa-studio` +- `elsa-workflows/elsa-extensions` + +The output should be a coherent product roadmap, not a raw issue digest. Ground every substantial change in source code, specs, releases, issues, pull requests, or discussions. + +## Safety Rules + +- Before editing, run `git status --short` in `elsa-core`. +- Never revert unrelated user changes. +- If `ROADMAP.md` or `README.md` already has uncommitted user edits, stop and report the conflict unless the user explicitly asked to work through it. +- Edit only roadmap-related files unless the user asks for more. +- Do not commit, push, or publish unless the user or automation prompt explicitly asks for it. +- If updating GitHub issue `elsa-core#3232`, use the final `ROADMAP.md` body as the issue body. + +## Evidence Workflow + +1. Read the current roadmap. + - `ROADMAP.md` + - `README.md` roadmap link, if relevant + - GitHub issue `elsa-workflows/elsa-core#3232` + +2. Inspect `elsa-core`. + - Source modules under `src/modules` + - App hosts under `src/apps` + - Specs under `specs` + - Docs under `doc` and `design` + - Recent releases, commits, open issues, discussions, and open PRs + +3. Inspect `elsa-studio`. + - Source layout and feature modules + - Designer, diagnostics, auth, localization, embedding, workflow authoring, and instance UX + - Recent releases, commits, open issues, discussions, and open PRs + +4. Inspect `elsa-extensions`. + - Module families and integration foundations + - Connections, Secrets, Agents, OpenAPI, schedulers, messaging, persistence, data tooling, and package manifests + - Recent releases, commits, open issues, and open PRs + - Discussions if enabled; otherwise state that issue/PR signal is the available source + +Use `gh` for GitHub data when available. Prefer local clones when present; otherwise use temporary clones or `gh repo clone` into `/tmp`. + +## Classification Rules + +Use these categories consistently: + +- `[x]` shipped foundation: implemented in source or released enough to build on. +- `[~]` partially shipped or needs productization: code exists, but docs, Studio UX, integration, tests, release packaging, or operational readiness are incomplete. +- `[ ]` roadmap candidate: valuable capability not yet implemented or only represented by issue/PR/proposal. +- stale/obsolete: roadmap item is already done, superseded, or no longer matches repository direction. + +Be explicit when a conclusion is an inference from evidence rather than a direct source fact. + +## Roadmap Editing Rules + +- Keep `ROADMAP.md` product-oriented and exciting, but technically defensible. +- Preserve the main structure unless a better structure is clearly needed: + - North Star + - Capability Checklist + - Current Foundations + - Production Confidence + - Authoring Productivity + - Integrations And Ecosystem + - Observability And Operations + - Security, Identity, And Enterprise Readiness + - AI-Assisted Workflow Engineering + - Recommended Sequencing + - Maintainership Recommendations +- Update `Last refreshed` to the current date. +- Keep issue and PR links close to the claims they support. +- Prefer platform tracks over long lists of unrelated features. +- Separate what is already present from what still needs productization. +- Do not overpromise release dates. + +## High-Value Themes To Re-Evaluate Each Refresh + +- Runtime recovery, graceful shutdown, distributed execution, scheduler/message reliability +- Studio designer reliability, state machine authoring, debugging, progress/timeline, embedded components +- Studio diagnostics, structured logs, console logs, OpenTelemetry, workflow incident timelines +- Extension Platform, package manifests, Connections, Secrets, generated activities, connector SDK +- Agents, MCP/tooling, provider matrix, AI-assisted authoring +- OpenAPI activity provider, Azure Functions, Azure DevOps, Microsoft 365 and Google Workspace integrations +- Security, OIDC, tenant/role activity visibility, localization, white-label readiness +- Marketplace/plugin installation path and package maturity states + +## Recommended GitHub Commands + +```bash +gh issue view 3232 --repo elsa-workflows/elsa-core --json title,body,updatedAt,url +gh issue list --repo elsa-workflows/elsa-core --state open --limit 200 --json number,title,labels,updatedAt,url +gh issue list --repo elsa-workflows/elsa-studio --state open --limit 200 --json number,title,labels,updatedAt,url +gh issue list --repo elsa-workflows/elsa-extensions --state open --limit 200 --json number,title,labels,updatedAt,url +gh pr list --repo elsa-workflows/elsa-core --state open --limit 100 --json number,title,updatedAt,url +gh pr list --repo elsa-workflows/elsa-studio --state open --limit 100 --json number,title,updatedAt,url +gh pr list --repo elsa-workflows/elsa-extensions --state open --limit 100 --json number,title,updatedAt,url +gh release list --repo elsa-workflows/elsa-core --limit 10 +gh release list --repo elsa-workflows/elsa-studio --limit 10 +gh release list --repo elsa-workflows/elsa-extensions --limit 10 +``` + +## Publishing + +When asked to mirror the roadmap to GitHub: + +```bash +gh issue edit 3232 --repo elsa-workflows/elsa-core --body-file ROADMAP.md +``` + +After publishing, verify: + +```bash +gh issue view 3232 --repo elsa-workflows/elsa-core --json title,url,updatedAt +``` + +Final response should summarize changed themes, whether the GitHub issue was updated, and any files left modified. diff --git a/.agents/skills/elsa-roadmap-refresh/agents/openai.yaml b/.agents/skills/elsa-roadmap-refresh/agents/openai.yaml new file mode 100644 index 000000000..dd0db5ea5 --- /dev/null +++ b/.agents/skills/elsa-roadmap-refresh/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Elsa Roadmap Refresh" + short_description: "Refresh the Elsa roadmap from source and GitHub evidence" + default_prompt: "Use $elsa-roadmap-refresh to update ROADMAP.md and mirror it to the public roadmap issue." diff --git a/.specify/feature.json b/.specify/feature.json index 692144c11..d418d5e78 100644 --- a/.specify/feature.json +++ b/.specify/feature.json @@ -1,3 +1,3 @@ { - "feature_directory": "specs/007-secrets-module" + "feature_directory": "specs/008-diagnostics-otel" } diff --git a/AGENTS.md b/AGENTS.md index 420dc3934..62610a8e8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -83,7 +83,7 @@ Before handing off changes, verify the following when applicable: For additional context about technologies to be used, project structure, -shell commands, and other important information, read `specs/007-secrets-module/plan.md`. +shell commands, and other important information, read `specs/008-diagnostics-otel/plan.md`. ## Active Technologies diff --git a/Directory.Packages.props b/Directory.Packages.props index a20a362ba..b66561041 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -99,6 +99,10 @@ + + + + diff --git a/Elsa.sln b/Elsa.sln index 469ecff98..46a604192 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -347,6 +347,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Secrets.UnitTests", "t EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Workflows.Api.UnitTests", "test\unit\Elsa.Workflows.Api.UnitTests\Elsa.Workflows.Api.UnitTests.csproj", "{81CFD2E0-2E5E-4810-ADB8-A08301199166}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry", "src\modules\Elsa.Diagnostics.OpenTelemetry\Elsa.Diagnostics.OpenTelemetry.csproj", "{007E3396-34EE-40A8-B697-23D694DC9EBE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry.UnitTests", "test\unit\Elsa.Diagnostics.OpenTelemetry.UnitTests\Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj", "{D9D6C168-36CB-46EB-838A-B26C22FE9FDB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry.IntegrationTests", "test\integration\Elsa.Diagnostics.OpenTelemetry.IntegrationTests\Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj", "{B5075CE7-7332-4F78-AB3D-492D670789FB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1387,6 +1393,42 @@ Global {81CFD2E0-2E5E-4810-ADB8-A08301199166}.Release|x64.Build.0 = Release|Any CPU {81CFD2E0-2E5E-4810-ADB8-A08301199166}.Release|x86.ActiveCfg = Release|Any CPU {81CFD2E0-2E5E-4810-ADB8-A08301199166}.Release|x86.Build.0 = Release|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x64.ActiveCfg = Debug|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x64.Build.0 = Debug|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x86.ActiveCfg = Debug|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x86.Build.0 = Debug|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|Any CPU.Build.0 = Release|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x64.ActiveCfg = Release|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x64.Build.0 = Release|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x86.ActiveCfg = Release|Any CPU + {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x86.Build.0 = Release|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x64.ActiveCfg = Debug|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x64.Build.0 = Debug|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x86.ActiveCfg = Debug|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x86.Build.0 = Debug|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|Any CPU.Build.0 = Release|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x64.ActiveCfg = Release|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x64.Build.0 = Release|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x86.ActiveCfg = Release|Any CPU + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x86.Build.0 = Release|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x64.ActiveCfg = Debug|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x64.Build.0 = Debug|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x86.ActiveCfg = Debug|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x86.Build.0 = Debug|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|Any CPU.Build.0 = Release|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x64.ActiveCfg = Release|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x64.Build.0 = Release|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x86.ActiveCfg = Release|Any CPU + {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1504,12 +1546,15 @@ Global {A0D906D7-9E4D-4C50-93B4-8720BB0AAFA7} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D} {695814F0-7E8F-469E-9A5A-E46759A4D67C} = {18453B51-25EB-4317-A4B3-B10518252E92} {FB7836E3-1D05-4123-B4FA-B9E722723603} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} + {195FD304-EC3F-4350-93C8-AFE80C4E6896} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D} {D8739449-22DC-42D4-85A4-4BA547B0B458} = {18453B51-25EB-4317-A4B3-B10518252E92} {93E9213A-694D-4AB4-870E-05E44F793133} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} {09B4B78B-FE02-44E2-8667-E182AF921C54} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {7D905CEC-B30B-4C99-B5F7-3052D33EC8E9} = {18453B51-25EB-4317-A4B3-B10518252E92} {81CFD2E0-2E5E-4810-ADB8-A08301199166} = {18453B51-25EB-4317-A4B3-B10518252E92} - {195FD304-EC3F-4350-93C8-AFE80C4E6896} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D} + {D9D6C168-36CB-46EB-838A-B26C22FE9FDB} = {18453B51-25EB-4317-A4B3-B10518252E92} + {B5075CE7-7332-4F78-AB3D-492D670789FB} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} + {007E3396-34EE-40A8-B697-23D694DC9EBE} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E} diff --git a/NuGet.Config b/NuGet.Config index af5965e56..6a0629d8a 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -6,6 +6,7 @@ + @@ -19,5 +20,9 @@ + + + + diff --git a/ROADMAP.md b/ROADMAP.md index c27195307..4470b613d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,6 @@ # Elsa Roadmap -Last refreshed: 2026-05-19 +Last refreshed: 2026-05-29 This roadmap is a product direction document, not a fixed release calendar. Elsa is developed through a mix of core maintainer work, customer-funded work, and community contributions, so sequencing can change when real-world demand changes. The intent is stable: make Elsa the most productive, dependable, and extensible workflow platform for the .NET ecosystem. @@ -38,13 +38,13 @@ Legend: `[x]` shipped foundation, `[~]` partially shipped or needs productizatio - [x] Distributed runtime package - [x] Structured logs - [x] Console logs -- [x] Studio structured-log and console-log foundations +- [x] Studio structured-log, console-log, and OpenTelemetry diagnostics foundations - [~] Durable structured log persistence - [~] Scheduler and message-bus foundations through Quartz, Hangfire, MassTransit, Kafka, and Azure Service Bus -- [ ] OpenTelemetry traces and default workflow metrics +- [~] OpenTelemetry diagnostics backend and default workflow metrics - [ ] Scheduler/message reliability hardening for clustered production workloads - [ ] Production security guide -- [ ] Enterprise deployment checklist +- [ ] Enterprise deployment platform and checklist ### Authoring And Studio @@ -56,8 +56,8 @@ Legend: `[x]` shipped foundation, `[~]` partially shipped or needs productizatio - [~] React Flow, sequence, and state-machine designer foundations - [~] Workflow organization with labels/categories/folders - [~] Workflow progress/timeline surface -- [~] Studio OIDC and identity modules -- [~] Studio diagnostics pages for structured and console logs +- [x] Studio OIDC and identity modules +- [~] Studio diagnostics pages for structured logs, console logs, and OpenTelemetry - [~] Studio alterations module - [ ] Designer reliability/regression hardening - [ ] Input validation and activity version visibility @@ -66,7 +66,7 @@ Legend: `[x]` shipped foundation, `[~]` partially shipped or needs productizatio - [ ] First-class workflow debugging - [ ] Designer extensibility, embedding, and white-label recipes - [ ] Tenant/role-based activity visibility -- [ ] AI-assisted workflow generation +- [~] AI-assisted workflow generation and copilot foundations ### Integrations @@ -77,11 +77,11 @@ Legend: `[x]` shipped foundation, `[~]` partially shipped or needs productizatio - [~] OpenAPI activity/provider foundations - [ ] Connector SDK - [ ] Marketplace/plugin installation -- [ ] Agent provider matrix and MCP/tool lifecycle +- [~] Agent provider matrix, with MCP/tool lifecycle still roadmap - [ ] Dynamic activity generation from OpenAPI, Azure Functions, registered methods, and schemas - [ ] Azure DevOps, Teams, OneDrive, SharePoint, Google Docs, and Google Sheets integration strategy - [ ] SQL authoring quality: Studio drag/drop reliability and IntelliSense -- [ ] Dapper package split and MongoDB secrets parity +- [~] Dapper package split and MongoDB secrets parity - [ ] MassTransit v9 strategy - [ ] Azure Functions / worker-service hosting guidance - [ ] WatchFileSystem and command-line automation activities @@ -93,21 +93,24 @@ Legend: `[x]` shipped foundation, `[~]` partially shipped or needs productizatio These are already present in the codebase and should be treated as foundations for the next roadmap slices: - Multi-targeting for `net8.0`, `net9.0`, and `net10.0` in [`src/Directory.Build.props`](src/Directory.Build.props). +- The `3.7.0` release train shipped across [Core](https://github.com/elsa-workflows/elsa-core/releases/tag/3.7.0), [Studio](https://github.com/elsa-workflows/elsa-studio/releases/tag/3.7.0), and [Extensions](https://github.com/elsa-workflows/elsa-extensions/releases/tag/3.7.0) in May 2026, promoting shell integration, Studio authentication, workflow diagnostics, and extension package metadata into released foundations. - Modular core packages under [`src/modules`](src/modules), with code-first features and CShells shell features documented in [`doc/wiki/module-system.md`](doc/wiki/module-system.md). - A modular server host using CShells and Nuplane package loading in [`src/apps/Elsa.ModularServer.Web`](src/apps/Elsa.ModularServer.Web). - Runtime admin, quiescence, drain, and interrupted recovery infrastructure in [`Elsa.Workflows.Runtime`](src/modules/Elsa.Workflows.Runtime) and runtime admin endpoints in [`Elsa.Workflows.Api`](src/modules/Elsa.Workflows.Api/Endpoints/RuntimeAdmin). - Distributed runtime support in [`Elsa.Workflows.Runtime.Distributed`](src/modules/Elsa.Workflows.Runtime.Distributed). - Structured diagnostics with recent/live capture plus SQLite persistence in [`Elsa.Diagnostics.StructuredLogs`](src/modules/Elsa.Diagnostics.StructuredLogs) and [`Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite`](src/modules/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite). -- Raw stdout/stderr console diagnostics in [`Elsa.Diagnostics.ConsoleLogs`](src/modules/Elsa.Diagnostics.ConsoleLogs). +- Raw stdout/stderr console diagnostics in [`Elsa.Diagnostics.ConsoleLogs`](src/modules/Elsa.Diagnostics.ConsoleLogs), with the post-3.7 console pipeline now carrying workflow and activity execution context through [PR #7536](https://github.com/elsa-workflows/elsa-core/pull/7536). +- Core OpenTelemetry diagnostics are actively in productization through [PR #7537](https://github.com/elsa-workflows/elsa-core/pull/7537), which adds OTLP ingestion, bounded storage, REST APIs, SignalR live updates, collector configuration, security checks, and tests. - State machine core activity support in [`Elsa.Workflows.Core/Activities/StateMachine`](src/modules/Elsa.Workflows.Core/Activities/StateMachine). - ElsaScript DSL and blob storage integration in [`Elsa.Dsl.ElsaScript`](src/modules/Elsa.Dsl.ElsaScript) and [`Elsa.WorkflowProviders.BlobStorage.ElsaScript`](src/modules/Elsa.WorkflowProviders.BlobStorage.ElsaScript). - Activity unit testing helpers and guidance in [`src/common/Elsa.Testing.Shared`](src/common/Elsa.Testing.Shared) and [`doc/qa/test-guidelines.md`](doc/qa/test-guidelines.md). - Label infrastructure in [`Elsa.Labels`](src/modules/Elsa.Labels), which is the likely backend foundation for workflow categories, tags, and folders. - Elsa Studio is already a modular Blazor product shell with workflow authoring, instance browsing, designer modules, diagnostics, authentication, localization, branding, custom elements, and early React wrapper work in [elsa-workflows/elsa-studio](https://github.com/elsa-workflows/elsa-studio). -- Studio `main` includes structured-log and console-log modules, newer React Flow/sequence/state-machine designer work, OIDC/identity infrastructure, custom elements, and an alterations module. +- Studio `3.7.0` shipped the modern authentication framework, Elsa Identity and OIDC modules, activity call-stack visualization, incident count badges, pending-instance filtering, and custom theme/DataPanel extensibility. +- Studio `main` includes structured-log, console-log, and OpenTelemetry diagnostics modules, newer React Flow/sequence/state-machine designer work, OIDC/identity infrastructure, custom elements, and an alterations module. The OpenTelemetry Studio module landed in [elsa-studio#834](https://github.com/elsa-workflows/elsa-studio/pull/834). - Elsa Extensions is an active modular integration repository with 70+ module projects in [elsa-workflows/elsa-extensions](https://github.com/elsa-workflows/elsa-extensions), targeting `net8.0`, `net9.0`, and `net10.0`. - Extensions already provide broad integration foundations: Connections, Secrets, Agents, OpenAPI, SQL/CSV/data tooling, messaging, schedulers, cloud storage, logging, webhooks, persistence providers, and external system activities. -- Recent extension work adds package manifest metadata, Kafka multitenancy/schema triggers, Quartz lifecycle/job cleanup fixes, Dapper bookmark cleanup, and other operational hardening. +- Extensions `3.7.0` adds package manifest metadata, infrastructure attributes, shell features for MassTransit/Quartz/Webhooks, Dapper and MongoDB activity execution-chain lookups, Dapper bookmark queue filtering, Kafka multitenancy/schema-trigger work, Quartz lifecycle/job cleanup fixes, and other operational hardening. The public roadmap issue remains useful history: [elsa-workflows/elsa-core#3232](https://github.com/elsa-workflows/elsa-core/issues/3232). Several items in that issue are now done in code but still open in the issue body, so this file should be considered the current working roadmap. @@ -123,12 +126,14 @@ High-value items: - Treat scheduler and messaging correctness as release-blocking infrastructure. Extensions issues around Quartz clustering and recovery ([elsa-extensions#109](https://github.com/elsa-workflows/elsa-extensions/issues/109), [elsa-extensions#101](https://github.com/elsa-workflows/elsa-extensions/issues/101)), Hangfire duplicate jobs ([elsa-extensions#121](https://github.com/elsa-workflows/elsa-extensions/issues/121)), MassTransit stimulus routing ([elsa-extensions#72](https://github.com/elsa-workflows/elsa-extensions/issues/72)), and Kafka extensibility ([elsa-extensions#134](https://github.com/elsa-workflows/elsa-extensions/issues/134)) all point to the same production theme: clustered workload behavior must be boring, observable, and customizable. - Turn the draft native background execution architecture into an implementation plan. [#7356](https://github.com/elsa-workflows/elsa-core/issues/7356) and [#7313](https://github.com/elsa-workflows/elsa-core/issues/7313) point toward an engine-owned, workflow-aware runtime that can evolve toward an actor-model abstraction without coupling Elsa to Orleans, Proto.Actor, or any single backend. - Treat persistence and migration reliability as a product feature: provider-specific migration validation, large-tenant performance tests, safer defaults, and upgrade notes that cover SQL Server, PostgreSQL, MySQL, SQLite, Oracle, and MongoDB scenarios. +- Promote the Elsa Deployment Platform PRD into scoped implementation work. [#7469](https://github.com/elsa-workflows/elsa-core/issues/7469) defines the right product boundary: declarative environment manifests, immutable deployment artifacts, dry-run validation, deployment history, and GitOps-compatible reconciliation should manage control-plane state without reconciling runtime execution state. - Maintain a security hardening track: document scripting trust boundaries, production-safe Docker posture, OIDC setup, default auth patterns, and secrets redaction. [#7096](https://github.com/elsa-workflows/elsa-core/issues/7096) is a reminder that optional code execution must be explained and guarded clearly. Recommended success measures: - rolling deploys do not leave workflows ambiguous or unrecoverable - every runtime admin action is observable and auditable +- deployments can be previewed, validated, promoted, rolled back, and audited without copying databases or reconciling runtime state - core distributed scenarios have component tests, not only unit coverage - upgrade guides call out migrations, package renames, and production security implications before users hit them @@ -142,7 +147,7 @@ High-value items: - Make designer reliability a visible workstream. Recent Studio issues show expression/input rendering regressions after 3.6 ([elsa-studio#791](https://github.com/elsa-workflows/elsa-studio/issues/791), [elsa-studio#781](https://github.com/elsa-workflows/elsa-studio/issues/781), [elsa-studio#795](https://github.com/elsa-workflows/elsa-studio/issues/795)); these should drive a regression harness for designer rendering, property editors, expression descriptors, drag/drop, and WASM/Server parity. - Make workflow progress visible to application users: a current-state/step API, timeline model, and embeddable progress component. This responds to [discussion #6012](https://github.com/elsa-workflows/elsa-core/discussions/6012) and should reuse execution logs, activity records, call-stack tracking, and real-time workflow updates. - Finish the state machine product surface. The core activity exists, but [#5085](https://github.com/elsa-workflows/elsa-core/issues/5085) should be closed only when JSON serialization, Studio authoring, docs, and examples make state machines approachable. -- Build first-class workflow testing and debugging: test runners for full workflows, breakpoint-like inspection, replay from execution logs where feasible, better failed-activity retry flows, child/descendant workflow instance navigation, and Studio affordances for fault investigation. This expands the activity test helper work that addressed [#3978](https://github.com/elsa-workflows/elsa-core/issues/3978) and matches Studio requests for child workflow visibility ([elsa-studio#152](https://github.com/elsa-workflows/elsa-studio/issues/152)) and breakpoint debugging ([elsa-studio discussion #662](https://github.com/elsa-workflows/elsa-studio/discussions/662)). +- Build first-class workflow testing and debugging: test runners for full workflows, breakpoint-like inspection, replay from execution logs where feasible, better failed-activity retry flows, child/descendant workflow instance navigation, and Studio affordances for fault investigation. The Studio `3.7.0` activity call-stack viewer is a useful foundation, but requests for child workflow visibility ([elsa-studio#152](https://github.com/elsa-workflows/elsa-studio/issues/152)) and breakpoint debugging ([elsa-studio discussion #662](https://github.com/elsa-workflows/elsa-studio/discussions/662)) still need a coherent debugging experience. - Improve Studio authoring fundamentals: input validation ([elsa-studio#15](https://github.com/elsa-workflows/elsa-studio/issues/15)), activity version indicators ([elsa-studio#284](https://github.com/elsa-workflows/elsa-studio/issues/284)), async `/dispatch` instead of blocking `/execute` where appropriate ([elsa-studio#811](https://github.com/elsa-workflows/elsa-studio/issues/811)), designer image export ([elsa-studio#585](https://github.com/elsa-workflows/elsa-studio/issues/585)), and expression evaluation controls ([elsa-studio#643](https://github.com/elsa-workflows/elsa-studio/issues/643)). - Improve designer extensibility, embedding, and white-labeling: custom activity property editors, custom list actions, embeddable designer/viewer recipes, custom elements, React wrapper direction, auth modes, base-path hosting, branding/theme, and clear Blazor/WASM/Server guidance. Community demand appears in [#4743](https://github.com/elsa-workflows/elsa-core/issues/4743), [#6685](https://github.com/elsa-workflows/elsa-core/issues/6685), [discussion #7246](https://github.com/elsa-workflows/elsa-core/discussions/7246), [elsa-studio#137](https://github.com/elsa-workflows/elsa-studio/issues/137), and [elsa-studio discussion #665](https://github.com/elsa-workflows/elsa-studio/discussions/665). - Ship user preference and UI state persistence as a Studio platform feature. [elsa-studio#703](https://github.com/elsa-workflows/elsa-studio/issues/703) already scopes theme, layout, table state, local/session storage, reset behavior, and future server profile storage. @@ -166,10 +171,10 @@ High-value items: - Create an OpenAPI activity provider that turns an OpenAPI document into typed designer activities. This is a recurring ask in [#2961](https://github.com/elsa-workflows/elsa-core/issues/2961) and [#6360](https://github.com/elsa-workflows/elsa-core/issues/6360), and it is the best foundation for a broad connector story. The existing Extensions OpenAPI work should be reconciled with this product goal. - Define a connector SDK before adding many one-off integrations. The SDK should cover authentication, secrets, generated activities, testing, metadata, versioning, packaging, Studio property editors, and manifest-driven installation. - Continue marketplace and plugin infrastructure. The Nuplane modular server, sample package, extension package manifest metadata, and [#7310](https://github.com/elsa-workflows/elsa-core/issues/7310) point to a compelling future where Elsa distributions can install safe custom modules without users maintaining a separate host app. -- Promote Agents to a strategic integration lane: provider matrix, OpenAI and Claude PR resolution, local/OpenRouter/custom endpoints, MCP/tool lifecycle, tool selection in Studio, and auditability. [elsa-extensions#58](https://github.com/elsa-workflows/elsa-extensions/issues/58), [elsa-extensions#98](https://github.com/elsa-workflows/elsa-extensions/pull/98), and [elsa-extensions#63](https://github.com/elsa-workflows/elsa-extensions/pull/63) show both demand and active work. +- Promote Agents to a strategic integration lane: provider matrix, OpenAI and Claude PR resolution, local/OpenRouter/custom endpoints, MCP/tool lifecycle, tool selection in Studio, and auditability. The Extensions source already contains Agents, OpenAI, Azure OpenAI, persistence, API, and Studio modules, while [elsa-extensions#58](https://github.com/elsa-workflows/elsa-extensions/issues/58), [elsa-extensions#98](https://github.com/elsa-workflows/elsa-extensions/pull/98), and [elsa-extensions#63](https://github.com/elsa-workflows/elsa-extensions/pull/63) show the provider matrix and Claude/OpenAI work are still actively moving. - Prioritize enterprise productivity integrations by leverage: Azure DevOps has a concrete implementation path ([elsa-extensions#124](https://github.com/elsa-workflows/elsa-extensions/issues/124), [elsa-extensions#125](https://github.com/elsa-workflows/elsa-extensions/pull/125)); Teams, OneDrive, SharePoint, Google Docs, and Google Sheets should follow a shared connector model rather than separate bespoke designs. - Treat dynamic activity generation as a platform primitive. Azure Functions ([elsa-extensions#39](https://github.com/elsa-workflows/elsa-extensions/issues/39)) and registered-method activities ([elsa-extensions#48](https://github.com/elsa-workflows/elsa-extensions/issues/48)) both point toward schema/method-driven activity generation that can also serve OpenAPI, SDK-generated connectors, and internal enterprise APIs. -- Improve data and automation authoring quality: SQL drag/drop reliability ([elsa-extensions#79](https://github.com/elsa-workflows/elsa-extensions/issues/79)), SQL IntelliSense ([elsa-extensions#88](https://github.com/elsa-workflows/elsa-extensions/issues/88)), Dapper package splitting ([elsa-extensions#131](https://github.com/elsa-workflows/elsa-extensions/issues/131), [elsa-extensions#132](https://github.com/elsa-workflows/elsa-extensions/pull/132)), MongoDB secrets parity ([elsa-extensions#126](https://github.com/elsa-workflows/elsa-extensions/issues/126)), WatchFileSystem ([elsa-extensions#90](https://github.com/elsa-workflows/elsa-extensions/issues/90)), and command-line activities ([elsa-extensions#36](https://github.com/elsa-workflows/elsa-extensions/issues/36)). +- Improve data and automation authoring quality: SQL result typing ([elsa-extensions#153](https://github.com/elsa-workflows/elsa-extensions/issues/153), [elsa-extensions#154](https://github.com/elsa-workflows/elsa-extensions/pull/154)), SQL drag/drop reliability ([elsa-extensions#79](https://github.com/elsa-workflows/elsa-extensions/issues/79)), SQL IntelliSense ([elsa-extensions#88](https://github.com/elsa-workflows/elsa-extensions/issues/88)), Dapper package splitting ([elsa-extensions#131](https://github.com/elsa-workflows/elsa-extensions/issues/131), [elsa-extensions#132](https://github.com/elsa-workflows/elsa-extensions/pull/132)), MongoDB secrets parity ([elsa-extensions#126](https://github.com/elsa-workflows/elsa-extensions/issues/126)), WatchFileSystem ([elsa-extensions#90](https://github.com/elsa-workflows/elsa-extensions/issues/90)), and command-line activities ([elsa-extensions#36](https://github.com/elsa-workflows/elsa-extensions/issues/36)). - Resolve the MassTransit strategy after the v9 licensing change. [discussion #6583](https://github.com/elsa-workflows/elsa-core/discussions/6583) raises a practical ecosystem risk; Elsa should either provide a clean split or reduce dependency weight through a smaller messaging abstraction. - Clarify Azure Functions and worker-service hosting patterns. [discussion #4707](https://github.com/elsa-workflows/elsa-core/discussions/4707) and [discussion #7420](https://github.com/elsa-workflows/elsa-core/discussions/7420) show demand for non-traditional hosts, Windows services, and serverless-adjacent deployments. - Add data movement and streaming workflow primitives. [#4809](https://github.com/elsa-workflows/elsa-core/issues/4809) frames this as datasets, linked services, transforms, and stream-oriented processing inspired by Azure Data Factory and stream analytics. @@ -188,9 +193,9 @@ Recommended success measures: High-value items: -- Finish the diagnostics trilogy: structured logs, console logs, and an explicit OpenTelemetry boundary. Structured and console logs now exist; OpenTelemetry traces/metrics need a current module story because [PR #5810](https://github.com/elsa-workflows/elsa-core/pull/5810) previously introduced a module, [#5988](https://github.com/elsa-workflows/elsa-core/issues/5988) asks for default metrics, and the current repo no longer contains an `Elsa.OpenTelemetry` module. -- Add default workflow semantic metrics: started, resumed, suspended, faulted, completed, active, activity executed/faulted, queue depth, recovery count, drain count, and dispatch latency. Align with OpenTelemetry semantic convention work where possible. -- Build Studio diagnostics pages that are useful under pressure: live console, structured logs, trace/metric links, workflow incident timelines, source health, dropped-event counters, source selection, filters, URL state, export/copy affordances, and direct deep links to workflow instances. +- Finish the diagnostics trilogy: structured logs, console logs, and OpenTelemetry. Structured and console logs now exist; Studio `main` has an OpenTelemetry diagnostics page from [elsa-studio#834](https://github.com/elsa-workflows/elsa-studio/pull/834), and Core has an active backend PR for OTLP ingestion, bounded stores, REST endpoints, SignalR live updates, collector configuration, and tests in [#7537](https://github.com/elsa-workflows/elsa-core/pull/7537). The remaining product work is to merge, release, document, and correlate this with workflow incidents. +- Add default workflow semantic metrics: started, resumed, suspended, faulted, completed, active, activity executed/faulted, queue depth, recovery count, drain count, and dispatch latency. [#5988](https://github.com/elsa-workflows/elsa-core/issues/5988) remains the durable demand signal, while [#7537](https://github.com/elsa-workflows/elsa-core/pull/7537) supplies the first current module boundary. +- Build Studio diagnostics pages that are useful under pressure: live console, structured logs, OpenTelemetry traces/metrics/logs, workflow incident timelines, source health, dropped-event counters, source selection, filters, URL state, export/copy affordances, and direct deep links to workflow instances. - Make execution history easier to reason about: distinguish faulted, interrupted, cancelled, crash-recovered, retried, and operator-modified workflows consistently across API, Studio, logs, and metrics. - Connect diagnostics to workflow navigation: trace/span IDs, log source IDs, child workflow chains, alterations, runtime admin actions, and recovery actions should be correlated instead of presented as isolated tables. @@ -206,7 +211,7 @@ Recommended success measures: High-value items: -- Publish canonical OIDC recipes for Blazor Server, WASM, separate server/studio, and all-in-one hosts. [#7181](https://github.com/elsa-workflows/elsa-core/issues/7181) shows both implementation and documentation demand. +- Publish canonical OIDC recipes for Blazor Server, WASM, separate server/studio, all-in-one hosts, and reverse-proxy sub-path deployments. Studio `3.7.0` shipped the modern authentication modules, [#7181](https://github.com/elsa-workflows/elsa-core/issues/7181) shows Core-side implementation and documentation demand, and [elsa-studio#809](https://github.com/elsa-workflows/elsa-studio/pull/809) shows sub-path redirect URI handling is still being hardened. - Provide a production security guide: API keys, JWT/OIDC, default admin bootstrap, scripting trust levels, C# expression risks, Docker demo boundaries, secret masking, tenant isolation, and permission design. - Expand authorization coverage tests around workflow instances, runtime admin, diagnostics, labels, tenants, and HTTP endpoint activities. - Add Studio governance controls: tenant/role-based activity visibility, permission-aware menus/routes, feature-gated modules, and clear behavior for hidden activities in existing workflow definitions. [elsa-studio#584](https://github.com/elsa-workflows/elsa-studio/issues/584) captures the authoring side of this enterprise need. @@ -226,10 +231,10 @@ Recommended success measures: High-value items: -- Build AI-assisted workflow generation that produces multiple visible activities from intent rather than hiding logic in one script activity. This direction is proposed in [discussion #7367](https://github.com/elsa-workflows/elsa-core/discussions/7367). +- Build AI-assisted workflow generation that produces multiple visible activities from intent rather than hiding logic in one script activity. This direction is proposed in [discussion #7367](https://github.com/elsa-workflows/elsa-core/discussions/7367), and [#7523](https://github.com/elsa-workflows/elsa-core/pull/7523) now provides an active Weaver AI Copilot foundation with AI abstractions, provider/session contracts, chat/tool endpoints, audit events, proposal persistence, EF Core storage, and integration/unit tests. - Provide an Elsa MCP/tooling surface for reading, validating, editing, and explaining workflow JSON/ElsaScript. This would make Elsa a strong fit for AI-enabled .NET development environments. - Align AI authoring with the Extensions Agents work: provider abstractions, MCP tools, OpenAI/Claude/local model support, tool approval, secrets handling, and Studio UX should share contracts instead of creating parallel AI stacks. -- Build a Studio copilot only after the authoring contracts are stable: validation, generated activity metadata, designer APIs, diagnostics links, and test scaffolding should be available before AI generation becomes prominent. [elsa-studio#553](https://github.com/elsa-workflows/elsa-studio/issues/553) has clear community signal and maintainer interest, but it should be an accelerator on top of reliable authoring. +- Build a Studio copilot only after the authoring contracts are stable: validation, generated activity metadata, designer APIs, diagnostics links, and test scaffolding should be available before AI generation becomes prominent. [elsa-studio#553](https://github.com/elsa-workflows/elsa-studio/issues/553) has clear community signal and maintainer interest, while [#7523](https://github.com/elsa-workflows/elsa-core/pull/7523) is still Core/backend-oriented and should not be treated as a complete Studio product surface. - Add "explain this workflow", "find risky activities", "suggest tests", and "generate migration notes" capabilities backed by workflow graph metadata. - Pair AI generation with validation: generated workflows should include test scaffolds, required input/output definitions, secrets handling, and clear review diffs. @@ -245,16 +250,17 @@ Near term: 1. Finish runtime confidence work: graceful shutdown remaining tasks, recovery clarity, distributed runtime regressions, security documentation, and OIDC recipes. 2. Stabilize Studio authoring: designer regression harness, input/property-editor fixes, async dispatch/run UX, state machine Studio/docs completion, and a clear UI framework direction. -3. Make workflow authoring easier to manage at scale: organization, search, progress/timeline APIs, testing docs, and user preference/table-state persistence. -4. Reconcile shipped extension foundations with roadmap status: package manifests, Connections/Secrets, OpenAPI, Agents, schedulers, messaging, and integration maturity labels. +3. Complete the diagnostics trilogy: merge/release the Core OpenTelemetry backend, connect it to the Studio OpenTelemetry page, document collector setup, and correlate traces/logs/metrics with workflow incidents. +4. Make workflow authoring easier to manage at scale: organization, search, progress/timeline APIs, testing docs, and user preference/table-state persistence. +5. Reconcile shipped extension foundations with roadmap status: package manifests, Connections/Secrets, OpenAPI, Agents, schedulers, messaging, and integration maturity labels. Mid term: -1. OpenAPI activity provider plus connector SDK. -2. Extension Platform: generated activities, contribution harnesses, Studio extension recipes, package manifest maturity, and marketplace/plugin installation path built on Nuplane and shell features. -3. OpenTelemetry module boundary, default workflow metrics, and Studio trace/log/incident correlation. +1. Promote [#7469](https://github.com/elsa-workflows/elsa-core/issues/7469) from deployment-platform PRD into an implementation spec covering manifests, immutable artifacts, dry-run validation, deployment history, and API/CLI surfaces. +2. OpenAPI activity provider plus connector SDK. +3. Extension Platform: generated activities, contribution harnesses, Studio extension recipes, package manifest maturity, and marketplace/plugin installation path built on Nuplane and shell features. 4. Workflow debugging, replay-oriented incident analysis, child workflow navigation, and operator recovery UX. -5. Agents provider matrix and MCP/tool lifecycle, with Studio UX that keeps generated workflows inspectable. +5. Weaver AI Copilot productization and Agents provider matrix/MCP lifecycle, with Studio UX that keeps generated workflows inspectable. Longer term: diff --git a/doc/website/product-website-feature-source.md b/doc/website/product-website-feature-source.md new file mode 100644 index 000000000..aa6ffea8e --- /dev/null +++ b/doc/website/product-website-feature-source.md @@ -0,0 +1,438 @@ +# Elsa Product Website Feature Source + +This document is source material for a product website aimed at developers, architects, and CTOs evaluating workflow engines. It was compiled from: + +- `elsa-core`: `/Users/sipke/Projects/Elsa/elsa-core` +- `elsa-studio`: `/Users/sipke/Projects/Elsa/elsa-studio` +- `elsa-extensions`: `/Users/sipke/Projects/Elsa/elsa-extensions-investigation` (`Elsa.Extensions.sln`) + +Use this as the comprehensive feature inventory. The website should not show every item with equal weight; the final section contains instructions for Lovable AI to select and present the strongest public-facing set. + +## Core Workflow Engine + +### Embeddable .NET Workflow Engine + +Elsa runs inside any .NET application and gives teams a workflow runtime they can embed directly into their own products, services, portals, back-office systems, and integration platforms. Workflows can be hosted in ASP.NET Core, run from worker services, or exposed through Elsa's server-style API surface. This matters to engineering teams that need workflow automation without handing orchestration to a black-box SaaS product. + +### Code-First, Designer-First, and JSON Workflows + +Workflows can be authored in C#, visually in Elsa Studio, or represented as JSON. Developers can keep critical workflows close to source control, product teams can iterate visually, and platforms can import/export workflow definitions through APIs or storage providers. This gives organizations a practical path from developer-owned automation to collaborative workflow operations. + +### Long-Running and Short-Running Workflows + +Elsa supports short-running automations as well as durable, long-running business processes that wait for external events, approvals, timers, or callbacks. The runtime persists workflow state, bookmarks, triggers, execution records, and incidents, allowing processes to pause and resume across application restarts and infrastructure events. + +### Rich Control Flow + +Elsa includes core control-flow activities such as `Sequence`, `If`, `Switch`, `For`, `ForEach`, `While`, `Parallel`, `Fork`, `Break`, `End`, `Finish`, `Complete`, and `Fault`. Teams can model simple linear automations, branching business rules, parallel work, loops, and failure paths without building custom orchestration logic for every process. + +### Flowcharts, Sequences, and State Machines + +Elsa's engine includes flowchart, sequence, and state machine execution models. Flowcharts support visual business-process modeling with joins, forks, switches, and token-based execution semantics. Sequences provide straightforward procedural automation. State machines model named states and trigger-driven transitions for processes that are naturally lifecycle-oriented. + +### Triggers, Bookmarks, and Event-Driven Resumption + +Workflows can start from triggers and resume from bookmarks. This is the foundation for event-driven automation: HTTP requests, timers, messages, webhooks, user actions, or external systems can start or continue the right workflow instance. Bookmarks are indexed by the runtime so waiting workflows can be found and resumed efficiently. + +### Background Dispatch and Runtime Workers + +The workflow runtime includes background dispatch for workflows, stimuli, tasks, and activities. This allows requests to hand off work and return while Elsa continues processing asynchronously. It also supports patterns where one workflow dispatches another workflow without coupling the caller to immediate execution. + +### Transactional Dispatch Outbox + +Elsa can use a transactional outbox for workflow dispatches created from inside a running workflow. The outbox prevents silent loss when a process crashes between persisting workflow state and enqueueing a dispatch command. Delivery is at-least-once, with idempotency support for child workflow dispatches. + +### Graceful Shutdown and Recovery + +The runtime includes node-local quiescence, drain orchestration, ingress-source pause/resume behavior, and interrupted workflow recovery. This gives operators a controlled way to stop servers without accepting new work mid-drain, and it helps recover work that was interrupted by shutdowns or crashes. + +### Runtime Administration APIs + +Elsa exposes runtime administration endpoints for status, pause, resume, and force-drain operations. Operators can inspect and control workflow runtime state through API-driven automation rather than relying only on process-level controls. + +### Dead-Lettered Bookmark Queue Management + +Bookmark queue items that expire or exceed delivery attempts can be moved to a dead-letter store. APIs allow operators to inspect, replay, and delete dead-lettered items. This is valuable for production workflows where failed event delivery should be visible and recoverable. + +### Workflow Versioning and Migration + +Elsa supports workflow definition versioning and API-driven migration. Teams can evolve workflows over time, publish new versions, and manage compatibility between definitions and running instances. + +### Workflow Management APIs + +Elsa has API surfaces for definitions, instances, execution journals, activity executions, runtime administration, triggers, bookmarks, and related workflow management concerns. This allows workflow capabilities to be embedded into custom platforms and integrated with existing developer or operator tooling. + +### Custom Activities + +Developers can add first-party or product-specific activities with strongly typed inputs and outputs, descriptors, UI hints, and designer integration. This is the extension point that turns Elsa from a generic workflow engine into a domain automation platform for a specific business. + +### Activities as Composable Building Blocks + +Elsa models workflow work as activities. Activities can be composed into higher-level workflows, and workflows themselves can be exposed as callable units. This supports reuse and standardization across teams. + +### Dynamic Activity Handling + +Elsa includes dynamic and missing-activity handling, allowing workflow definitions and designer/API surfaces to evolve while maintaining controlled behavior when activity types are not available. + +### Expressions and Scripting + +Elsa supports dynamic expressions through C#, JavaScript, Python, and Liquid expression modules. Activities can evaluate runtime data, inputs, variables, outputs, workflow context, and external values without forcing every transformation into compiled code. + +### Workflow Inputs, Outputs, Variables, and Correlation + +Elsa includes typed input/output models, variables, workflow input, activity outputs, correlation, and runtime state capture. This gives workflows structured data flow and allows external systems to correlate events with the right workflow instance. + +### Persistence-Agnostic Architecture + +Elsa is persistence-agnostic and includes persistence packages for EF Core providers such as SQLite, SQL Server, PostgreSQL, MySQL, and Oracle. Extension packages also add Dapper and MongoDB persistence options. This lets teams choose infrastructure that fits existing operational standards. + +### Multi-Tenancy and Identity + +Elsa includes identity, authorization, tenant support, and tenant-aware runtime behavior. This is important for SaaS platforms and internal platforms where different teams, customers, or environments need isolated workflow definitions, instances, and permissions. + +### Secrets Management + +Elsa includes a secrets module design with in-memory, configuration-backed, and encrypted Elsa-managed stores. Secrets are intended for use by activities and integrations that need credentials without exposing sensitive values in workflow definitions. + +### Labels, Key Values, SAS Tokens, and Supporting Infrastructure + +Elsa includes supporting modules such as labels, key-value storage, SAS tokens, caching, mediator infrastructure, and feature/module composition. These are less visible as standalone marketing features but help developers build complete workflow-enabled products. + +## Operations and Observability + +### Workflow Execution Journal + +Elsa stores workflow and activity execution records that can be exposed through APIs and Studio. Operators and developers can inspect what ran, what failed, and how a workflow reached its current state. + +### Structured Log Capture + +`Elsa.Diagnostics.StructuredLogs` captures semantic `ILogger` events from Elsa hosts, redacts sensitive data, stores recent records, exposes REST query endpoints, and streams live events to Studio over SignalR. Records include rendered messages, templates, properties, scopes, exceptions, source metadata, trace/span IDs, workflow context, tenant, and correlation fields. + +### Durable Structured Log Persistence + +Structured logs default to a bounded in-memory store, with relational/SQLite persistence available for durable storage. The design includes bounded write queues, batch writes, retention services, storage diagnostics, and dropped-write reporting. + +### Console Log Streaming + +`Elsa.Diagnostics.ConsoleLogs` captures raw stdout and stderr, preserves the original console output destination, redacts content before buffering or streaming, and exposes recent/live console lines through REST and SignalR. This helps operators diagnose container or process-level output without leaving the workflow management experience. + +### OpenTelemetry Workflow Diagnostics + +The extensions repository includes `Elsa.OpenTelemetry`, and Studio includes an OpenTelemetry diagnostics module. The intent is workflow-aware trace, metric, and log exploration where Core remains responsible for ingestion, redaction, storage, permissions, and API contracts while Studio presents normalized diagnostics views. + +### Configurable Workflow Logging Framework + +The extensions repository includes a logging framework with configurable sinks such as console and Serilog, appsettings-based configuration, custom sink factories, and a `Log` activity for emitting structured log entries from workflows. + +### Source and Storage Diagnostics + +Diagnostics modules track source metadata, source health, storage pressure, dropped durable writes, dropped console lines, and live subscription state. These details are useful in clustered or high-volume environments where observability itself needs operational guardrails. + +## Elsa Studio + +### Modular Workflow Management UI + +Elsa Studio is a modular Blazor application framework built with MudBlazor for managing workflows and related entities. It can run as Blazor Server, Blazor WebAssembly, hosted WebAssembly, or custom elements depending on host requirements. + +### Visual Workflow Designer + +Studio provides a drag-and-drop workflow designer for authoring workflows visually. It integrates with Elsa activity descriptors and UI hints so custom activities can appear in the designer alongside built-in activities. + +### Workflow Definition and Instance Management + +Studio includes workflow modules for managing definitions, viewing workflow state, and working with execution/runtime data exposed by the backend. This turns the engine from a library into an operator-facing workflow platform. + +### Real-Time Workflow and Diagnostics Updates + +Studio uses SignalR-backed clients for live updates such as structured logs and console logs. Authentication providers can configure SignalR connections consistently, allowing live operational views to work with JWT, Elsa Identity, or OpenID Connect setups. + +### Structured Logs Viewer + +Studio's structured log viewer loads recent semantic logs, subscribes to live updates, supports source selection, filtering, pause/reconnect/clear behaviors, and exposes detailed log inspection with properties, scopes, exceptions, trace/span fields, tenant, workflow, correlation, and raw JSON. + +### Console Logs Viewer + +Studio includes a diagnostics console page for raw stdout/stderr streaming. Navigation is feature-gated by backend capability and permission, with unavailable and unauthorized states handled in the UI. + +### OpenTelemetry Diagnostics Viewer + +Studio includes a diagnostics OpenTelemetry shell at `/diagnostics/opentelemetry`, with expected views for resource search, trace search/detail, metrics, OTLP logs, storage diagnostics, and collector configuration. + +### Authentication Options + +Studio supports Elsa Identity and OpenID Connect authentication modules across Blazor Server and WebAssembly hosting models. The architecture includes token providers, automatic refresh, backend API token acquisition, SignalR authentication configuration, and custom unauthorized UI rendering. + +### Localization + +Studio includes localization modules for Blazor Server and WebAssembly. Applications can register localization providers, configure supported cultures, and translate the Studio UI for international teams. + +### Extensible Studio Modules + +Studio modules include dashboard, workflows, designer, labels, environments, security, UI hints, diagnostics, localization, authentication, secrets, workflow contexts, and agents. The modular architecture lets product teams compose the Studio experience that fits their platform. + +### Performance-Oriented Designer + +Recent designer work includes batched activity size calculation, activity size caching, and conditional size updates to improve large workflow loading. This matters for teams building complex workflows with many activities. + +### React Wrapper and Custom Embedding + +Studio includes wrapper projects and host variants that support embedding Elsa workflow design experiences into different frontends, including React-oriented integration samples. + +## Built-In Core Capabilities and Activities + +### HTTP Workflows + +Elsa includes HTTP activities for exposing endpoints, sending HTTP requests, downloading HTTP files, and writing HTTP responses or file responses. This makes it natural to build API-triggered workflows, webhook receivers, integration endpoints, and workflow-backed HTTP services. + +### Scheduling and Timers + +Scheduling activities include cron, delay, start-at, and timer behavior. Workflows can run on schedules, pause until a specific time, or wait for durations without custom background job code. + +### Alterations + +Elsa includes alteration modules for applying operational changes to workflow instances. Extensions add a MassTransit-backed alteration background runner for broker-backed, more resilient background processing. + +### Resilience + +Elsa includes resilience modules for workflow execution and activity behavior. These support more robust process automation in failure-prone distributed systems. + +### Workflow Providers + +Elsa includes workflow providers for loading definitions from blob storage and ElsaScript sources. This allows teams to source workflows from external storage rather than only from the management database. + +### ElsaScript DSL + +The ElsaScript DSL module provides a workflow definition scripting format, useful for teams that want text-based workflow authoring and source-controlled definitions. + +## Extensions Ecosystem + +### AI Agents and Multi-Agent Workflows + +The extensions repository includes an Elsa Agents module built on Microsoft's Agent Framework/Semantic Kernel Agents. It supports configuration-based agents, code-first agents, multi-agent workflows, tool calling, persistent conversations/state, REST APIs, persistence packages, OpenAI and Azure OpenAI providers, workflow activities, and Studio UI. + +### Connections Framework + +The extensions repository includes connection modules for registering, describing, and applying connection information to activities. This is a foundation for reusable, centrally managed integration credentials and connection settings. + +### SQL Automation + +The SQL extension provides `SqlQuery`, `SqlCommand`, and `SqlSingleValue` activities, with providers for MySQL, PostgreSQL, SQLite, and SQL Server. It supports parameterization of workflow inputs, outputs, variables, activity context, execution context, workflow properties, POCOs, dictionaries, arrays, lists, and JSON objects, plus SQL syntax highlighting in Studio. + +### CSV Processing + +The CSV extension provides a `ReadCsv` activity that can read byte arrays, streams, strings, URLs, and uploaded files. It supports delimiters, header detection, dictionary output, and optional strongly typed mapping through CsvHelper. + +### Email Automation + +The extensions repository includes an email module with a `SendEmail` activity. This is a common workflow primitive for notifications, approvals, and operational alerts. + +### Slack Automation + +The Slack extension includes activities for channels, messages, reminders, reactions, stars, files, users, search, and event triggers. Workflows can create/update/delete messages, pin/unpin messages, upload files, manage reminders, list/search users and channels, and react to Slack events. + +### GitHub DevOps Automation + +The GitHub extension includes activities for issues, comments, labels, pull requests, repositories, users, organizations, milestones, releases, gists, branch search, GraphQL queries, and webhook-style triggers for issues, pull requests, and branches. Tokens should be stored securely through Elsa secrets. + +### Service Bus and Messaging + +Extensions include Azure Service Bus, Kafka, and MassTransit packages. Activities can send/publish/produce messages and react to received messages, enabling event-driven workflow automation across common messaging infrastructure. + +### Distributed Runtime with Proto.Actor + +The extensions repository includes actor-based runtime packages, including Proto.Actor-backed workflow runtime and actor modules. This extends Elsa's throughput and distributed execution story beyond the base runtime. + +### Distributed Caching + +Extensions include distributed caching modules over MassTransit and Proto.Actor. These support clustered scenarios where local in-memory assumptions are not enough. + +### Scheduling Backends + +Extensions include Hangfire and Quartz scheduling packages, with Quartz EF Core providers for MySQL, PostgreSQL, SQL Server, and SQLite. This lets teams use mature scheduling infrastructure behind Elsa's workflow scheduling concepts. + +### Persistence Extensions + +Extensions add persistence options such as Dapper, MongoDB, and Elasticsearch. These broaden deployment choices for organizations that standardize on specific storage technologies. + +### File and Blob Storage + +Extensions include Azure Storage and local file storage activities such as upload blob, save file, and open file. Workflows can move files through storage systems as part of business processes. + +### HTTP OpenAPI and Webhooks + +Extensions include OpenAPI and webhook modules for HTTP workflows. These help expose, document, and consume HTTP-driven workflow integration surfaces. + +### Compression and I/O + +Extensions include I/O and compression modules, including ZIP archive creation. These are useful in document, file transfer, and batch processing workflows. + +### Telnyx Telephony Automation + +The Telnyx extension includes call-control activities and webhook triggers such as answer call, hang up, dial, bridge calls, speak text, gather DTMF input, get call status, and react to call hangup or general webhook events. + +### Orchard Core Integration + +The extensions repository includes Orchard Core integration modules, useful for teams building CMS-backed or modular application platforms that also need workflow automation. + +### Retention + +The retention extension includes cleanup strategies and collectors for workflow-related records. This supports operational lifecycle management for workflow data. + +### Workflow Contexts + +Workflow context modules let activities set and use contextual parameters associated with workflow context providers. Studio modules add UI support for workflow context activity settings. + +### Drop-Ins + +Drop-in modules suggest a packaging and extension mechanism for pluggable capabilities. These are relevant to teams building modular workflow platforms. + +### Planned and Roadmap Extensions + +The extensions README lists planned or in-development integrations for Telegram, Discord, Microsoft Teams, Gmail, Outlook, Google Calendar, Microsoft Calendar, Google Drive, OneDrive, Azure Storage, Dropbox, Azure DevOps, GitLab, Jenkins, Datadog, cloud functions, CRM systems, payment providers, AI providers, video platforms, and industrial protocols such as OPC UA, Modbus, and MQTT Sparkplug. These should be presented carefully as ecosystem direction unless confirmed released. + +## Architectural Selling Points + +### Modular Feature System + +Elsa uses explicit feature/module registration, dependency declarations, and extension methods. Teams can add only the capabilities they need, keep hosts lean, and build their own modules using the same conventions as first-party packages. + +### Provider-Neutral Boundaries + +Many Elsa capabilities are expressed behind provider contracts: persistence, structured logs, scheduling, workflow providers, SQL clients, authentication, storage, logging sinks, and diagnostics. This gives architects flexibility to standardize on their own infrastructure. + +### API-First and Studio-Ready + +Core capabilities are exposed through APIs and then surfaced in Studio. This means teams can automate through APIs, use Studio as an operator interface, or build their own UI on top of the same contracts. + +### Production Operations Mindset + +The runtime includes operational concepts such as graceful shutdown, recovery scanning, dead-letter queues, storage diagnostics, redaction, bounded buffers, authorization, tenant-aware behavior, and runtime admin endpoints. These are the details architects and CTOs look for when evaluating production fit. + +### Developer Extensibility + +Elsa is designed for developers to extend: custom activities, expression providers, API endpoints, stores, workflow providers, runtime ingress sources, Studio modules, authentication providers, log sinks, SQL clients, agent providers, and integration modules all have clear extension paths. + +### Open Source and Ecosystem Friendly + +Elsa is distributed through NuGet packages, Docker images, GitHub repositories, and community channels. The ecosystem includes Core, Studio, Extensions, Templates, package catalogs, and professional support options. + +## Recommended Website Feature Selection + +For the public product website, do not display all features as a flat checklist. Select the most compelling features for evaluators: + +1. Visual workflow designer plus embeddable .NET runtime. +2. Code-first, visual, and JSON authoring. +3. Long-running durable workflows with triggers and bookmarks. +4. Rich control flow, including flowcharts, sequences, state machines, and parallel execution. +5. API-first workflow management and runtime administration. +6. Persistence choices and production-ready storage boundaries. +7. Observability: execution journal, structured logs, console logs, OpenTelemetry direction. +8. Security and platform fit: identity, authorization, multi-tenancy, secrets. +9. Extensibility: custom activities, modules, expression providers, Studio modules. +10. Integration ecosystem: HTTP, scheduling, SQL, Slack, GitHub, messaging, files, AI agents. +11. Operational readiness: graceful shutdown, recovery, dead-letter handling, durable dispatch outbox. +12. Studio as a modular operations console, not only a designer. + +## Suggested Public Website Copy + +### Hero + +**Title:** Workflow automation for .NET teams + +**Description:** Elsa is an open-source workflow engine and visual workflow platform for building long-running, event-driven, and integration-heavy processes inside your own .NET applications. + +### Feature: Build Workflows Your Way + +**Title:** Code-first, visual, or JSON workflows + +**Description:** Define workflows in C#, design them visually in Elsa Studio, or store them as JSON for API-driven platforms. Developers can keep critical automation close to source control while business and operations teams collaborate through a visual designer. + +### Feature: Durable Event-Driven Runtime + +**Title:** Long-running workflows that wait, resume, and recover + +**Description:** Model processes that pause for timers, webhooks, approvals, messages, and external events. Elsa persists workflow state, indexes triggers and bookmarks, and resumes the right instance when the next signal arrives. + +### Feature: Visual Studio Experience + +**Title:** A modular Studio for designers and operators + +**Description:** Elsa Studio provides a Blazor-based workflow designer, management UI, diagnostics views, authentication modules, localization, and extensible modules for custom platform experiences. + +### Feature: Integration-Ready + +**Title:** Connect workflows to real systems + +**Description:** Use built-in and extension activities for HTTP, scheduling, SQL, CSV, email, Slack, GitHub, Azure Service Bus, Kafka, files, storage, telephony, and AI agents. Add custom activities when your domain needs first-class workflow building blocks. + +### Feature: Production Operations + +**Title:** Built for production workflow operations + +**Description:** Elsa includes runtime administration, execution journals, graceful shutdown, recovery scanning, dead-letter handling, structured log capture, console streaming, redaction, permissions, and storage diagnostics. + +### Feature: Architecture Fit + +**Title:** Modular, provider-neutral, and extensible + +**Description:** Compose only the features you need, plug in your persistence and infrastructure choices, and extend the platform with custom modules, activities, expression providers, APIs, authentication providers, and Studio screens. + +### Feature: Observability + +**Title:** See what workflows are doing + +**Description:** Inspect workflow execution history, activity records, structured logs, raw console output, source metadata, trace and span correlation, workflow context, tenant, and correlation fields from API and Studio diagnostics views. + +### Feature: Security and Multi-Tenancy + +**Title:** Designed for secure platforms + +**Description:** Elsa includes identity, authorization, tenant-aware behavior, secrets management, authenticated SignalR diagnostics, and permission-gated APIs for teams building SaaS, internal platforms, and regulated automation systems. + +### Feature: AI Workflow Orchestration + +**Title:** Orchestrate agents inside workflows + +**Description:** Elsa Agents brings configuration-based and code-first AI agents, multi-agent workflows, tool calling, stateful conversations, OpenAI and Azure OpenAI providers, APIs, persistence, and Studio integration into the workflow model. + +## Lovable AI Instructions + +Use the source inventory above to design a product website section for Elsa Workflows. The target audience is developers, software architects, engineering managers, and CTOs evaluating workflow engines for .NET platforms. + +Prioritize clarity, technical credibility, and enterprise-readiness over hype. Select the most interesting features rather than displaying the complete inventory. The site should make Elsa feel like a serious embeddable workflow platform with a strong visual designer, production runtime, and integration ecosystem. + +Recommended structure: + +1. Hero: "Workflow automation for .NET teams" with a concise description about open-source, embeddable, event-driven workflow automation. +2. Primary feature grid: 6-8 cards covering authoring flexibility, durable runtime, visual Studio, integrations, operations, observability, security, and extensibility. +3. Architecture band: explain modular/provider-neutral design, custom activities, APIs, and persistence choices. +4. Integrations band: show categories rather than a huge checklist. Use "HTTP & APIs", "Scheduling", "Databases", "Messaging", "DevOps", "Communication", "Files & Storage", and "AI Agents". +5. Operations band: highlight graceful shutdown, recovery, dead-letter queues, runtime admin, logs, and diagnostics. +6. CTA: invite visitors to try the Docker image, explore docs, or view GitHub. + +Use these exact card titles unless the layout requires shorter labels: + +- Build Workflows Your Way +- Durable Event-Driven Runtime +- Visual Workflow Studio +- Integration-Ready Automation +- Production Workflow Operations +- Observable by Design +- Secure Multi-Tenant Platform +- Extensible by Developers + +Use concise card descriptions derived from the suggested public copy. Avoid listing unreleased/planned extensions as if they are shipped. If planned ecosystem items are mentioned, label them as roadmap or ecosystem direction. + +Visual direction: + +- Use product screenshots or workflow/designer imagery prominently. +- Keep the design technical, polished, and readable. +- Avoid vague abstract SaaS imagery. +- Favor architecture diagrams, workflow nodes, log/detail panels, integration icons, and code snippets. +- Make the first viewport communicate that Elsa is both a workflow engine and a visual workflow platform. + +Tone: + +- Direct, practical, developer-first. +- Avoid exaggerated claims such as "effortless", "revolutionary", or "no-code magic". +- Emphasize control, extensibility, operational readiness, and .NET-native integration. diff --git a/doc/wiki/opentelemetry-workflows.md b/doc/wiki/opentelemetry-workflows.md index f41449514..3896934cf 100644 --- a/doc/wiki/opentelemetry-workflows.md +++ b/doc/wiki/opentelemetry-workflows.md @@ -6,8 +6,12 @@ To collect workflow traces, configure OpenTelemetry to listen to the `Elsa.Workf ```csharp services.AddOpenTelemetry() - .WithTracing(builder => builder.AddSource("Elsa.Workflows")) - .WithMetrics(builder => builder.AddMeter("Elsa.Workflows")); + .WithTracing(builder => builder + .AddSource("Elsa.Workflows") + .AddOtlpExporter()) + .WithMetrics(builder => builder + .AddMeter("Elsa.Workflows") + .AddOtlpExporter()); ``` If you previously enabled workflow tracing through the `Elsa.OpenTelemetry` extension package, avoid enabling both the extension tracing middleware and the first-party workflow spans for the same host unless duplicate workflow and activity spans are acceptable. Both integrations publish to the `Elsa.Workflows` activity source so existing collectors can keep the same source configuration. @@ -30,3 +34,53 @@ The `Elsa.Workflows` meter emits: - `elsa.activity.duration` in seconds Metric tags use the same low-cardinality workflow and activity metadata as the spans where practical. The started counter omits execution status tags because it records the pre-execution boundary; completed and faulted counters include terminal workflow status tags. + +## Elsa Diagnostics Collector + +The `Elsa.Diagnostics.OpenTelemetry` module can collect OTLP HTTP/protobuf telemetry for local diagnostics and Studio visualization. The default ingestion routes are: + +- `/elsa/otlp/v1/traces` +- `/elsa/otlp/v1/metrics` +- `/elsa/otlp/v1/logs` + +Use the collector for development and focused troubleshooting. Production deployments should usually export to an external OpenTelemetry Collector or observability backend unless Elsa collector capacity, retention, and ingress security are deliberately configured for that environment. + +### .NET Setup + +Configure the .NET OpenTelemetry SDK to collect Elsa workflow instrumentation and export via OTLP: + +```csharp +services.AddOpenTelemetry() + .WithTracing(builder => builder + .AddSource("Elsa.Workflows") + .AddOtlpExporter()) + .WithMetrics(builder => builder + .AddMeter("Elsa.Workflows") + .AddOtlpExporter()); +``` + +Then configure standard OTEL environment variables for the process: + +```bash +OTEL_SERVICE_NAME=elsa-server +OTEL_RESOURCE_ATTRIBUTES=service.instance.id=local-dev +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5000/elsa/otlp/v1 +OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf +OTEL_BSP_SCHEDULE_DELAY=1000 +OTEL_METRIC_EXPORT_INTERVAL=1000 +``` + +If the collector is exposed beyond loopback, also configure the required API key header. The header name is returned by the collector configuration API; do not expose the secret value through Studio or documentation. + +### Polyglot Setup + +Non-.NET services can use the same standard OTEL variables: + +```bash +OTEL_SERVICE_NAME=worker +OTEL_RESOURCE_ATTRIBUTES=service.instance.id=worker-1 +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5000/elsa/otlp/v1 +OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf +``` + +Use each language SDK's OTLP exporter package. Studio identifies resources by `service.name` and `service.instance.id` when those attributes are present. diff --git a/docker/ElsaServer-Datadog.Dockerfile b/docker/ElsaServer-Datadog.Dockerfile index 9305f71e8..13c6f966d 100644 --- a/docker/ElsaServer-Datadog.Dockerfile +++ b/docker/ElsaServer-Datadog.Dockerfile @@ -13,7 +13,7 @@ COPY *.props ./ RUN dotnet restore "./src/apps/Elsa.Server.Web/Elsa.Server.Web.csproj" # Build and publish (UseAppHost=false creates platform independent binaries). -WORKDIR /source/src/bundles/Elsa.Server.Web +WORKDIR /source/src/apps/Elsa.Server.Web RUN dotnet build "Elsa.Server.Web.csproj" -c Release -o /app/build RUN dotnet publish "Elsa.Server.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false --no-restore -f net10.0 @@ -27,20 +27,21 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ - libpython3.11 \ - python3.11 \ - python3.11-dev \ + libpython3-dev \ + python3 \ + python3-dev \ python3-pip \ unzip \ wget \ && update-ca-certificates \ + && ln -s "$(find /usr/lib -name 'libpython3*.so' -print -quit)" /usr/local/lib/libpython3.so \ && rm -rf /var/lib/apt/lists/* COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh # Set PYTHONNET_PYDLL environment variable -ENV PYTHONNET_PYDLL=/usr/lib/aarch64-linux-gnu/libpython3.11.so +ENV PYTHONNET_PYDLL=/usr/local/lib/libpython3.so # Set environment variables for OpenTelemetry Auto-Instrumentation ENV OTEL_DOTNET_AUTO_HOME=/otel \ diff --git a/docker/ElsaServer.Dockerfile b/docker/ElsaServer.Dockerfile index c194e4253..30d51c454 100644 --- a/docker/ElsaServer.Dockerfile +++ b/docker/ElsaServer.Dockerfile @@ -23,18 +23,19 @@ COPY --from=build /app/publish ./ RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ - libpython3.11 \ - python3.11 \ - python3.11-dev \ + libpython3-dev \ + python3 \ + python3-dev \ python3-pip \ && update-ca-certificates \ + && ln -s "$(find /usr/lib -name 'libpython3*.so' -print -quit)" /usr/local/lib/libpython3.so \ && rm -rf /var/lib/apt/lists/* COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh # Set PYTHONNET_PYDLL environment variable -ENV PYTHONNET_PYDLL=/usr/lib/aarch64-linux-gnu/libpython3.11.so +ENV PYTHONNET_PYDLL=/usr/local/lib/libpython3.so EXPOSE 8080/tcp EXPOSE 443/tcp diff --git a/docker/ElsaServerAndStudio.Dockerfile b/docker/ElsaServerAndStudio.Dockerfile index 726904cd0..95c1c7bfb 100644 --- a/docker/ElsaServerAndStudio.Dockerfile +++ b/docker/ElsaServerAndStudio.Dockerfile @@ -7,13 +7,12 @@ COPY ./NuGet.Config ./ COPY *.props ./ # restore packages. -RUN dotnet restore "./src/apps/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj" -RUN dotnet restore "./src/apps/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj" +RUN dotnet restore "./src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj" # build and publish (UseAppHost=false creates platform independent binaries). -WORKDIR /source/src/apps/Elsa.ServerAndStudio.Web -RUN dotnet build "Elsa.ServerAndStudio.Web.csproj" -c Release -o /app/build -RUN dotnet publish "Elsa.ServerAndStudio.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false --no-restore -f net10.0 +WORKDIR /source/src/apps/Elsa.ModularServer.Web +RUN dotnet build "Elsa.ModularServer.Web.csproj" -c Release -o /app/build +RUN dotnet publish "Elsa.ModularServer.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false --no-restore -f net10.0 # move binaries into smaller base image. FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base @@ -24,20 +23,21 @@ COPY --from=build /app/publish ./ RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ - libpython3.11 \ - python3.11 \ - python3.11-dev \ + libpython3-dev \ + python3 \ + python3-dev \ python3-pip \ && update-ca-certificates \ + && ln -s "$(find /usr/lib -name 'libpython3*.so' -print -quit)" /usr/local/lib/libpython3.so \ && rm -rf /var/lib/apt/lists/* COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh # Set PYTHONNET_PYDLL environment variable -ENV PYTHONNET_PYDLL=/usr/lib/aarch64-linux-gnu/libpython3.11.so +ENV PYTHONNET_PYDLL=/usr/local/lib/libpython3.so EXPOSE 8080/tcp EXPOSE 443/tcp ENTRYPOINT ["/entrypoint.sh"] -CMD ["dotnet", "Elsa.ServerAndStudio.Web.dll"] +CMD ["dotnet", "Elsa.ModularServer.Web.dll"] diff --git a/docker/ElsaStudio.Dockerfile b/docker/ElsaStudio.Dockerfile index 34b69c0c9..61b6032f3 100644 --- a/docker/ElsaStudio.Dockerfile +++ b/docker/ElsaStudio.Dockerfile @@ -7,13 +7,12 @@ COPY ./NuGet.Config ./ COPY *.props ./ # restore packages. -RUN dotnet restore "./src/apps/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj" -RUN dotnet restore "./src/apps/Elsa.Studio.Web/Elsa.Studio.Web.csproj" +RUN dotnet restore "./src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj" # build and publish (UseAppHost=false creates platform independent binaries). -WORKDIR /source/src/apps/Elsa.Studio.Web -RUN dotnet build "Elsa.Studio.Web.csproj" -c Release -o /app/build -RUN dotnet publish "Elsa.Studio.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false --no-restore -f net10.0 +WORKDIR /source/src/apps/Elsa.ModularServer.Web +RUN dotnet build "Elsa.ModularServer.Web.csproj" -c Release -o /app/build +RUN dotnet publish "Elsa.ModularServer.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false --no-restore -f net10.0 # move binaries into smaller base image. FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base @@ -32,4 +31,4 @@ RUN chmod +x /entrypoint.sh EXPOSE 8080/tcp EXPOSE 443/tcp ENTRYPOINT ["/entrypoint.sh"] -CMD ["dotnet", "Elsa.Studio.Web.dll"] +CMD ["dotnet", "Elsa.ModularServer.Web.dll"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 356daf467..2df206496 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -75,6 +75,16 @@ services: - ASPNETCORE_URLS=http://+:80 - Logging__LogLevel__Default=Information + aspire-dashboard: + image: mcr.microsoft.com/dotnet/aspire-dashboard:latest + container_name: aspire-dashboard + ports: + - "18888:18888" # Dashboard UI + - "4317:18889" # OTLP/gRPC + - "4318:18890" # OTLP/HTTP + environment: + ASPIRE_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS: "true" + volumes: sqlserver_data: postgres-data: diff --git a/scripts/test-ca-trust.sh b/scripts/test-ca-trust.sh index 7c078606b..42f0bcdf7 100755 --- a/scripts/test-ca-trust.sh +++ b/scripts/test-ca-trust.sh @@ -54,40 +54,48 @@ CERTEXT fi sleep 0.2 done +} - echo "$CERT_WORKDIR" +cleanup_local_ca_server() { + if [ -n "${SERVER_PID:-}" ]; then + kill "$SERVER_PID" >/dev/null 2>&1 || true + wait "$SERVER_PID" 2>/dev/null || true + SERVER_PID= + fi + + if [ -n "${CERT_WORKDIR:-}" ]; then + rm -rf "$CERT_WORKDIR" + CERT_WORKDIR= + fi } run_extra_ca_test() { - local cert_dir - cert_dir=$(start_local_ca_server) - trap "kill ${SERVER_PID:-0} >/dev/null 2>&1 || true; rm -rf '$cert_dir'" EXIT + start_local_ca_server + trap cleanup_local_ca_server EXIT echo "[CA] Validating EXTRA_CA_CERT flow against local CA" >&2 run_smoke "https://host.docker.internal:${LOCAL_PORT}" \ --add-host host.docker.internal:host-gateway \ - -v "${cert_dir}:/certs:ro" \ + -v "${CERT_WORKDIR}:/certs:ro" \ -e EXTRA_CA_CERT=/certs/ca.crt echo "[CA] Validating SSL_CERT_FILE fallback" >&2 run_smoke "https://host.docker.internal:${LOCAL_PORT}" \ --add-host host.docker.internal:host-gateway \ - -v "${cert_dir}:/certs:ro" \ + -v "${CERT_WORKDIR}:/certs:ro" \ -e SSL_CERT_FILE=/certs/ca.crt - mkdir -p "$cert_dir/dir" - cp "$cert_dir/ca.crt" "$cert_dir/dir/custom-ca.crt" - openssl rehash "$cert_dir/dir" >/dev/null 2>&1 + mkdir -p "$CERT_WORKDIR/dir" + cp "$CERT_WORKDIR/ca.crt" "$CERT_WORKDIR/dir/custom-ca.crt" + openssl rehash "$CERT_WORKDIR/dir" >/dev/null 2>&1 echo "[CA] Validating SSL_CERT_DIR fallback" >&2 run_smoke "https://host.docker.internal:${LOCAL_PORT}" \ --add-host host.docker.internal:host-gateway \ - -v "${cert_dir}:/certs:ro" \ + -v "${CERT_WORKDIR}:/certs:ro" \ -e SSL_CERT_DIR=/certs/dir - kill "${SERVER_PID:-0}" >/dev/null 2>&1 || true - wait "${SERVER_PID:-0}" 2>/dev/null || true - rm -rf "$cert_dir" + cleanup_local_ca_server trap - EXIT } diff --git a/specs/008-diagnostics-otel/checklists/requirements.md b/specs/008-diagnostics-otel/checklists/requirements.md new file mode 100644 index 000000000..de04485bb --- /dev/null +++ b/specs/008-diagnostics-otel/checklists/requirements.md @@ -0,0 +1,31 @@ +# Specification Quality Checklist: Diagnostics OpenTelemetry + +**Purpose**: Validate Core specification completeness before implementation +**Created**: 2026-05-25 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details in product requirements beyond Core system boundaries +- [x] Focused on user value and backend diagnostics needs +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] Functional requirements have clear acceptance criteria +- [x] User scenarios cover primary Core flows +- [x] Technical plan identifies Core module boundaries + +## Notes + +- Studio UI work is intentionally tracked in `elsa-studio/specs/008-diagnostics-otel`. diff --git a/specs/008-diagnostics-otel/contracts/otlp-ingest.md b/specs/008-diagnostics-otel/contracts/otlp-ingest.md new file mode 100644 index 000000000..e6b3913ec --- /dev/null +++ b/specs/008-diagnostics-otel/contracts/otlp-ingest.md @@ -0,0 +1,50 @@ +# Contract: OTLP Ingestion + +## HTTP/protobuf + +Default base path: + +```text +/elsa/otlp/v1 +``` + +Supported paths: + +```text +POST /elsa/otlp/v1/traces +POST /elsa/otlp/v1/metrics +POST /elsa/otlp/v1/logs +``` + +Requests use OTLP protobuf bodies. Accepted payloads return `200 OK`; unauthorized requests return `401 Unauthorized`; malformed protobuf payloads return `400 Bad Request`; payloads over the configured request body limit return `413 Payload Too Large`. The current collector does not emit OTLP partial-success response bodies. + +## gRPC + +When enabled, Core exposes OTLP gRPC services: + +```text +opentelemetry.proto.collector.trace.v1.TraceService/Export +opentelemetry.proto.collector.metrics.v1.MetricsService/Export +opentelemetry.proto.collector.logs.v1.LogsService/Export +``` + +When gRPC is disabled, collector configuration must return `GrpcEnabled = false` and no endpoint. + +## Security + +- Loopback-only development ingestion may run without an API key only when the request remote address is loopback and the advertised collector binding is loopback. +- Non-loopback requests and non-loopback collector bindings must require a configured header such as `x-otlp-api-key`. +- Secret header values are configured server-side, compared without exposing the configured value, and omitted from collector configuration responses. +- Accepted telemetry is redacted before storage and live streaming. +- OTLP sender auth is separate from diagnostics API user auth. + +## Internal Contract + +```csharp +public interface IOpenTelemetryIngestor +{ + ValueTask IngestAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default); +} +``` + +Transport-specific code parses payloads; shared ingestion normalizes, redacts, stores, and publishes live updates. diff --git a/specs/008-diagnostics-otel/contracts/provider-contract.md b/specs/008-diagnostics-otel/contracts/provider-contract.md new file mode 100644 index 000000000..7b0f974ff --- /dev/null +++ b/specs/008-diagnostics-otel/contracts/provider-contract.md @@ -0,0 +1,48 @@ +# Contract: Provider and Store + +## Provider Facade + +```csharp +public interface IOpenTelemetryProvider +{ + ValueTask SearchResourcesAsync(TelemetryResourceFilter filter, CancellationToken cancellationToken = default); + ValueTask SearchTracesAsync(TelemetryTraceFilter filter, CancellationToken cancellationToken = default); + ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default); + ValueTask SearchMetricsAsync(TelemetryMetricFilter filter, CancellationToken cancellationToken = default); + ValueTask SearchLogsAsync(OtlpLogFilter filter, CancellationToken cancellationToken = default); + ValueTask GetStorageDiagnosticsAsync(CancellationToken cancellationToken = default); +} +``` + +## Store + +```csharp +public interface IOpenTelemetryStore +{ + ValueTask WriteTracesAsync(IReadOnlyCollection spans, CancellationToken cancellationToken = default); + ValueTask WriteMetricsAsync(IReadOnlyCollection metrics, CancellationToken cancellationToken = default); + ValueTask WriteLogsAsync(IReadOnlyCollection logs, CancellationToken cancellationToken = default); +} +``` + +The concrete in-memory implementation also supports provider queries. A later durable provider may split write/query responsibilities if needed. + +Search methods return bounded results using server-capped limits. Search ordering is newest receive time first. Trace detail ordering is parent/child chronological so Studio can render a waterfall without reassembling hierarchy from arbitrary span order. + +## Redaction + +```csharp +public interface IOpenTelemetryRedactor +{ + TelemetryResource Redact(TelemetryResource resource); + TelemetrySpan Redact(TelemetrySpan span); + MetricPoint Redact(MetricPoint point); + OtlpLogRecord Redact(OtlpLogRecord logRecord); +} +``` + +Redaction occurs before store writes and live publishing. + +## Capacity + +The default in-memory provider uses configurable per-signal limits with drop-oldest overflow. Defaults must be at least 500 resources, 2,000 traces, 10,000 spans, 20,000 metric points, 10,000 OTLP log records, and 1,000 queued live updates per subscriber. diff --git a/specs/008-diagnostics-otel/contracts/rest-api.md b/specs/008-diagnostics-otel/contracts/rest-api.md new file mode 100644 index 000000000..66c128a48 --- /dev/null +++ b/specs/008-diagnostics-otel/contracts/rest-api.md @@ -0,0 +1,67 @@ +# Contract: REST API + +Base path: + +```text +/diagnostics/opentelemetry +``` + +All endpoints require the OpenTelemetry diagnostics view permission. + +Search endpoints accept a caller-provided limit capped by server options. Trace, metric, and log search results return the latest matching window in ascending chronological order. Resource search results are ordered by most recently seen first. Trace detail spans are returned in parent/child order with chronological ordering inside each sibling set. + +## Resources + +```text +POST /diagnostics/opentelemetry/resources/search +``` + +Filters by service name, status, and text. + +## Trace Search + +```text +POST /diagnostics/opentelemetry/traces/search +``` + +Filters by resource key, service name, trace ID, workflow instance ID, workflow definition ID, status, text, and time range. + +## Trace Detail + +```text +GET /diagnostics/opentelemetry/traces/{traceId} +``` + +Returns trace summary, ordered spans, related resources, and OTLP logs for the trace when available. + +## Metrics + +```text +POST /diagnostics/opentelemetry/metrics/search +``` + +Filters by resource, instrument name, attribute text, and time range. + +## OTLP Logs + +```text +POST /diagnostics/opentelemetry/logs/search +``` + +Filters by resource, trace ID, span ID, severity, text, and time range. + +## Collector Configuration + +```text +GET /diagnostics/opentelemetry/collector-configuration +``` + +Returns HTTP endpoint metadata, nullable/disabled gRPC metadata, required header names, loopback status, and recommended non-secret OTEL environment variables. + +## Storage Diagnostics + +```text +GET /diagnostics/opentelemetry/storage +``` + +Returns capacity, dropped counts, and current resource/trace/series counts. diff --git a/specs/008-diagnostics-otel/contracts/signalr-hub.md b/specs/008-diagnostics-otel/contracts/signalr-hub.md new file mode 100644 index 000000000..f788b4d96 --- /dev/null +++ b/specs/008-diagnostics-otel/contracts/signalr-hub.md @@ -0,0 +1,39 @@ +# Contract: SignalR Hub + +Hub path: + +```text +/elsa/hubs/diagnostics/opentelemetry +``` + +The hub requires the OpenTelemetry diagnostics view permission. + +## Client-to-Server Methods + +```text +SubscribeAsync(OpenTelemetryTraceFilter filter) +``` + +Filters support resource ID, service name, trace ID, workflow instance ID, workflow definition ID, status, text, and time range. Metric clients subscribe through the trace-filter-compatible live stream and apply metric-specific filtering client-side. + +## Server-to-Client Events + +```text +ReceiveAsync(OpenTelemetryStreamItem item) +``` + +`OpenTelemetryStreamItem` variants: + +- `Resource` +- `Trace` +- `MetricPoint` +- `Log` +- `DroppedItems` + +## Lifecycle + +- Subscriptions are bounded by server-side per-connection subscriber capacity. +- Filter changes are represented by starting a new subscription. +- Disconnected clients release subscriber resources. +- When a subscriber queue is full, live updates are dropped and reported through `DroppedItems` summaries. +- Subscriber overflow must not disconnect the client unless the connection itself is unhealthy or unauthorized. diff --git a/specs/008-diagnostics-otel/data-model.md b/specs/008-diagnostics-otel/data-model.md new file mode 100644 index 000000000..f1c72d262 --- /dev/null +++ b/specs/008-diagnostics-otel/data-model.md @@ -0,0 +1,104 @@ +# Data Model: Diagnostics OpenTelemetry + +## Telemetry Resource + +| Field | Notes | +|-------|-------| +| `ResourceKey` | Stable key derived from service name, instance ID, and resource attributes. | +| `ServiceName` | From `service.name` or `OTEL_SERVICE_NAME`; fallback is `unknown_service`. | +| `ServiceInstanceId` | From `service.instance.id` when present. | +| `ServiceVersion` | From `service.version` when present. | +| `DeploymentEnvironment` | From `deployment.environment` when present. | +| `Attributes` | Redacted resource attributes. | +| `FirstSeen`, `LastSeen` | Backend receive timestamps. | +| `Status` | Active, stale, or disconnected. | + +## Telemetry Trace + +| Field | Notes | +|-------|-------| +| `TraceId` | Required trace identifier. | +| `RootSpanId` | Root span when known. | +| `Name` | Root span name or synthesized trace label. | +| `ResourceKeys` | Participating resources. | +| `StartTime`, `EndTime`, `Duration` | Derived from spans. | +| `Status` | Ok, error, unset, or mixed. | +| `SpanCount`, `ErrorCount` | Derived counters. | +| `WorkflowInstanceId`, `WorkflowDefinitionId` | Elsa span attributes when present. | +| `LastReceivedAt` | Backend receive timestamp. | + +## Telemetry Span + +| Field | Notes | +|-------|-------| +| `TraceId`, `SpanId`, `ParentSpanId` | Trace hierarchy. | +| `ResourceKey` | Emitting resource. | +| `Name`, `Kind` | OTEL span metadata. | +| `StartTime`, `EndTime`, `Duration` | Timing. | +| `StatusCode`, `StatusDescription` | OTEL status. | +| `Attributes` | Redacted span attributes. | +| `Events` | Redacted events. | +| `Links` | Span links. | +| `Workflow*`, `Activity*`, `TenantId`, `CorrelationId` | Existing `Elsa.Workflows` semantic attributes when present: `workflow.*`, `workflow.activity.*`, and `elsa.tenant.id`. | +| `ReceivedAt` | Backend receive timestamp. | + +## Metric Instrument and Point + +| Field | Notes | +|-------|-------| +| `Name`, `Description`, `Unit`, `Type` | Instrument metadata. | +| `ResourceKey` | Emitting resource. | +| `Series` | Bounded collection by attribute set. | +| `Timestamp`, `StartTimestamp` | Point timestamps. | +| `Attributes` | Redacted point attributes. | +| `Value` | Sum/gauge value. | +| `Count`, `Sum`, `Min`, `Max`, `Buckets` | Histogram fields when present. | +| `Temporality` | Cumulative or delta. | +| `DroppedPointCount` | Capacity drop count. | + +## OTLP Log Record + +| Field | Notes | +|-------|-------| +| `Id` | Backend assigned ID. | +| `Timestamp`, `ObservedTimestamp`, `ReceivedAt` | OTLP and backend timing. | +| `ResourceKey` | Emitting resource. | +| `SeverityText`, `SeverityNumber` | OTEL severity. | +| `Body` | Redacted body. | +| `TraceId`, `SpanId` | Correlation fields. | +| `Attributes` | Redacted log attributes. | + +## Collector Configuration + +| Field | Notes | +|-------|-------| +| `HttpEndpoint` | Base endpoint suitable for `OTEL_EXPORTER_OTLP_ENDPOINT` with HTTP/protobuf. | +| `GrpcEndpoint` | Endpoint suitable for gRPC when enabled; null when unavailable. | +| `GrpcEnabled` | Whether gRPC ingestion is enabled. | +| `GrpcDisabledReason` | Optional non-secret explanation when disabled. | +| `RequiredHeaders` | Required ingestion header names without secret values. | +| `RecommendedEnvironment` | Copyable non-secret OTEL environment variable values. | +| `IsLoopbackOnly` | Whether ingestion is restricted to loopback. | +| `RequiresApiKey` | Whether configured ingestion protection is required for advertised endpoints. | + +## Storage Diagnostics + +| Field | Notes | +|-------|-------| +| `DroppedSpanCount` | Spans dropped by store capacity. | +| `DroppedMetricPointCount` | Metric points dropped by capacity. | +| `DroppedLogRecordCount` | OTLP logs dropped by capacity. | +| `DroppedLiveUpdateCount` | Live updates dropped by subscriber capacity. | +| `ResourceCount`, `TraceCount`, `MetricSeriesCount` | Current counts. | + +## Storage Capacity Policy + +| Field | Notes | +|-------|-------| +| `MaxResources` | Default at least 500. | +| `MaxTraces` | Default at least 2,000. | +| `MaxSpans` | Default at least 10,000. | +| `MaxMetricPoints` | Default at least 20,000 across all metric series. | +| `MaxLogRecords` | Default at least 10,000. | +| `MaxLiveUpdatesPerSubscriber` | Default at least 1,000 queued updates per SignalR subscriber. | +| `OverflowPolicy` | Drop oldest item in the signal-specific buffer and increment the matching dropped counter. | diff --git a/specs/008-diagnostics-otel/plan.md b/specs/008-diagnostics-otel/plan.md new file mode 100644 index 000000000..0fd66f7df --- /dev/null +++ b/specs/008-diagnostics-otel/plan.md @@ -0,0 +1,149 @@ +# Implementation Plan: Diagnostics OpenTelemetry + +**Branch**: `008-diagnostics-otel` | **Date**: 2026-05-25 | **Spec**: [spec.md](./spec.md) +**Input**: Feature specification from `/specs/008-diagnostics-otel/spec.md` + +## Summary + +Add an opt-in `Elsa.Diagnostics.OpenTelemetry` Core diagnostics module that receives OTLP telemetry, normalizes it into Elsa diagnostics read models, redacts sensitive values before provider boundaries, stores recent telemetry in bounded memory, exposes authenticated REST APIs and SignalR live updates for Studio, and publishes collector configuration metadata for standard OTEL senders. + +The module is a collector/API backend, not producer-side workflow tracing middleware. Existing `Elsa.Workflows.Core` `ActivitySource` and `Meter` instrumentation remains the workflow telemetry producer. The historical `Elsa.OpenTelemetry` module from `elsa-extensions` is not ported in v1. + +## Technical Context + +**Language/Version**: C# latest, nullable reference types enabled, implicit usings enabled. +**Primary Dependencies**: OpenTelemetry SDK/proto contracts, ASP.NET Core endpoint patterns, optional gRPC services, SignalR, Elsa feature/module infrastructure, FastEndpoints through Elsa API endpoint patterns, Elsa shell feature infrastructure, existing Elsa identity/authorization patterns, current `Elsa.Workflows.Core` instrumentation. +**Storage**: Bounded in-memory telemetry repository for resources, traces, spans, metric instruments/points, OTLP log records, live subscribers, and dropped-count diagnostics. Defaults are configurable, drop oldest per signal on overflow, and start with at least 500 resources, 2,000 traces, 10,000 spans, 20,000 metric points, 10,000 OTLP log records, and 1,000 queued live updates per subscriber. No durable database schema in v1. +**Testing**: xUnit unit tests for normalization, redaction, resource identity, filtering, bounded storage, dropped counts, and collector configuration; integration tests for HTTP/protobuf OTLP ingestion, optional gRPC ingestion when enabled, permissions, SignalR, API contracts, and workflow export-to-collector timing. +**Target Platform**: ASP.NET Core Elsa Server on supported repository target frameworks. +**Project Type**: Modular .NET library inside the existing Elsa solution. +**Performance Goals**: Local workflow telemetry appears through diagnostics APIs within 2 seconds; trace detail handles 100 spans; metrics handle 20 instruments and 1,000 recent points; backend buffers remain bounded under overload. +**Constraints**: Do not merge with Structured Logs or Console Logs. Do not port historical producer middleware. Do not start workflow/activity spans in the diagnostics module or mutate `Activity.Current`. Do not add durable OTEL persistence, vendor exporters, Kubernetes/Docker APIs, or Studio UI in Core. Non-loopback OTLP ingestion requires explicit protection. +**Scale/Scope**: One Core module, unit/integration tests, docs/wiki quickstart updates, API/hub contracts, and sample host wiring if needed for verification. + +## Constitution Check + +Evaluated against `.specify/memory/constitution.md` v1.1.0: + +| Principle | Verdict | Evidence | +|-----------|---------|----------| +| I. Modular Architecture | PASS | Work is a focused module under `src/modules/Elsa.Diagnostics.OpenTelemetry` with contracts, services, endpoints, hub, options, permissions, and shell feature. | +| II. Composition & Extensibility | PASS | Ingestion, redaction, store, live feed, source registry, and collector configuration are explicit contracts/services. | +| III. Convention-Driven Design | PASS | Names follow Elsa module, endpoint, feature, permission, and test conventions with American English. | +| IV. Async & Pipeline Execution | PASS | Ingestion, provider queries, endpoints, live subscriptions, and shutdown paths are async/cancellation-aware. | +| V. Testing Discipline | PASS | Plan requires unit/integration coverage for ingestion, security, storage, API, SignalR, and workflow telemetry timing. | +| VI. Trunk-Based Development | PASS | Core backend module can land independently from Studio after API contracts stabilize. | +| VII. Simplicity, SRP, DRY & KISS | PASS | V1 uses bounded in-memory storage and excludes durable storage, vendor exporters, app launcher behavior, and producer middleware changes. | + +## Project Structure + +### Documentation (this feature) + +```text +specs/008-diagnostics-otel/ +├── spec.md +├── plan.md +├── research.md +├── data-model.md +├── quickstart.md +├── contracts/ +│ ├── rest-api.md +│ ├── otlp-ingest.md +│ ├── signalr-hub.md +│ └── provider-contract.md +├── checklists/ +│ └── requirements.md +└── tasks.md +``` + +### Source Code (repository root) + +```text +src/modules/ +└── Elsa.Diagnostics.OpenTelemetry/ + ├── Contracts/ + │ ├── IOpenTelemetryIngestor.cs + │ ├── IOpenTelemetryProvider.cs + │ ├── IOpenTelemetryRedactor.cs + │ ├── IOpenTelemetrySourceRegistry.cs + │ ├── IOpenTelemetryStore.cs + │ └── IOpenTelemetryLiveFeed.cs + ├── Endpoints/OpenTelemetry/ + │ ├── CollectorConfiguration/Endpoint.cs + │ ├── Logs/Endpoint.cs + │ ├── Metrics/Endpoint.cs + │ ├── Resources/Endpoint.cs + │ ├── Storage/Endpoint.cs + │ ├── Trace/Endpoint.cs + │ └── Traces/Endpoint.cs + ├── Extensions/ + ├── Features/OpenTelemetryFeature.cs + ├── Ingestion/ + │ ├── Grpc/ + │ └── HttpProtobuf/ + ├── Models/ + ├── Options/OpenTelemetryDiagnosticsOptions.cs + ├── Permissions/OpenTelemetryPermissions.cs + ├── Providers/InMemory/ + ├── RealTime/OpenTelemetryHub.cs + ├── Services/ + └── ShellFeatures/OpenTelemetryFeature.cs + +test/unit/ +└── Elsa.Diagnostics.OpenTelemetry.UnitTests/ + +test/integration/ +└── Elsa.Diagnostics.OpenTelemetry.IntegrationTests/ +``` + +**Structure Decision**: Add a new diagnostics module parallel to `Elsa.Diagnostics.StructuredLogs` and `Elsa.Diagnostics.ConsoleLogs`. The module owns collector, normalization, storage, APIs, and live contracts only. + +## Phase 0 Output + +See [research.md](./research.md). + +Resolved decisions: + +- Core module is the OTLP collector and diagnostics API boundary. +- Existing `Elsa.Workflows.Core` instrumentation remains the producer. +- Do not port historical `Elsa.OpenTelemetry` producer middleware from `elsa-extensions`. +- Support HTTP/protobuf as required; support gRPC when host/dependencies enable it and advertise disabled metadata otherwise. +- Use bounded in-memory storage in v1. +- Keep OTLP logs separate from `Elsa.Diagnostics.StructuredLogs`. +- Require protection for non-loopback ingestion. + +## Phase 1 Output + +- [data-model.md](./data-model.md) +- [contracts/rest-api.md](./contracts/rest-api.md) +- [contracts/otlp-ingest.md](./contracts/otlp-ingest.md) +- [contracts/signalr-hub.md](./contracts/signalr-hub.md) +- [contracts/provider-contract.md](./contracts/provider-contract.md) +- [quickstart.md](./quickstart.md) + +## Post-Design Constitution Re-Check + +| Principle | Verdict | Post-design evidence | +|-----------|---------|----------------------| +| I. Modular Architecture | PASS | Contracts and source tree keep all Core OpenTelemetry diagnostics behavior in one focused module. | +| II. Composition & Extensibility | PASS | Provider/store/live-feed/redactor/ingestor contracts isolate real variability points. | +| III. Convention-Driven Design | PASS | Endpoint and type names follow diagnostics module conventions. | +| IV. Async & Pipeline Execution | PASS | Provider, store, endpoint, and hub contracts are async/cancellation-aware. | +| V. Testing Discipline | PASS | Tasks include unit and integration tests for each buildable slice. | +| VI. Trunk-Based Development | PASS | Core slice remains independently reviewable from Studio. | +| VII. Simplicity, SRP, DRY & KISS | PASS | V1 avoids persistence and producer instrumentation rewrites. | + +## Phase 2 Handoff + +Use [tasks.md](./tasks.md) as the implementation backlog. Suggested order: + +1. Create module/test projects, solution entries, options, permissions, feature, and shell feature. +2. Add models and shared provider contracts. +3. Add HTTP/protobuf ingestion, normalization, redaction, resource registry, bounded store, and provider facade. +4. Add REST APIs, SignalR hub, collector configuration, and security checks. +5. Add optional gRPC wrappers and disabled metadata handling. +6. Add docs, sample host wiring if needed, and run targeted tests/builds. + +## Complexity Tracking + +No constitution violations identified. diff --git a/specs/008-diagnostics-otel/quickstart.md b/specs/008-diagnostics-otel/quickstart.md new file mode 100644 index 000000000..11ab69d79 --- /dev/null +++ b/specs/008-diagnostics-otel/quickstart.md @@ -0,0 +1,72 @@ +# Quickstart: Diagnostics OpenTelemetry + +## Enable Core Diagnostics + +```csharp +services.AddElsa(elsa => +{ + elsa.UseOpenTelemetryDiagnostics(options => + { + options.HttpEndpointPath = "/elsa/otlp/v1"; + options.ApiKey = builder.Configuration["Diagnostics:OpenTelemetry:ApiKey"]; + options.TraceCapacity = 2_000; + options.SpanCapacity = 10_000; + options.MetricPointCapacity = 20_000; + options.LogRecordCapacity = 10_000; + options.ResourceCapacity = 500; + options.SubscriberChannelCapacity = 1_000; + options.MaxHttpRequestBodySize = 10 * 1024 * 1024; + }); +}); +``` + +## Configure Elsa Workflow Telemetry Export + +```csharp +services.AddOpenTelemetry() + .WithTracing(builder => builder + .AddSource("Elsa.Workflows") + .AddOtlpExporter()) + .WithMetrics(builder => builder + .AddMeter("Elsa.Workflows") + .AddOtlpExporter()); +``` + +Development HTTP/protobuf environment: + +```text +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5000/elsa/otlp/v1 +OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf +OTEL_SERVICE_NAME=elsa-api +OTEL_RESOURCE_ATTRIBUTES=service.instance.id=local-elsa-api,deployment.environment=development +OTEL_BSP_SCHEDULE_DELAY=1000 +OTEL_BLRP_SCHEDULE_DELAY=1000 +OTEL_METRIC_EXPORT_INTERVAL=1000 +``` + +When the collector is reachable from non-loopback addresses, configure the server-side API key and send only the configured header name/value through OTLP exporter headers. Collector configuration must advertise required header names but never secret values. + +gRPC senders should only use gRPC when collector configuration advertises a gRPC endpoint: + +```text +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +OTEL_EXPORTER_OTLP_PROTOCOL=grpc +``` + +## Verify + +```bash +dotnet test test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj +dotnet test test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj +``` + +Manual checks: + +- Run a workflow and confirm a workflow trace appears through `/diagnostics/opentelemetry/traces/search` within 2 seconds. +- Query `/diagnostics/opentelemetry/traces/{traceId}` and confirm workflow/activity spans are parented and ordered. +- Query collector configuration and confirm HTTP metadata, nullable/disabled gRPC metadata, and required header names. +- Attempt non-loopback ingestion without the configured API key and confirm rejection. + +## Scope Boundaries + +This feature does not add durable OTEL persistence, vendor exporters, Studio UI, alerting, Kubernetes/Docker APIs, or historical `Elsa.OpenTelemetry` producer middleware. Production deployments should usually export to a standard OpenTelemetry Collector or observability platform unless Elsa collector capacity and security are deliberately configured. diff --git a/specs/008-diagnostics-otel/research.md b/specs/008-diagnostics-otel/research.md new file mode 100644 index 000000000..40d3ebb0e --- /dev/null +++ b/specs/008-diagnostics-otel/research.md @@ -0,0 +1,54 @@ +# Research: Diagnostics OpenTelemetry + +## Decision: Core owns the collector/API boundary + +**Rationale**: OTLP ingestion must happen in an ASP.NET Core backend, not in Studio. Core can authenticate diagnostics APIs, protect ingestion, normalize protobuf payloads, and stream live updates. + +**Alternatives considered**: + +- Studio collector: rejected because browser/Studio hosts cannot reliably expose OTLP endpoints. +- External collector only: rejected because this feature needs a first-party local diagnostics story. + +## Decision: Preserve existing workflow instrumentation + +**Rationale**: Current `Elsa.Workflows.Core` already emits `Elsa.Workflows` spans and metrics through `System.Diagnostics`. This module should consume/export that telemetry through OTLP rather than re-instrument workflow execution. + +**Alternatives considered**: + +- Port `elsa-extensions` `Elsa.OpenTelemetry`: rejected because it is producer-side middleware, overlaps current Core instrumentation, and includes trace-boundary behavior that mutates ambient `Activity.Current`. +- Move instrumentation into diagnostics: rejected because workflow instrumentation is valuable even when diagnostics collector is not installed. + +## Decision: HTTP/protobuf required, gRPC optional + +**Rationale**: HTTP/protobuf fits existing ASP.NET Core endpoint patterns and common deployment routes. gRPC is useful for SDK defaults but depends on host configuration and package choices, so it should be enabled when available and represented honestly in collector metadata. + +**Alternatives considered**: + +- gRPC only: rejected because it complicates proxying and local HTTP testing. +- Always return a gRPC endpoint: rejected because it misleads clients when the host does not expose gRPC. + +## Decision: Bounded in-memory v1 storage + +**Rationale**: Traces, metrics, and logs can be high volume. A bounded in-memory default matches the existing diagnostics modules and keeps v1 focused. + +**Alternatives considered**: + +- Durable storage now: rejected because trace and metric schemas need a deliberate follow-up provider design. +- Raw OTLP payload storage only: rejected because diagnostics clients need filtered, assembled trace and metric models. + +## Decision: OTLP logs stay separate from Structured Logs + +**Rationale**: OTLP logs can come from arbitrary resources and use OTEL schemas. `Elsa.Diagnostics.StructuredLogs` owns first-party `ILogger` capture. Correlation should use trace/span IDs, not shared storage. + +**Alternatives considered**: + +- Merge OTLP logs into Structured Logs: rejected because schemas, retention, permissions, and source semantics differ. + +## Decision: Explicit non-loopback protection + +**Rationale**: OTLP ingestion can expose sensitive application metadata and create high traffic. Loopback development can be low friction, but remote ingestion needs an API key header or equivalent configured protection. + +**Alternatives considered**: + +- No OTLP sender auth: rejected as unsafe. +- Require interactive user auth for OTLP senders: rejected because SDKs usually support headers, not browser auth. diff --git a/specs/008-diagnostics-otel/spec.md b/specs/008-diagnostics-otel/spec.md new file mode 100644 index 000000000..2c662a5ce --- /dev/null +++ b/specs/008-diagnostics-otel/spec.md @@ -0,0 +1,158 @@ +# Feature Specification: Diagnostics OpenTelemetry + +**Feature Branch**: `008-diagnostics-otel` +**Created**: 2026-05-25 +**Status**: Draft +**Input**: Core-owned specification for the backend side of the OpenTelemetry diagnostics PRD coordinated with `elsa-studio/specs/008-diagnostics-otel`. + +## Clarifications + +### Session 2026-05-25 + +- Q: What default capacity and overflow policy should the Core in-memory OTEL store use? -> A: Configurable bounded defaults with drop-oldest per signal. +- Q: How should Core decide when OTLP ingestion requires an API key? -> A: Require the configured header for any non-loopback request or non-loopback collector binding. +- Q: How should live SignalR subscriptions behave under backpressure? -> A: Use bounded per-connection queues, drop oldest updates, and report dropped counts. +- Q: Which workflow attributes are canonical for Elsa trace correlation? -> A: Preserve existing `Elsa.Workflows` semantic tags; do not add producer middleware or mutate ambient activity context. + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Collect OpenTelemetry from Elsa services (Priority: P1) + +An operator enables OpenTelemetry diagnostics on an Elsa backend and receives workflow traces, activity spans, metrics, resources, and correlated OTLP logs through a first-party diagnostics backend. + +**Why this priority**: Studio cannot visualize telemetry until Core can collect, normalize, secure, and expose it. + +**Independent Test**: Enable the Core OpenTelemetry diagnostics feature, run a workflow with multiple activities, export telemetry to the local diagnostics collector, and verify recent resources, traces, spans, metrics, and logs through backend diagnostics APIs. + +**Acceptance Scenarios**: + +1. **Given** the diagnostics OpenTelemetry feature is enabled, **When** workflow execution emits spans and metrics from `Elsa.Workflows`, **Then** Core stores recent telemetry with resource identity, trace/span IDs, timing, status, and workflow metadata. +2. **Given** a standard OpenTelemetry SDK posts OTLP traces, metrics, or logs to the HTTP/protobuf collector endpoint, **When** the payload is accepted, **Then** Core normalizes the telemetry into queryable diagnostics models. +3. **Given** telemetry contains sensitive attributes matching configured redaction rules, **When** Core stores or streams it, **Then** sensitive values are redacted before provider boundaries. + +--- + +### User Story 2 - Serve Trace Investigation APIs (Priority: P1) + +Studio and other authenticated diagnostics clients can query recent traces and retrieve a trace detail model with ordered spans, resource metadata, OTLP logs, and storage diagnostics. + +**Why this priority**: Trace investigation is the main workflow troubleshooting path and must be backend-filtered before Studio renders a waterfall. + +**Independent Test**: Seed or ingest telemetry for a workflow trace and call the trace search/detail APIs with filters for service, resource, trace ID, workflow instance ID, status, text, and time range. + +**Acceptance Scenarios**: + +1. **Given** a trace contains workflow and activity spans, **When** a diagnostics client requests trace detail, **Then** Core returns parent/child span data ordered for a waterfall view. +2. **Given** filters include workflow instance ID or trace ID, **When** trace search is executed, **Then** only matching trace summaries are returned. +3. **Given** the caller lacks the OpenTelemetry diagnostics view permission, **When** the caller requests trace APIs or live updates, **Then** Core denies the request without exposing telemetry. + +--- + +### User Story 3 - Serve Metrics and OTLP Logs (Priority: P2) + +An authenticated diagnostics client can inspect recent OpenTelemetry metric instruments, bounded metric points, OTLP log records, and overflow diagnostics. + +**Why this priority**: Metrics and OTLP logs complement traces and validate that all OpenTelemetry signals are flowing. + +**Independent Test**: Ingest metrics and OTLP logs for multiple resources, query them by resource, instrument, severity, trace/span ID, text, and time range, and verify capacity diagnostics. + +**Acceptance Scenarios**: + +1. **Given** metrics are emitted by multiple services, **When** a client filters by resource or instrument, **Then** Core returns only matching bounded series. +2. **Given** a metric has high-cardinality attributes, **When** capacity is exceeded, **Then** Core drops according to configured policy and reports dropped point counts. +3. **Given** OTLP logs include trace/span IDs, **When** logs are queried by trace/span, **Then** Core returns correlated OTLP log records without merging them into `Elsa.Diagnostics.StructuredLogs`. + +--- + +### User Story 4 - Expose Collector Configuration and Secure Ingestion (Priority: P3) + +A developer can discover active collector endpoints and configure .NET or non-.NET senders using standard OTEL environment variables, while Core protects non-loopback ingestion. + +**Why this priority**: Elsa does not own an Aspire-style launcher, so Core must make active collector configuration discoverable and secure. + +**Independent Test**: Request collector configuration, verify HTTP metadata and nullable/disabled gRPC metadata, configure a sample sender, and verify non-loopback ingestion requires the configured API key header. + +**Acceptance Scenarios**: + +1. **Given** the collector is enabled, **When** a diagnostics client requests collector configuration, **Then** Core returns HTTP endpoint metadata, any enabled gRPC endpoint metadata, required header names, and recommended non-secret environment variables. +2. **Given** gRPC ingestion is unavailable, **When** configuration is requested, **Then** Core marks gRPC disabled instead of returning a misleading endpoint. +3. **Given** OTLP ingestion is exposed beyond loopback, **When** a sender omits the required API key header, **Then** Core rejects the request. + +### Edge Cases + +- OTLP payloads include unsupported future fields or incomplete resource attributes. +- Multiple services share `service.name` but have different `service.instance.id` values. +- A trace arrives out of span order. +- Metrics create more series or points than configured capacity allows. +- Backend restarts and loses in-memory telemetry. +- OTLP logs reference trace/span IDs for traces that have expired. +- gRPC support is not available in the hosting configuration. +- The caller has Studio access but not the OpenTelemetry diagnostics permission. +- A sender posts from loopback while the collector is configured for loopback-only development. +- A sender posts from a non-loopback address without the configured ingestion API key header. +- A live client subscribes with filters that receive more updates than its per-connection queue allows. +- The historical `Elsa.OpenTelemetry` extension package is present in another repository but must not be ported into this module. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: Core MUST introduce an opt-in module under `src/modules/Elsa.Diagnostics.OpenTelemetry`. +- **FR-002**: The module MUST be separate from `Elsa.Diagnostics.StructuredLogs` and `Elsa.Diagnostics.ConsoleLogs`. +- **FR-003**: The module MUST use existing `Elsa.Workflows` `ActivitySource` and `Meter` instrumentation as the producer of Elsa workflow telemetry. +- **FR-004**: The module MUST NOT port the historical `Elsa.OpenTelemetry` producer-side middleware from `elsa-extensions` in v1. +- **FR-005**: The module MUST accept OTLP HTTP/protobuf traces, metrics, and logs. +- **FR-006**: The module SHOULD support OTLP gRPC ingestion when the host has gRPC support enabled; collector metadata MUST represent gRPC as disabled or null when unavailable. +- **FR-007**: HTTP and gRPC ingestion, when both are enabled, MUST feed one shared ingestion contract for normalization, redaction, storage, and live publishing. +- **FR-008**: The module MUST normalize telemetry into bounded queryable models for resources, traces, spans, metrics, and OTLP log records. +- **FR-009**: The default store MUST be bounded in memory and MUST report dropped telemetry counts. +- **FR-010**: Redaction MUST run before telemetry reaches provider storage or live subscribers. +- **FR-011**: Resource identity MUST use OpenTelemetry resource attributes, including service name and service instance ID when present. +- **FR-012**: Workflow and activity telemetry MUST preserve the existing `Elsa.Workflows` semantic attributes when present, including `workflow.instance.id`, `workflow.definition.id`, `workflow.definition.version`, `workflow.definition.version.id`, `workflow.status`, `workflow.substatus`, `workflow.faulted`, `workflow.parent.instance.id`, `workflow.correlation.id`, `workflow.activity.id`, `workflow.activity.name`, `workflow.activity.type`, `workflow.activity.version`, `workflow.activity.execution.id`, `workflow.activity.status`, `workflow.activity.outcome`, `workflow.activity.parent.execution.id`, `workflow.activity.scheduled.by.execution.id`, `workflow.activity.faulted`, `elsa.tenant.id`, and `exception.type`. +- **FR-013**: The module MUST expose authenticated diagnostics APIs for resources, trace search, trace detail, metrics, OTLP logs, storage diagnostics, and collector configuration. +- **FR-014**: The module MUST expose live updates through an authenticated SignalR hub. +- **FR-015**: The module MUST enforce an OpenTelemetry diagnostics view permission for all diagnostics APIs and live connections. +- **FR-016**: Loopback-only development ingestion MAY run without an API key only for loopback requests while the collector is bound to loopback; any non-loopback request or non-loopback collector binding MUST require an explicit API key header or equivalent configured protection. +- **FR-017**: Collector configuration MUST expose standard OTEL environment variable metadata without exposing secret values. +- **FR-018**: The module MUST document that production deployments should generally export to an external OpenTelemetry Collector or observability backend unless Elsa collector capacity and security are deliberately configured. +- **FR-019**: OTLP logs MUST remain separate from `Elsa.Diagnostics.StructuredLogs`; correlation uses trace/span IDs rather than shared storage. +- **FR-020**: The module MUST include tests for ingestion, normalization, redaction, bounded storage, permissions, live updates, collector configuration, and end-to-end workflow export-to-collector timing. +- **FR-021**: In-memory storage defaults MUST be configurable and MUST start with bounded development defaults of at least 500 resources, 2,000 traces, 10,000 spans, 20,000 metric points, 10,000 OTLP log records, and 1,000 queued live updates per subscriber; when a capacity is exceeded, the oldest item in that signal-specific buffer is dropped and the relevant dropped count is incremented. +- **FR-022**: Search APIs MUST return deterministic, bounded result sets with caller-specified limits capped by server options; default ordering is newest receive time first for searches and parent/child chronological ordering for trace detail spans. +- **FR-023**: Live SignalR subscriptions MUST use bounded per-connection queues, update filters in place, drop oldest queued updates on overflow, and publish dropped-update diagnostics without disconnecting healthy subscribers. +- **FR-024**: The diagnostics module MUST NOT start new workflow or activity spans itself and MUST NOT mutate `Activity.Current`; trace production remains owned by existing `Elsa.Workflows.Core` instrumentation. + +### Key Entities + +- **Telemetry Resource**: Resource/service identity derived from OTEL resource attributes. +- **Telemetry Trace**: Trace summary grouped by trace ID. +- **Telemetry Span**: Timed operation inside a trace with attributes, events, links, and status. +- **Metric Instrument**: Metric name, unit, description, type, resource, and bounded series. +- **Metric Point**: Recent data point for a metric series. +- **OTLP Log Record**: Log record received through OTLP and correlated by trace/span IDs. +- **Collector Configuration**: Active endpoint, protocol, security, and environment-variable metadata. +- **Storage Diagnostics**: Capacity and dropped telemetry counters. +- **Telemetry Subscription**: Live SignalR subscription with filters and connection state. +- **Storage Capacity Policy**: Configurable per-signal limits and drop-oldest overflow behavior for in-memory telemetry. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: A local Core host with OpenTelemetry diagnostics enabled receives workflow trace spans and exposes them through diagnostics APIs within 2 seconds of workflow execution. +- **SC-002**: Core accepts representative OTLP HTTP/protobuf traces, metrics, and logs from standard SDK payloads and returns normalized diagnostics models. +- **SC-003**: Trace detail APIs return at least 100 ordered spans for one trace without unbounded memory growth. +- **SC-004**: Metric APIs return at least 20 instruments and 1,000 recent points while honoring configured capacity. +- **SC-005**: Unauthorized API and hub calls are denied without exposing telemetry. +- **SC-006**: Sensitive configured attribute names and text patterns are redacted before stored telemetry is returned. +- **SC-007**: Collector configuration reports HTTP metadata, nullable/disabled gRPC metadata, and required header names accurately. +- **SC-008**: Capacity tests prove each signal-specific buffer drops oldest telemetry, increments dropped counts, and keeps queries bounded when defaults are exceeded. +- **SC-009**: SignalR tests prove subscriber overflow drops oldest queued live updates, reports dropped-update counts, and keeps the connection usable. + +## Assumptions + +- `Elsa.Workflows.Core` keeps first-party workflow tracing and metrics instrumentation. +- Durable OpenTelemetry persistence is a later provider feature. +- The Studio feature has its own spec in `elsa-studio/specs/008-diagnostics-otel`. +- Core and Studio contracts should remain aligned, but Core is the source of truth for ingestion, permissions, normalization, and API behavior. +- Default in-memory capacities are development-friendly starting points, not production sizing guidance. diff --git a/specs/008-diagnostics-otel/tasks.md b/specs/008-diagnostics-otel/tasks.md new file mode 100644 index 000000000..ca6f798c0 --- /dev/null +++ b/specs/008-diagnostics-otel/tasks.md @@ -0,0 +1,123 @@ +# Tasks: Diagnostics OpenTelemetry + +**Input**: Design documents from `/specs/008-diagnostics-otel/` +**Prerequisites**: [plan.md](./plan.md), [spec.md](./spec.md), [research.md](./research.md), [data-model.md](./data-model.md), [contracts/](./contracts/), [quickstart.md](./quickstart.md) + +**Tests**: Required for ingestion, normalization, redaction, bounded storage, permissions, live updates, collector configuration, and workflow export-to-collector timing. + +## Phase 1: Setup + +- [X] T001 Create Core project skeleton at `src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj` +- [X] T002 Create unit test project at `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj` +- [X] T003 Create integration test project at `test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj` +- [X] T004 Add project and test projects to `Elsa.sln` +- [X] T005 [P] Add initial module README at `src/modules/Elsa.Diagnostics.OpenTelemetry/README.md` + +--- + +## Phase 2: Foundational + +- [X] T006 Create telemetry resource/span/trace/metric/log/storage models in `src/modules/Elsa.Diagnostics.OpenTelemetry/Models` +- [X] T007 Create filter/result DTOs for resources, traces, metrics, logs, and collector configuration in `src/modules/Elsa.Diagnostics.OpenTelemetry/Models` +- [X] T008 Create provider, store, live feed, ingestor, redactor, and source registry contracts in `src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts` +- [X] T009 Create options in `src/modules/Elsa.Diagnostics.OpenTelemetry/Options/OpenTelemetryDiagnosticsOptions.cs` with configurable capacity defaults, ingestion security, and live subscriber queue settings +- [X] T010 Create permission constants in `src/modules/Elsa.Diagnostics.OpenTelemetry/Permissions/OpenTelemetryPermissions.cs` +- [X] T011 Create feature and shell feature in `src/modules/Elsa.Diagnostics.OpenTelemetry/Features/OpenTelemetryFeature.cs` and `src/modules/Elsa.Diagnostics.OpenTelemetry/ShellFeatures/OpenTelemetryFeature.cs` +- [X] T012 Create DI and endpoint mapping extensions in `src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions` +- [X] T013 Add README note that historical `Elsa.OpenTelemetry` producer middleware is not ported in v1 in `src/modules/Elsa.Diagnostics.OpenTelemetry/README.md` + +--- + +## Phase 3: User Story 1 - Collect OpenTelemetry from Elsa services (Priority: P1) MVP + +**Goal**: Receive OTLP payloads, normalize, redact, store bounded telemetry, and expose basic diagnostics queries. + +**Independent Test**: Ingest OTLP traces/metrics/logs and run an Elsa workflow export-to-collector integration test. + +- [X] T014 [P] [US1] Add OTLP trace normalization tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpTraceNormalizerTests.cs` +- [X] T015 [P] [US1] Add OTLP metric normalization tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpMetricNormalizerTests.cs` +- [X] T016 [P] [US1] Add OTLP log normalization tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpLogNormalizerTests.cs` +- [X] T017 [P] [US1] Add redaction tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/OpenTelemetryRedactorTests.cs` +- [X] T018 [P] [US1] Add bounded store/drop-count tests for default capacities, drop-oldest overflow, and deterministic query limits in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/InMemoryOpenTelemetryStoreTests.cs` +- [X] T019 [P] [US1] Add HTTP/protobuf ingestion and workflow export-to-collector timing tests that assert existing `Elsa.Workflows` tags are preserved in `test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpHttpIngestionTests.cs` +- [X] T020 [US1] Implement HTTP/protobuf request parsing in `src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/HttpProtobuf` +- [X] T021 [US1] Implement shared OTLP normalization services in `src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion` +- [X] T022 [US1] Implement redactor in `src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryRedactor.cs` +- [X] T023 [US1] Implement source registry in `src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetrySourceRegistry.cs` +- [X] T024 [US1] Implement bounded in-memory store in `src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs` +- [X] T025 [US1] Implement provider facade in `src/modules/Elsa.Diagnostics.OpenTelemetry/Services/DefaultOpenTelemetryProvider.cs` +- [X] T026 [US1] Implement HTTP/protobuf endpoint mapping in `src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/EndpointRouteBuilderExtensions.cs` + +--- + +## Phase 4: User Story 2 - Serve Trace Investigation APIs (Priority: P1) + +**Goal**: Provide authenticated trace search/detail APIs and live updates. + +**Independent Test**: Query traces by service/resource/trace/workflow/status/time and retrieve ordered span detail. + +- [X] T027 [P] [US2] Add trace search/detail provider tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryTraceQueryTests.cs` +- [X] T028 [P] [US2] Add API authorization tests in `test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryAuthorizationTests.cs` +- [X] T029 [P] [US2] Add SignalR hub tests for authorization, filter updates, per-subscriber queue overflow, drop-oldest behavior, and dropped-update diagnostics in `test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs` +- [X] T030 [US2] Implement trace search and trace detail query logic in `src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs` +- [X] T031 [US2] Implement resource search endpoint in `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Resources/Endpoint.cs` +- [X] T032 [US2] Implement trace search and detail endpoints in `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Traces/Endpoint.cs` and `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Trace/Endpoint.cs` +- [X] T033 [US2] Implement live feed in `src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs` +- [X] T034 [US2] Implement SignalR hub in `src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetryHub.cs` + +--- + +## Phase 5: User Story 3 - Serve Metrics and OTLP Logs (Priority: P2) + +**Goal**: Provide bounded metric and OTLP log search APIs with overflow diagnostics. + +**Independent Test**: Ingest metrics/logs, query by filters, and verify dropped counts. + +- [X] T035 [P] [US3] Add metric query tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryMetricQueryTests.cs` +- [X] T036 [P] [US3] Add OTLP log query tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OtlpLogQueryTests.cs` +- [X] T037 [US3] Implement metric instrument and point query support in `src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs` +- [X] T038 [US3] Implement OTLP log query support in `src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs` +- [X] T039 [US3] Implement metrics endpoint in `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Metrics/Endpoint.cs` +- [X] T040 [US3] Implement OTLP logs endpoint in `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Logs/Endpoint.cs` +- [X] T041 [US3] Implement storage diagnostics endpoint in `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Storage/Endpoint.cs` + +--- + +## Phase 6: User Story 4 - Expose Collector Configuration and Secure Ingestion (Priority: P3) + +**Goal**: Provide collector configuration metadata and protect non-loopback ingestion. + +**Independent Test**: Query configuration and verify API key enforcement. + +- [X] T042 [P] [US4] Add collector configuration tests in `test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/CollectorConfigurationTests.cs` +- [X] T043 [P] [US4] Add ingestion security tests for loopback-only no-key development, non-loopback request rejection without API key, and non-secret collector metadata in `test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpIngestionSecurityTests.cs` +- [X] T044 [US4] Implement collector configuration provider in `src/modules/Elsa.Diagnostics.OpenTelemetry/Services/CollectorConfigurationProvider.cs` +- [X] T045 [US4] Implement collector configuration endpoint in `src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/CollectorConfiguration/Endpoint.cs` +- [X] T046 [US4] Implement API key header validation in `src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion` +- [X] T047 [US4] Add option-gated gRPC wrappers and disabled metadata handling in `src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/Grpc` +- [X] T048 [US4] Update workflow OpenTelemetry docs in `doc/wiki/opentelemetry-workflows.md` + +--- + +## Phase 7: Polish and Verification + +- [X] T049 [P] Update module README with routes, permissions, security, scope boundaries, and historical extension decision in `src/modules/Elsa.Diagnostics.OpenTelemetry/README.md` +- [X] T050 [P] Verify no production code references historical producer middleware by running `rg "Elsa.OpenTelemetry|UseWorkflowExecutionTracing|UseActivityExecutionTracing" src test` +- [X] T051 Run `dotnet test test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj` +- [X] T052 Run `dotnet test test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj` +- [X] T053 Run `dotnet build Elsa.sln` + +## Dependencies + +- Phase 1 precedes all work. +- Phase 2 blocks all user stories. +- US1 is the MVP backend collector slice. +- US2 can begin after Phase 2 with seeded store data; full validation depends on US1. +- US3 depends on US1 storage and normalization. +- US4 depends on endpoint mapping from US1. + +## Notes + +- Keep Studio UI tasks in `elsa-studio/specs/008-diagnostics-otel/tasks.md`. +- Do not port historical `Elsa.OpenTelemetry` middleware in this feature. +- Durable OTEL persistence and vendor exporters are out of scope. diff --git a/src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj b/src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj index ae9991352..cbb44d3ba 100644 --- a/src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj +++ b/src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj @@ -5,9 +5,14 @@ + + + + + diff --git a/src/apps/Elsa.ModularServer.Web/Program.cs b/src/apps/Elsa.ModularServer.Web/Program.cs index 981f34116..3a5624e39 100644 --- a/src/apps/Elsa.ModularServer.Web/Program.cs +++ b/src/apps/Elsa.ModularServer.Web/Program.cs @@ -2,8 +2,6 @@ using ConsoleLogStreaming.Core.Capture; using CShells.AspNetCore.Configuration; using CShells.AspNetCore.Extensions; using CShells.DependencyInjection; -using Elsa.Diagnostics.ConsoleLogs.Extensions; -using Elsa.Diagnostics.ConsoleLogs.Services; using Elsa.ModularServer.Web; using Elsa.ModularServer.Web.Catalog; using Elsa.ShellFeatures; @@ -12,22 +10,44 @@ using Elsa.Workflows.Management.ShellFeatures; using Elsa.Workflows.Runtime.Distributed.ShellFeatures; using Elsa.Workflows.Runtime.ShellFeatures; using Elsa.Workflows.ShellFeatures; +using Elsa.Workflows.Telemetry; using Nuplane; using Nuplane.Loading.Hosting.Builder; using Nuplane.Sources.Directory.Configuration; +using OpenTelemetry.Exporter; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; -// Install the console stream tee as early as possible — before WebApplication.CreateBuilder and -// any logger provider construction — so that downstream loggers (Microsoft.Extensions.Logging.Console, -// Kestrel/Hosting loggers, etc.) capture our tee writer instead of the raw Console.Out / Console.Error. ConsoleStreamHook.Install(); var builder = WebApplication.CreateBuilder(args); var services = builder.Services; var configuration = builder.Configuration; +var serviceVersion = typeof(Program).Assembly.GetName().Version?.ToString(); -// Console output is a single process-wide resource; the capture pipeline is owned by the root host so -// every shell's diagnostics endpoints (REST + SignalR) read from the same in-memory ring buffer. -services.AddConsoleLogsHost(); +builder.Logging.AddOpenTelemetry(logging => +{ + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + logging.ParseStateValues = true; + logging.SetResourceBuilder(CreateOpenTelemetryResource(builder.Environment.ApplicationName, serviceVersion)); + logging.AddOtlpExporter(options => ConfigureDiagnosticsOtlpExporter(options, configuration, "logs")); +}); + +services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService(builder.Environment.ApplicationName, serviceVersion: serviceVersion)) + .WithTracing(tracing => tracing + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddSource(WorkflowInstrumentation.ActivitySourceName) + .AddOtlpExporter(options => ConfigureDiagnosticsOtlpExporter(options, configuration, "traces"))) + .WithMetrics(metrics => metrics + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddMeter(WorkflowInstrumentation.MeterName) + .AddOtlpExporter(options => ConfigureDiagnosticsOtlpExporter(options, configuration, "metrics"))); var nuplaneConfiguration = configuration.GetSection("Nuplane"); @@ -71,3 +91,39 @@ app.UseAuthentication(); app.UseAuthorization(); app.MapSampleCatalog(); app.Run(); + +static ResourceBuilder CreateOpenTelemetryResource(string serviceName, string? serviceVersion) +{ + return ResourceBuilder.CreateDefault().AddService(serviceName, serviceVersion: serviceVersion); +} + +static void ConfigureDiagnosticsOtlpExporter(OtlpExporterOptions options, IConfiguration configuration, string signal) +{ + var protocol = configuration["Diagnostics:OpenTelemetry:Exporter:Protocol"]; + options.Protocol = protocol?.Trim().ToLowerInvariant() switch + { + "grpc" => OtlpExportProtocol.Grpc, + "http/protobuf" or "httpprotobuf" => OtlpExportProtocol.HttpProtobuf, + _ => options.Protocol + }; + + var endpoint = configuration["Diagnostics:OpenTelemetry:Exporter:Endpoint"]; + if (!string.IsNullOrWhiteSpace(endpoint)) + options.Endpoint = new Uri(GetSignalEndpoint(endpoint, signal, options.Protocol), UriKind.Absolute); +} + +static string GetSignalEndpoint(string endpoint, string signal, OtlpExportProtocol protocol) +{ + if (protocol != OtlpExportProtocol.HttpProtobuf) + return endpoint; + + var trimmed = endpoint.TrimEnd('/'); + + if (trimmed.EndsWith($"/v1/{signal}", StringComparison.OrdinalIgnoreCase)) + return trimmed; + + if (trimmed.EndsWith("/v1", StringComparison.OrdinalIgnoreCase)) + return $"{trimmed}/{signal}"; + + return $"{trimmed}/v1/{signal}"; +} diff --git a/src/apps/Elsa.ModularServer.Web/Properties/launchSettings.json b/src/apps/Elsa.ModularServer.Web/Properties/launchSettings.json index 2d8d243e8..cb36e8242 100644 --- a/src/apps/Elsa.ModularServer.Web/Properties/launchSettings.json +++ b/src/apps/Elsa.ModularServer.Web/Properties/launchSettings.json @@ -7,7 +7,10 @@ "launchBrowser": true, "applicationUrl": "http://localhost:5002", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "OTEL_SERVICE_NAME": "Elsa.ModularServer.Web", + "Diagnostics__OpenTelemetry__Exporter__Endpoint": "http://localhost:5002/elsa/otlp", + "Diagnostics__OpenTelemetry__Exporter__Protocol": "http/protobuf" } }, "https": { @@ -16,7 +19,34 @@ "launchBrowser": true, "applicationUrl": "https://localhost:7294;http://localhost:5002", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "OTEL_SERVICE_NAME": "Elsa.ModularServer.Web", + "Diagnostics__OpenTelemetry__Exporter__Endpoint": "https://localhost:7294/elsa/otlp", + "Diagnostics__OpenTelemetry__Exporter__Protocol": "http/protobuf" + } + }, + "http-aspire": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5002", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "OTEL_SERVICE_NAME": "Elsa.ModularServer.Web", + "Diagnostics__OpenTelemetry__Exporter__Endpoint": "http://localhost:4317", + "Diagnostics__OpenTelemetry__Exporter__Protocol": "grpc" + } + }, + "https-aspire": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7294;http://localhost:5002", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "OTEL_SERVICE_NAME": "Elsa.ModularServer.Web", + "Diagnostics__OpenTelemetry__Exporter__Endpoint": "http://localhost:4317", + "Diagnostics__OpenTelemetry__Exporter__Protocol": "grpc" } } } diff --git a/src/apps/Elsa.ModularServer.Web/appsettings.json b/src/apps/Elsa.ModularServer.Web/appsettings.json index 3b0d7ad3e..d7e3f4a0f 100644 --- a/src/apps/Elsa.ModularServer.Web/appsettings.json +++ b/src/apps/Elsa.ModularServer.Web/appsettings.json @@ -4,7 +4,8 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning", "Microsoft.EntityFrameworkCore": "Warning", - "Nuplane": "Warning" + "Nuplane": "Warning", + "CShells": "Warning" }, "Console": { "FormatterOptions": { @@ -12,6 +13,14 @@ } } }, + "Diagnostics": { + "OpenTelemetry": { + "Exporter": { + "Endpoint": "http://localhost:5002/elsa/otlp", + "Protocol": "http/protobuf" + } + } + }, "AllowedHosts": "*", "CShells": { "Shells": { @@ -44,6 +53,11 @@ }, "StructuredLogs": {}, "ConsoleLogs": {}, + "OpenTelemetry": {}, + "Alterations": {}, + "SqliteAlterationsPersistence": { + "ConnectionString": "Data Source=elsa_workflows.db;Cache=Shared" + }, "SqliteStructuredLogPersistence": { "ConnectionString": "Data Source=elsa_logs.db;Cache=Shared" }, diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Contracts/IActivityExecutionsApi.cs b/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Contracts/IActivityExecutionsApi.cs index 65266fb05..4535cebda 100644 --- a/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Contracts/IActivityExecutionsApi.cs +++ b/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Contracts/IActivityExecutionsApi.cs @@ -43,8 +43,8 @@ public interface IActivityExecutionsApi /// The ID of the activity execution. /// An optional cancellation token. /// The activity execution. - [Get("/activity-executions/{id}")] - Task GetAsync(string id, CancellationToken cancellationToken = default); + [Get("/activity-executions/by-id")] + Task GetAsync([Query] string id, CancellationToken cancellationToken = default); /// /// Gets the call stack (execution chain) for a given activity execution. diff --git a/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs b/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs index 8d4210e05..242f6d772 100644 --- a/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs +++ b/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs @@ -1,5 +1,6 @@ using Elsa.Mediator.Contexts; using Elsa.Mediator.Contracts; +using Elsa.Mediator.Middleware.Command; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Mediator.CommandStrategies; @@ -13,7 +14,15 @@ public class BackgroundStrategy : ICommandStrategy public async Task ExecuteAsync(CommandStrategyContext context) { var commandsChannel = context.ServiceProvider.GetRequiredService(); - await commandsChannel.Writer.WriteAsync(context.CommandContext, context.CancellationToken); + var commandContext = context.CommandContext; + var queuedContext = new CommandContext( + commandContext.Command, + CommandStrategy.Default, + commandContext.ResultType, + commandContext.Headers, + commandContext.ServiceProvider, + commandContext.CancellationToken); + await commandsChannel.Writer.WriteAsync(queuedContext, context.CancellationToken); return default!; } -} \ No newline at end of file +} diff --git a/src/common/Elsa.Mediator/Extensions/DependencyInjectionExtensions.cs b/src/common/Elsa.Mediator/Extensions/DependencyInjectionExtensions.cs index 68ea123d8..04f4f0ba9 100644 --- a/src/common/Elsa.Mediator/Extensions/DependencyInjectionExtensions.cs +++ b/src/common/Elsa.Mediator/Extensions/DependencyInjectionExtensions.cs @@ -48,15 +48,28 @@ public static class DependencyInjectionExtensions /// /// public static IServiceCollection AddMediatorHostedServices(this IServiceCollection services) + { + return services + .AddMediatorBackgroundChannels() + .AddHostedService() + .AddHostedService() + .AddHostedService(); + } + + /// + /// Adds mediator background processing channels to the . + /// + public static IServiceCollection AddMediatorBackgroundChannels(this IServiceCollection services) { return services .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() - .AddHostedService() - .AddHostedService() - .AddHostedService(); + .AddSingleton() + .AddSingleton() + .AddSingleton() + ; } /// @@ -225,4 +238,4 @@ public static class DependencyInjectionExtensions private static Channel CreateChannel() => Channel.CreateUnbounded(new UnboundedChannelOptions()); private static ChannelReader CreateChannelReader(IServiceProvider serviceProvider) => serviceProvider.GetRequiredService>().Reader; private static ChannelWriter CreateChannelWriter(IServiceProvider serviceProvider) => serviceProvider.GetRequiredService>().Writer; -} \ No newline at end of file +} diff --git a/src/common/Elsa.Mediator/HostedServices/BackgroundCommandSenderHostedService.cs b/src/common/Elsa.Mediator/HostedServices/BackgroundCommandSenderHostedService.cs index d8aa66be5..f75125a1c 100644 --- a/src/common/Elsa.Mediator/HostedServices/BackgroundCommandSenderHostedService.cs +++ b/src/common/Elsa.Mediator/HostedServices/BackgroundCommandSenderHostedService.cs @@ -1,103 +1,20 @@ -using System.Threading.Channels; -using Elsa.Mediator.Contracts; -using Elsa.Mediator.Middleware.Command; -using Elsa.Mediator.Options; -using Microsoft.Extensions.DependencyInjection; +using Elsa.Mediator.Services; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Elsa.Mediator.HostedServices; /// -/// Continuously reads from a channel to which commands can be sent, executing each received command. +/// Hosted service adapter for . /// -public class BackgroundCommandSenderHostedService : BackgroundService +public class BackgroundCommandSenderHostedService(BackgroundCommandProcessor processor) : BackgroundService { - private readonly int _workerCount; - private readonly ICommandsChannel _commandsChannel; - private readonly IServiceScopeFactory _scopeFactory; - private readonly List> _outputs; - private readonly ILogger _logger; - - /// - public BackgroundCommandSenderHostedService(IOptions options, ICommandsChannel commandsChannel, IServiceScopeFactory scopeFactory, ILogger logger) + /// + /// Initializes a new instance of the class. + /// + public BackgroundCommandSenderHostedService(BackgroundCommandProcessor processor, int workerCount) : this(processor) { - _workerCount = options.Value.CommandWorkerCount; - _commandsChannel = commandsChannel; // The shared input channel for all commands - _scopeFactory = scopeFactory; - _logger = logger; - _outputs = new(_workerCount); // Prepare a list to hold worker-specific channels } /// - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - var index = 0; // Used for round-robin distribution of work - - // Set up worker channels and start background tasks for each worker - for (var i = 0; i < _workerCount; i++) - { - var output = Channel.CreateUnbounded(); - _outputs.Add(output); - // Start a background task that processes commands from this worker's channel - _ = ReadOutputAsync(output, cancellationToken); - } - - // Main dispatcher loop: read from the input channel and distribute to worker channels - try - { - await foreach (var commandContext in _commandsChannel.Reader.ReadAllAsync(cancellationToken)) - { - var output = _outputs[index]; - await output.Writer.WriteAsync(commandContext, cancellationToken); - // Round-robin distribution - move to next worker - index = (index + 1) % _workerCount; - } - } - catch (OperationCanceledException ex) - { - _logger.LogDebug(ex, "An operation was cancelled while processing the queue"); - } - - // If the input channel is completed, complete all worker channels - foreach (var output in _outputs) - output.Writer.Complete(); - } - - private async Task ReadOutputAsync(Channel output, CancellationToken cancellationToken) - { - // Worker task: process commands from the worker's channel - try - { - await foreach (var commandContext in output.Reader.ReadAllAsync(cancellationToken)) - { - try - { - // Create a fresh scope for each command to ensure proper service lifetime - using var scope = _scopeFactory.CreateScope(); - var commandSender = scope.ServiceProvider.GetRequiredService(); - - // Decouple from the caller's CancellationToken. - // We use only the service's cancellationToken (the background worker's lifetime) - // to ensure that dispatched workflows are processed even if the original - // HTTP request or triggering context has timed out. - await commandSender.SendAsync( - commandContext.Command, - CommandStrategy.Default, - commandContext.Headers, - cancellationToken); - } - catch (Exception e) - { - // Log errors but continue processing other commands - _logger.LogError(e, "An unhandled exception occurred while processing the queue"); - } - } - } - catch (OperationCanceledException ex) - { - _logger.LogDebug(ex, "An operation was cancelled while processing the queue"); - } - } -} \ No newline at end of file + protected override Task ExecuteAsync(CancellationToken stoppingToken) => processor.ExecuteAsync(stoppingToken); +} diff --git a/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs b/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs index 9bb516bdf..411039b69 100644 --- a/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs +++ b/src/common/Elsa.Mediator/HostedServices/BackgroundEventPublisherHostedService.cs @@ -1,111 +1,20 @@ -using System.Threading.Channels; -using Elsa.Mediator.Contracts; -using Elsa.Mediator.Middleware.Notification; -using Elsa.Mediator.Options; -using Microsoft.Extensions.DependencyInjection; +using Elsa.Mediator.Services; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Elsa.Mediator.HostedServices; /// -/// Continuously reads from a channel to which notifications can be sent, publishing each received notification. +/// Hosted service adapter for . /// -public class BackgroundEventPublisherHostedService : BackgroundService +public class BackgroundEventPublisherHostedService(BackgroundNotificationProcessor processor) : BackgroundService { - private readonly int _workerCount; - private readonly INotificationsChannel _notificationsChannel; - private readonly IServiceScopeFactory _scopeFactory; - private readonly List> _outputs; - private readonly ILogger _logger; - - /// - public BackgroundEventPublisherHostedService(IOptions options, INotificationsChannel notificationsChannel, IServiceScopeFactory scopeFactory, ILogger logger) - { - _workerCount = options.Value.NotificationWorkerCount; - _notificationsChannel = notificationsChannel; - _scopeFactory = scopeFactory; - _logger = logger; - _outputs = new(_workerCount); - } - - /// - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - // Index to round-robin distribute notifications across worker channels - var index = 0; - - using var scope = _scopeFactory.CreateScope(); - var notificationSender = scope.ServiceProvider.GetRequiredService(); - - // Create multiple output channels and start worker tasks for parallel processing - for (var i = 0; i < _workerCount; i++) - { - var output = Channel.CreateUnbounded(); - _outputs.Add(output); - // Start a background task to process notifications from this output channel - _ = ReadOutputAsync(output, notificationSender, cancellationToken); - } - - var channelReader = _notificationsChannel.Reader; - - // Continuously read notifications from the input channel and distribute them to worker channels - // using round-robin distribution for load balancing - try - { - await foreach (var notification in channelReader.ReadAllAsync(cancellationToken)) - { - var output = _outputs[index]; - await output.Writer.WriteAsync(notification, cancellationToken); - // Move to the next worker in a circular fashion - index = (index + 1) % _workerCount; - } - } - catch (OperationCanceledException ex) - { - _logger.LogDebug(ex, "An operation was cancelled while processing the queue"); - } - - // When the input channel is completed, complete all output channels - foreach (var output in _outputs) - { - output.Writer.Complete(); - } - } - /// - /// Processes notifications from an output channel asynchronously. + /// Initializes a new instance of the class. /// - /// The channel to read notifications from - /// The service used to send notifications - /// Cancellation token from the hosted service - private async Task ReadOutputAsync(Channel output, INotificationSender notificationSender, CancellationToken cancellationToken) + public BackgroundEventPublisherHostedService(BackgroundNotificationProcessor processor, int workerCount) : this(processor) { - try - { - await foreach (var notificationContext in output.Reader.ReadAllAsync(cancellationToken)) - { - try - { - var notification = notificationContext.Notification; - // Link the cancellation tokens so that cancellation can happen from either source - using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, notificationContext.CancellationToken); - await notificationSender.SendAsync(notification, NotificationStrategy.Sequential, linkedTokenSource.Token); - } - catch (OperationCanceledException e) - { - _logger.LogDebug(e, "An operation was cancelled while processing the queue"); - } - catch (Exception e) - { - _logger.LogError(e, "An unhandled exception occurred while processing the queue"); - } - } - } - catch (OperationCanceledException ex) - { - _logger.LogDebug(ex, "An operation was cancelled while processing the queue"); - } } -} \ No newline at end of file + + /// + protected override Task ExecuteAsync(CancellationToken stoppingToken) => processor.ExecuteAsync(stoppingToken); +} diff --git a/src/common/Elsa.Mediator/HostedServices/JobRunnerHostedService.cs b/src/common/Elsa.Mediator/HostedServices/JobRunnerHostedService.cs index 14af18b4b..603f83f89 100644 --- a/src/common/Elsa.Mediator/HostedServices/JobRunnerHostedService.cs +++ b/src/common/Elsa.Mediator/HostedServices/JobRunnerHostedService.cs @@ -1,71 +1,13 @@ -using Elsa.Mediator.Contracts; -using Elsa.Mediator.Options; +using Elsa.Mediator.Services; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Elsa.Mediator.HostedServices; /// -/// A hosted service that runs jobs. +/// Hosted service adapter for . /// -public class JobRunnerHostedService : BackgroundService +public class JobRunnerHostedService(BackgroundJobProcessor processor) : BackgroundService { - private readonly int _workerCount; - private readonly IJobsChannel _jobsChannel; - private readonly ILogger _logger; - /// - public JobRunnerHostedService(IOptions options, IJobsChannel jobsChannel, ILogger logger) - { - _workerCount = options.Value.JobWorkerCount; - _jobsChannel = jobsChannel; - _logger = logger; - } - - /// - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - // Create an array of worker tasks to process jobs in parallel - var workers = new Task[_workerCount]; - - // Start multiple workers (tasks) to process jobs concurrently - for (var i = 0; i < _workerCount; i++) - workers[i] = ProcessJobsAsync(stoppingToken); - - // Wait for all worker tasks to complete (typically when the application is shutting down) - await Task.WhenAll(workers); - } - - /// - /// Continuously processes jobs from the job channel until cancellation is requested. - /// - /// Cancellation token from the hosted service - private async Task ProcessJobsAsync(CancellationToken stoppingToken) - { - // Process all jobs from the channel until it's completed or cancellation is requested - await foreach (var jobItem in _jobsChannel.Reader.ReadAllAsync(stoppingToken)) - { - try - { - // Link the cancellation tokens so that cancellation can happen from either source - using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, jobItem.CancellationTokenSource.Token); - await jobItem.Action(linkedTokenSource.Token); - _logger.LogInformation("Worker {CurrentTaskId} processed job {JobId}", Task.CurrentId, jobItem.JobId); - } - catch (OperationCanceledException) - { - _logger.LogInformation("Job {JobId} was canceled", jobItem.JobId); - } - catch (Exception ex) - { - _logger.LogError(ex, "Job {JobId} failed", jobItem.JobId); - } - finally - { - // Notify that the job has completed (whether successfully or not) - jobItem.OnJobCompleted(jobItem.JobId); - } - } - } -} \ No newline at end of file + protected override Task ExecuteAsync(CancellationToken stoppingToken) => processor.ExecuteAsync(stoppingToken); +} diff --git a/src/common/Elsa.Mediator/PublishingStrategies/BackgroundProcessingStrategy.cs b/src/common/Elsa.Mediator/PublishingStrategies/BackgroundProcessingStrategy.cs index e960050f5..c611415e5 100644 --- a/src/common/Elsa.Mediator/PublishingStrategies/BackgroundProcessingStrategy.cs +++ b/src/common/Elsa.Mediator/PublishingStrategies/BackgroundProcessingStrategy.cs @@ -1,5 +1,6 @@ using Elsa.Mediator.Contexts; using Elsa.Mediator.Contracts; +using Elsa.Mediator.Middleware.Notification; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Mediator.PublishingStrategies; @@ -13,7 +14,13 @@ public class BackgroundProcessingStrategy : IEventPublishingStrategy public async Task PublishAsync(NotificationStrategyContext context) { var notificationsChannel = context.ServiceProvider.GetRequiredService(); + var notificationContext = context.NotificationContext; + var queuedContext = new NotificationContext( + notificationContext.Notification, + NotificationStrategy.Sequential, + notificationContext.ServiceProvider, + notificationContext.CancellationToken); - await notificationsChannel.Writer.WriteAsync(context.NotificationContext, context.CancellationToken); + await notificationsChannel.Writer.WriteAsync(queuedContext, context.CancellationToken); } -} \ No newline at end of file +} diff --git a/src/common/Elsa.Mediator/Services/BackgroundCommandProcessor.cs b/src/common/Elsa.Mediator/Services/BackgroundCommandProcessor.cs new file mode 100644 index 000000000..876bbd59a --- /dev/null +++ b/src/common/Elsa.Mediator/Services/BackgroundCommandProcessor.cs @@ -0,0 +1,101 @@ +using System.Threading.Channels; +using Elsa.Mediator.Contracts; +using Elsa.Mediator.Middleware.Command; +using Elsa.Mediator.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Elsa.Mediator.Services; + +/// +/// Continuously reads from a channel to which commands can be sent, executing each received command. +/// +public class BackgroundCommandProcessor +{ + private readonly int _workerCount; + private readonly ICommandsChannel _commandsChannel; + private readonly IServiceScopeFactory _scopeFactory; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public BackgroundCommandProcessor(IOptions options, ICommandsChannel commandsChannel, IServiceScopeFactory scopeFactory, ILogger logger) + { + _workerCount = options.Value.CommandWorkerCount; + _commandsChannel = commandsChannel; + _scopeFactory = scopeFactory; + _logger = logger; + } + + /// + /// Runs the processor until cancellation is requested. + /// + public async Task ExecuteAsync(CancellationToken cancellationToken) + { + var index = 0; + var outputs = new List>(_workerCount); + var workers = new List(_workerCount); + + for (var i = 0; i < _workerCount; i++) + { + var output = Channel.CreateUnbounded(); + outputs.Add(output); + workers.Add(ReadOutputAsync(output, cancellationToken)); + } + + try + { + await foreach (var commandContext in _commandsChannel.Reader.ReadAllAsync(cancellationToken)) + { + var output = outputs[index]; + await output.Writer.WriteAsync(commandContext, cancellationToken); + index = (index + 1) % _workerCount; + } + } + catch (OperationCanceledException ex) when (cancellationToken.IsCancellationRequested) + { + _logger.LogDebug(ex, "An operation was cancelled while processing the command queue"); + } + + foreach (var output in outputs) + output.Writer.Complete(); + + await Task.WhenAll(workers); + } + + private async Task ReadOutputAsync(Channel output, CancellationToken cancellationToken) + { + try + { + await foreach (var commandContext in output.Reader.ReadAllAsync(cancellationToken)) + { + try + { + using var scope = _scopeFactory.CreateScope(); + var commandSender = scope.ServiceProvider.GetRequiredService(); + using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, commandContext.CancellationToken); + + await commandSender.SendAsync( + commandContext.Command, + commandContext.CommandStrategy, + commandContext.Headers, + linkedTokenSource.Token); + } + catch (OperationCanceledException e) + { + _logger.LogDebug(e, "An operation was cancelled while processing the command queue"); + } + catch (Exception e) + { + _logger.LogError(e, "An unhandled exception occurred while processing the command queue"); + } + } + } + catch (OperationCanceledException ex) when (cancellationToken.IsCancellationRequested) + { + _logger.LogDebug(ex, "An operation was cancelled while processing the command queue"); + } + } +} diff --git a/src/common/Elsa.Mediator/Services/BackgroundJobProcessor.cs b/src/common/Elsa.Mediator/Services/BackgroundJobProcessor.cs new file mode 100644 index 000000000..dee6867f3 --- /dev/null +++ b/src/common/Elsa.Mediator/Services/BackgroundJobProcessor.cs @@ -0,0 +1,71 @@ +using Elsa.Mediator.Contracts; +using Elsa.Mediator.Options; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Elsa.Mediator.Services; + +/// +/// Continuously reads from a channel to which jobs can be sent, executing each received job. +/// +public class BackgroundJobProcessor +{ + private readonly int _workerCount; + private readonly IJobsChannel _jobsChannel; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public BackgroundJobProcessor(IOptions options, IJobsChannel jobsChannel, ILogger logger) + { + _workerCount = options.Value.JobWorkerCount; + _jobsChannel = jobsChannel; + _logger = logger; + } + + /// + /// Runs the processor until cancellation is requested. + /// + public async Task ExecuteAsync(CancellationToken cancellationToken) + { + var workers = new Task[_workerCount]; + + for (var i = 0; i < _workerCount; i++) + workers[i] = ProcessJobsAsync(cancellationToken); + + await Task.WhenAll(workers); + } + + private async Task ProcessJobsAsync(CancellationToken cancellationToken) + { + try + { + await foreach (var jobItem in _jobsChannel.Reader.ReadAllAsync(cancellationToken)) + { + try + { + using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, jobItem.CancellationTokenSource.Token); + await jobItem.Action(linkedTokenSource.Token); + _logger.LogInformation("Worker {CurrentTaskId} processed job {JobId}", Task.CurrentId, jobItem.JobId); + } + catch (OperationCanceledException) + { + _logger.LogInformation("Job {JobId} was canceled", jobItem.JobId); + } + catch (Exception ex) + { + _logger.LogError(ex, "Job {JobId} failed", jobItem.JobId); + } + finally + { + jobItem.OnJobCompleted(jobItem.JobId); + } + } + } + catch (OperationCanceledException ex) when (cancellationToken.IsCancellationRequested) + { + _logger.LogDebug(ex, "An operation was cancelled while processing the job queue"); + } + } +} diff --git a/src/common/Elsa.Mediator/Services/BackgroundNotificationProcessor.cs b/src/common/Elsa.Mediator/Services/BackgroundNotificationProcessor.cs new file mode 100644 index 000000000..8e062287a --- /dev/null +++ b/src/common/Elsa.Mediator/Services/BackgroundNotificationProcessor.cs @@ -0,0 +1,98 @@ +using System.Threading.Channels; +using Elsa.Mediator.Contracts; +using Elsa.Mediator.Middleware.Notification; +using Elsa.Mediator.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Elsa.Mediator.Services; + +/// +/// Continuously reads from a channel to which notifications can be sent, publishing each received notification. +/// +public class BackgroundNotificationProcessor +{ + private readonly int _workerCount; + private readonly INotificationsChannel _notificationsChannel; + private readonly IServiceScopeFactory _scopeFactory; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public BackgroundNotificationProcessor(IOptions options, INotificationsChannel notificationsChannel, IServiceScopeFactory scopeFactory, ILogger logger) + { + _workerCount = options.Value.NotificationWorkerCount; + _notificationsChannel = notificationsChannel; + _scopeFactory = scopeFactory; + _logger = logger; + } + + /// + /// Runs the processor until cancellation is requested. + /// + public async Task ExecuteAsync(CancellationToken cancellationToken) + { + var index = 0; + var outputs = new List>(_workerCount); + var workers = new List(_workerCount); + + for (var i = 0; i < _workerCount; i++) + { + var output = Channel.CreateUnbounded(); + outputs.Add(output); + workers.Add(ReadOutputAsync(output, cancellationToken)); + } + + try + { + await foreach (var notification in _notificationsChannel.Reader.ReadAllAsync(cancellationToken)) + { + var output = outputs[index]; + await output.Writer.WriteAsync(notification, cancellationToken); + index = (index + 1) % _workerCount; + } + } + catch (OperationCanceledException ex) when (cancellationToken.IsCancellationRequested) + { + _logger.LogDebug(ex, "An operation was cancelled while processing the notification queue"); + } + + foreach (var output in outputs) + output.Writer.Complete(); + + await Task.WhenAll(workers); + } + + private async Task ReadOutputAsync(Channel output, CancellationToken cancellationToken) + { + try + { + using var scope = _scopeFactory.CreateScope(); + var notificationSender = scope.ServiceProvider.GetRequiredService(); + + await foreach (var notificationContext in output.Reader.ReadAllAsync(cancellationToken)) + { + try + { + var notification = notificationContext.Notification; + using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, notificationContext.CancellationToken); + await notificationSender.SendAsync(notification, notificationContext.NotificationStrategy, linkedTokenSource.Token); + } + catch (OperationCanceledException e) + { + _logger.LogDebug(e, "An operation was cancelled while processing the notification queue"); + } + catch (Exception e) + { + _logger.LogError(e, "An unhandled exception occurred while processing the notification queue"); + } + } + } + catch (OperationCanceledException ex) when (cancellationToken.IsCancellationRequested) + { + _logger.LogDebug(ex, "An operation was cancelled while processing the notification queue"); + } + } +} diff --git a/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs b/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs index 947221322..2b608d392 100644 --- a/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs +++ b/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs @@ -6,7 +6,7 @@ using Elsa.Alterations.Core.Stores; using Elsa.Alterations.Extensions; using Elsa.Alterations.Services; using Elsa.Alterations.Workflows; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Services; @@ -60,7 +60,7 @@ public class AlterationsFeature : FeatureBase /// public override void Apply() { - Services.Configure(options => + Services.Configure(options => { options.RegisterTypeAlias(typeof(AlterationPlanParams), typeof(AlterationPlanParams).GetSimpleAssemblyQualifiedName()); options.RegisterTypeAlias(typeof(AlterationPlanParams), nameof(AlterationPlanParams)); diff --git a/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs b/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs index cb8674b42..aa6962a91 100644 --- a/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs +++ b/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs @@ -1,10 +1,14 @@ +using CShells.FastEndpoints.Features; using CShells.Features; using Elsa.Alterations.Core.Contracts; using Elsa.Alterations.Core.Entities; using Elsa.Alterations.Core.Extensions; +using Elsa.Alterations.Core.Models; using Elsa.Alterations.Core.Stores; using Elsa.Alterations.Extensions; using Elsa.Alterations.Services; +using Elsa.Alterations.Workflows; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; @@ -16,9 +20,10 @@ namespace Elsa.Alterations.ShellFeatures; /// [ShellFeature( DisplayName = "Alterations", - Description = "Provides workflow alteration capabilities for modifying running workflow instances")] + Description = "Provides workflow alteration capabilities for modifying running workflow instances", + DependsOn = ["ElsaFastEndpoints", "WorkflowRuntime"])] [UsedImplicitly] -public class AlterationsFeature : IShellFeature +public class AlterationsFeature : IFastEndpointsShellFeature { /// /// Gets or sets the factory for the alteration plan store. @@ -37,6 +42,12 @@ public class AlterationsFeature : IShellFeature public void ConfigureServices(IServiceCollection services) { + services.Configure(options => + { + options.RegisterTypeAlias(typeof(AlterationPlanParams), typeof(AlterationPlanParams).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(AlterationPlanParams), nameof(AlterationPlanParams)); + }); + services.AddScoped(); services.AddAlterations(); services.AddAlterationsCore(); @@ -51,6 +62,7 @@ public class AlterationsFeature : IShellFeature services.AddScoped(AlterationPlanStoreFactory); services.AddScoped(AlterationJobStoreFactory); services.AddScoped(AlterationJobDispatcherFactory); + + services.AddWorkflow(); } } - diff --git a/src/modules/Elsa.Common/Entities/OrderDefinition.cs b/src/modules/Elsa.Common/Entities/OrderDefinition.cs index 8a50560f5..18c1fa090 100644 --- a/src/modules/Elsa.Common/Entities/OrderDefinition.cs +++ b/src/modules/Elsa.Common/Entities/OrderDefinition.cs @@ -34,10 +34,4 @@ public class OrderDefinition /// [JsonIgnore] public Expression> KeySelector { get; set; } = null!; - - /// - /// A best-effort textual representation of the key selector for cache-key generation. - /// - [JsonIgnore] - public string? KeySelectorText => KeySelector?.ToString(); } diff --git a/src/modules/Elsa.Common/ShellFeatures/MediatorFeature.cs b/src/modules/Elsa.Common/ShellFeatures/MediatorFeature.cs index e162e8d10..6808838c4 100644 --- a/src/modules/Elsa.Common/ShellFeatures/MediatorFeature.cs +++ b/src/modules/Elsa.Common/ShellFeatures/MediatorFeature.cs @@ -1,5 +1,8 @@ using CShells.Features; +using Elsa.Common.ShellHandlers; +using Elsa.Extensions; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace Elsa.Common.ShellFeatures; @@ -9,13 +12,17 @@ namespace Elsa.Common.ShellFeatures; [ShellFeature( "Mediator", DisplayName = "Mediator", - Description = "Registers mediator services for in-process notifications and requests")] + Description = "Registers mediator services for in-process notifications and requests", + DependsOn = [typeof(MultitenancyFeature)])] public class MediatorFeature : IShellFeature { public void ConfigureServices(IServiceCollection services) { services .AddMediator() - .AddMediatorHostedServices(); + .AddMediatorBackgroundChannels(); + + services.TryAddSingleton(); + services.AddBackgroundTask(); } } diff --git a/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundProcessingCoordinator.cs b/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundProcessingCoordinator.cs new file mode 100644 index 000000000..702e438c7 --- /dev/null +++ b/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundProcessingCoordinator.cs @@ -0,0 +1,91 @@ +using Elsa.Mediator.Services; +using Microsoft.Extensions.Logging; + +namespace Elsa.Common.ShellHandlers; + +public sealed class MediatorBackgroundProcessingCoordinator( + BackgroundCommandProcessor commandProcessor, + BackgroundNotificationProcessor notificationProcessor, + BackgroundJobProcessor jobProcessor, + ILogger logger) : IAsyncDisposable +{ + private readonly SemaphoreSlim _lock = new(1, 1); + private CancellationTokenSource? _cancellationTokenSource; + private Task? _processingTask; + private int _referenceCount; + + public async Task StartAsync(CancellationToken cancellationToken = default) + { + await _lock.WaitAsync(cancellationToken); + try + { + if (_referenceCount++ > 0) + return; + + _cancellationTokenSource = new(); + _processingTask = Task.WhenAll( + commandProcessor.ExecuteAsync(_cancellationTokenSource.Token), + notificationProcessor.ExecuteAsync(_cancellationTokenSource.Token), + jobProcessor.ExecuteAsync(_cancellationTokenSource.Token)); + } + finally + { + _lock.Release(); + } + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + Task? processingTask; + CancellationTokenSource? cancellationTokenSource; + + await _lock.WaitAsync(cancellationToken); + try + { + if (_referenceCount == 0) + return; + + if (--_referenceCount > 0) + return; + + processingTask = _processingTask; + cancellationTokenSource = _cancellationTokenSource; + _processingTask = null; + _cancellationTokenSource = null; + } + finally + { + _lock.Release(); + } + + if (cancellationTokenSource is null) + return; + + await cancellationTokenSource.CancelAsync(); + + if (processingTask is not null) + { + try + { + await processingTask.WaitAsync(cancellationToken); + } + catch (OperationCanceledException) when (cancellationTokenSource.IsCancellationRequested) + { + } + catch (Exception e) + { + logger.LogError(e, "An error occurred while stopping mediator background processing"); + throw; + } + } + + cancellationTokenSource.Dispose(); + } + + public async ValueTask DisposeAsync() + { + _referenceCount = 1; + await StopAsync(CancellationToken.None); + _lock.Dispose(); + } +} diff --git a/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundTask.cs b/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundTask.cs new file mode 100644 index 000000000..62756b83c --- /dev/null +++ b/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundTask.cs @@ -0,0 +1,10 @@ +using Elsa.Common; + +namespace Elsa.Common.ShellHandlers; + +public sealed class MediatorBackgroundTask(MediatorBackgroundProcessingCoordinator coordinator) : BackgroundTask +{ + public override Task StartAsync(CancellationToken cancellationToken) => coordinator.StartAsync(cancellationToken); + + public override Task StopAsync(CancellationToken cancellationToken) => coordinator.StopAsync(cancellationToken); +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/AssemblyInfo.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/AssemblyInfo.cs new file mode 100644 index 000000000..5b9f0622d --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Elsa.Diagnostics.ConsoleLogs.UnitTests")] diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ConsoleStreamJsonConverter.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ConsoleStreamJsonConverter.cs new file mode 100644 index 000000000..d3274d5bb --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ConsoleStreamJsonConverter.cs @@ -0,0 +1,57 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using ConsoleLogStreaming.Core.Models; + +namespace Elsa.Diagnostics.ConsoleLogs.Contracts; + +/// +/// Converts the public console stream filter contract values. +/// +public sealed class ConsoleStreamJsonConverter : JsonConverter +{ + public override ConsoleStream? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.Null => null, + JsonTokenType.String => ReadString(reader.GetString()), + JsonTokenType.Number => ReadNumber(ref reader), + _ => throw new JsonException("The console log stream filter must be 'stdout', 'stderr', or null.") + }; + } + + public override void Write(Utf8JsonWriter writer, ConsoleStream? value, JsonSerializerOptions options) + { + if (value == null) + { + writer.WriteNullValue(); + return; + } + + writer.WriteStringValue(value.Value switch + { + ConsoleStream.Stdout => "stdout", + ConsoleStream.Stderr => "stderr", + _ => throw new JsonException($"Unsupported console stream value '{value}'.") + }); + } + + private static ConsoleStream? ReadString(string? value) + { + return value?.Trim().ToLowerInvariant() switch + { + null or "" or "all" => null, + "stdout" => ConsoleStream.Stdout, + "stderr" => ConsoleStream.Stderr, + _ => throw new JsonException("The console log stream filter must be 'stdout', 'stderr', or null.") + }; + } + + private static ConsoleStream ReadNumber(ref Utf8JsonReader reader) + { + if (!reader.TryGetInt32(out var value) || !Enum.IsDefined(typeof(ConsoleStream), value)) + throw new JsonException("The console log stream filter has an unsupported numeric value."); + + return (ConsoleStream)value; + } +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs index 8571ce119..b4b0e42fb 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs @@ -1,21 +1,25 @@ +using System.Text.Json.Serialization; + namespace Elsa.Diagnostics.ConsoleLogs.Contracts; /// /// Console log filter accepted by Elsa REST and SignalR endpoints. /// -public sealed record ElsaConsoleLogFilter +public sealed class ElsaConsoleLogFilter { - public string? SourceId { get; init; } - public global::ConsoleLogStreaming.Contracts.ConsoleLogStreaming? Stream { get; init; } - public string? Query { get; init; } - public string? WorkflowInstanceId { get; init; } - public string? WorkflowDefinitionId { get; init; } - public string? WorkflowDefinitionVersionId { get; init; } - public string? ActivityInstanceId { get; init; } - public string? ActivityId { get; init; } - public string? ActivityNodeId { get; init; } - public IReadOnlyDictionary? Metadata { get; init; } - public DateTimeOffset? From { get; init; } - public DateTimeOffset? To { get; init; } - public int? Limit { get; init; } + public string? SourceId { get; set; } + + [JsonConverter(typeof(ConsoleStreamJsonConverter))] + public global::ConsoleLogStreaming.Core.Models.ConsoleStream? Stream { get; set; } + public string? Query { get; set; } + public string? WorkflowInstanceId { get; set; } + public string? WorkflowDefinitionId { get; set; } + public string? WorkflowDefinitionVersionId { get; set; } + public string? ActivityInstanceId { get; set; } + public string? ActivityId { get; set; } + public string? ActivityNodeId { get; set; } + public IDictionary? Metadata { get; set; } + public DateTimeOffset? From { get; set; } + public DateTimeOffset? To { get; set; } + public int? Limit { get; set; } } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Elsa.Diagnostics.ConsoleLogs.csproj b/src/modules/Elsa.Diagnostics.ConsoleLogs/Elsa.Diagnostics.ConsoleLogs.csproj index d1b95cc5b..208c80ab4 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Elsa.Diagnostics.ConsoleLogs.csproj +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Elsa.Diagnostics.ConsoleLogs.csproj @@ -8,13 +8,13 @@ + + + - - - diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Recent/Endpoint.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Recent/Endpoint.cs index 906218c13..6f51c3436 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Recent/Endpoint.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Recent/Endpoint.cs @@ -1,15 +1,18 @@ +using System.Text.Json; using ConsoleLogStreaming.Core; using Elsa.Abstractions; -using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Permissions; using Elsa.Diagnostics.ConsoleLogs.Services; using JetBrains.Annotations; +using Microsoft.AspNetCore.Http; namespace Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent; [PublicAPI] -internal class Endpoint(IConsoleLogProvider provider, IConsoleLogStreamingApiMapper mapper) : ElsaEndpoint +internal class Endpoint(IConsoleLogProvider provider) : ElsaEndpointWithoutRequest { + private static readonly JsonSerializerOptions JsonSerializerOptions = new(JsonSerializerDefaults.Web); + public override void Configure() { Verbs(FastEndpoints.Http.POST); @@ -17,9 +20,47 @@ internal class Endpoint(IConsoleLogProvider provider, IConsoleLogStreamingApiMap ConfigurePermissions(ConsoleLogsPermissions.Read); } - public override async Task ExecuteAsync(ElsaConsoleLogFilter request, CancellationToken cancellationToken) + public override async Task ExecuteAsync(CancellationToken cancellationToken) { - var result = await provider.GetRecentAsync(mapper.ToCore(ConsoleLogFilterMapper.ToStreamingFilter(request)), cancellationToken); - return mapper.ToApi(result); + var request = await ReadJsonBodyAsync(cancellationToken); + if (ValidationFailed) + { + await Send.ErrorsAsync(StatusCodes.Status400BadRequest, cancellationToken); + return new(); + } + + var result = await provider.GetRecentAsync(ConsoleLogFilterMapper.ToStreamingFilter(request ?? new()), cancellationToken); + return result; + } + + private async Task ReadJsonBodyAsync(CancellationToken cancellationToken) + { + if (HttpContext.Request.ContentLength is 0) + return null; + + if (!HttpContext.Request.HasJsonContentType()) + return null; + + using var body = new MemoryStream(); + await HttpContext.Request.Body.CopyToAsync(body, cancellationToken); + + if (body.Length == 0) + return null; + + body.Position = 0; + try + { + return await DeserializeJsonBodyAsync(body, cancellationToken); + } + catch (JsonException) + { + AddError("Invalid console log filter JSON."); + return null; + } + } + + internal static async ValueTask DeserializeJsonBodyAsync(Stream body, CancellationToken cancellationToken) + { + return await JsonSerializer.DeserializeAsync(body, JsonSerializerOptions, cancellationToken); } } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs index 98e1ed557..81858b72b 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs @@ -6,7 +6,7 @@ using JetBrains.Annotations; namespace Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Sources; [PublicAPI] -internal class Endpoint(IConsoleLogProvider provider, IConsoleLogStreamingApiMapper mapper) : ElsaEndpointWithoutRequest> +internal class Endpoint(IConsoleLogProvider provider) : ElsaEndpointWithoutRequest> { public override void Configure() { @@ -16,7 +16,6 @@ internal class Endpoint(IConsoleLogProvider provider, IConsoleLogStreamingApiMap public override async Task> ExecuteAsync(CancellationToken cancellationToken) { - var sources = await provider.ListSourcesAsync(cancellationToken); - return sources.Select(mapper.ToApi).ToList(); + return await provider.ListSourcesAsync(cancellationToken); } } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogContextServiceCollectionExtensions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogContextServiceCollectionExtensions.cs index 0463ef364..ac4bb466d 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogContextServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogContextServiceCollectionExtensions.cs @@ -1,7 +1,4 @@ -using ConsoleLogStreaming.Core; -using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Services; -using Elsa.Workflows; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -13,7 +10,7 @@ internal static class ConsoleLogContextServiceCollectionExtensions { services.TryAddSingleton(_ => ConsoleLogContextAccessor.Instance); services.TryAddSingleton(sp => sp.GetRequiredService()); - services.TryAddSingleton(sp => sp.GetRequiredService()); + services.TryAddSingleton(sp => sp.GetRequiredService()); services.TryAddEnumerable(ServiceDescriptor.Scoped()); services.TryAddEnumerable(ServiceDescriptor.Scoped()); return services; diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogProviderServiceCollectionExtensions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogProviderServiceCollectionExtensions.cs new file mode 100644 index 000000000..b0efb30d7 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ConsoleLogProviderServiceCollectionExtensions.cs @@ -0,0 +1,40 @@ +using ConsoleLogStreaming.Core; +using Elsa.Diagnostics.ConsoleLogs.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Elsa.Diagnostics.ConsoleLogs.Extensions; + +internal static class ConsoleLogProviderServiceCollectionExtensions +{ + public static void DecorateConsoleLogProvider(this IServiceCollection services) + { + var descriptor = services.LastOrDefault(x => x.ServiceType == typeof(IConsoleLogProvider)); + if (descriptor == null) + return; + + services.TryAddSingleton(); + services.Remove(descriptor); + services.Add(ServiceDescriptor.Describe( + typeof(IConsoleLogProvider), + sp => new ElsaConsoleLogProvider( + CreateProvider(sp, descriptor), + sp.GetRequiredService(), + sp.GetRequiredService()), + descriptor.Lifetime)); + } + + private static IConsoleLogProvider CreateProvider(IServiceProvider serviceProvider, ServiceDescriptor descriptor) + { + if (descriptor.ImplementationInstance is IConsoleLogProvider instance) + return instance; + + if (descriptor.ImplementationFactory != null) + return (IConsoleLogProvider)descriptor.ImplementationFactory(serviceProvider)!; + + if (descriptor.ImplementationType != null) + return (IConsoleLogProvider)ActivatorUtilities.CreateInstance(serviceProvider, descriptor.ImplementationType); + + throw new InvalidOperationException("The console log provider registration is invalid."); + } +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/EndpointRouteBuilderExtensions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/EndpointRouteBuilderExtensions.cs index 6401544fb..666ee32a6 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/EndpointRouteBuilderExtensions.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/EndpointRouteBuilderExtensions.cs @@ -1,9 +1,6 @@ -using ConsoleLogStreaming.SignalR; using Elsa.Diagnostics.ConsoleLogs.RealTime; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; namespace Elsa.Diagnostics.ConsoleLogs.Extensions; @@ -13,12 +10,6 @@ public static class EndpointRouteBuilderExtensions public static void MapConsoleLogsHub(this IEndpointRouteBuilder endpoints) { - var options = endpoints.ServiceProvider.GetRequiredService>().Value; - var hub = endpoints.MapHub(options.HubPath); - - if (!string.IsNullOrWhiteSpace(options.AuthorizationPolicy)) - hub.RequireAuthorization(options.AuthorizationPolicy); - - options.ConfigureHubEndpoint?.Invoke(hub); + endpoints.MapHub(HubRoute); } } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/HostServiceCollectionExtensions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/HostServiceCollectionExtensions.cs index 93d996cc1..f6152bbfb 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/HostServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/HostServiceCollectionExtensions.cs @@ -1,13 +1,10 @@ -using ConsoleLogStreaming.Contracts; -using ConsoleLogStreaming.Core; using ConsoleLogStreaming.Core.DependencyInjection; using ConsoleLogStreaming.Core.Options; -using ConsoleLogStreaming.SignalR; -using ConsoleLogStreaming.SignalR.DependencyInjection; using Elsa.Diagnostics.ConsoleLogs.RealTime; using Elsa.Diagnostics.ConsoleLogs.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; namespace Elsa.Diagnostics.ConsoleLogs.Extensions; @@ -19,14 +16,16 @@ public static class HostServiceCollectionExtensions public static IServiceCollection AddConsoleLogsHost(this IServiceCollection services, Action? configure = null) { services.AddConsoleLogContextServices(); - services.AddConsoleLogStreamingHost(options => + services.AddConsoleLogStreaming(options => { ElsaConsoleLogOptions.ConfigureDefaults(options); configure?.Invoke(options); }); - services.AddConsoleLogStreamingSignalR(options => options.HubPath = EndpointRouteBuilderExtensions.HubRoute); - services.TryAddSingleton(); + services.AddSignalR(); + services.DecorateConsoleLogProvider(); + services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddEnumerable(ServiceDescriptor.Singleton()); return services; } } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ServiceCollectionExtensions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ServiceCollectionExtensions.cs index 4cf635467..c0dde3cac 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Extensions/ServiceCollectionExtensions.cs @@ -1,9 +1,6 @@ -using ConsoleLogStreaming.Contracts; -using ConsoleLogStreaming.Core; using ConsoleLogStreaming.Core.DependencyInjection; using ConsoleLogStreaming.Core.Options; -using ConsoleLogStreaming.SignalR; -using ConsoleLogStreaming.SignalR.DependencyInjection; +using CShells.Lifecycle; using Elsa.Diagnostics.ConsoleLogs.RealTime; using Elsa.Diagnostics.ConsoleLogs.Services; using Microsoft.Extensions.DependencyInjection; @@ -19,14 +16,18 @@ public static class ServiceCollectionExtensions public static IServiceCollection AddConsoleLogsServices(this IServiceCollection services, Action? configureOptions = null) { services.AddConsoleLogContextServices(); - services.AddConsoleLogStreamingHost(options => + services.AddConsoleLogStreaming(options => { ElsaConsoleLogOptions.ConfigureDefaults(options); configureOptions?.Invoke(options); }); - services.AddConsoleLogStreamingSignalR(options => options.HubPath = EndpointRouteBuilderExtensions.HubRoute); - services.TryAddSingleton(); + services.AddSignalR(); + services.DecorateConsoleLogProvider(); + services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddScoped(); + services.TryAddEnumerable(ServiceDescriptor.Scoped()); + services.TryAddEnumerable(ServiceDescriptor.Scoped()); return services; } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/README.md b/src/modules/Elsa.Diagnostics.ConsoleLogs/README.md index 96c3c6c13..dd8058740 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/README.md +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/README.md @@ -69,7 +69,7 @@ tee, the capture publishes them verbatim, and the Studio renders them. Recent, source, and hub access all require the same permission. -Custom storage providers should implement `ConsoleLogStreaming.Core.IConsoleLogProvider` and use the core models. Elsa-specific values such as workflow instance IDs are represented as metadata internally and projected onto shared `ConsoleLogStreaming.Contracts` DTOs at the REST and SignalR boundaries. +Custom storage providers should implement `ConsoleLogStreaming.Core.IConsoleLogProvider` and use the core models. Elsa-specific values such as workflow instance IDs are represented as metadata internally and projected onto shared `ConsoleLogStreaming.Core.Models` DTOs at the REST and SignalR boundaries. ## Safety Boundaries diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs index ecc1237f2..0b25cc2a6 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs @@ -1,13 +1,8 @@ using System.Collections.Concurrent; -using ConsoleLogStreaming.Contracts; using ConsoleLogStreaming.Core; -using ConsoleLogStreaming.SignalR; -using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Services; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; -using CoreConsoleLogSource = ConsoleLogStreaming.Core.Models.ConsoleLogSource; - namespace Elsa.Diagnostics.ConsoleLogs.RealTime; /// @@ -17,9 +12,7 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable { private readonly ConcurrentDictionary _subscriptions = new(StringComparer.Ordinal); private readonly IConsoleLogProvider _provider; - private readonly IConsoleLogSourceRegistry _sourceRegistry; - private readonly IConsoleLogStreamingApiMapper _mapper; - private readonly IHubContext _hubContext; + private readonly IHubContext _hubContext; private readonly ILogger _logger; /// @@ -27,17 +20,12 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable /// public ElsaConsoleLogSubscriptionManager( IConsoleLogProvider provider, - IConsoleLogSourceRegistry sourceRegistry, - IConsoleLogStreamingApiMapper mapper, - IHubContext hubContext, + IHubContext hubContext, ILogger logger) { _provider = provider; - _sourceRegistry = sourceRegistry; - _mapper = mapper; _hubContext = hubContext; _logger = logger; - _sourceRegistry.SourceChanged += OnSourceChanged; } /// @@ -74,8 +62,6 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable /// public void Dispose() { - _sourceRegistry.SourceChanged -= OnSourceChanged; - foreach (var subscription in _subscriptions.Values) { subscription.CancellationTokenSource.Cancel(); @@ -89,13 +75,24 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable { try { - await foreach (var item in _provider.SubscribeAsync(_mapper.ToCore(ConsoleLogFilterMapper.ToStreamingFilter(filter)), cancellationToken).ConfigureAwait(false)) + string? lastSourceSignature = null; + + await foreach (var item in _provider.SubscribeAsync(ConsoleLogFilterMapper.ToStreamingFilter(filter), cancellationToken).ConfigureAwait(false)) { if (item.Line != null) - await _hubContext.Clients.Client(connectionId).ReceiveConsoleLogLineAsync(_mapper.ToApi(item.Line), cancellationToken).ConfigureAwait(false); + { + await _hubContext.Clients.Client(connectionId).ReceiveConsoleLogLineAsync(item.Line, cancellationToken).ConfigureAwait(false); + + var sourceSignature = GetSourceSignature(item.Line.Source); + if (!string.Equals(sourceSignature, lastSourceSignature, StringComparison.Ordinal)) + { + lastSourceSignature = sourceSignature; + await _hubContext.Clients.Client(connectionId).ReceiveSourceChangedAsync(item.Line.Source, cancellationToken).ConfigureAwait(false); + } + } if (item.Dropped != null) - await _hubContext.Clients.Client(connectionId).ReceiveDroppedLinesAsync(_mapper.ToApi(item.Dropped), cancellationToken).ConfigureAwait(false); + await _hubContext.Clients.Client(connectionId).ReceiveDroppedLinesAsync(item.Dropped, cancellationToken).ConfigureAwait(false); } } catch (OperationCanceledException e) @@ -128,36 +125,21 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable subscription.CancellationTokenSource.Dispose(); } - private void OnSourceChanged(CoreConsoleLogSource source) + private static string GetSourceSignature(ConsoleLogSource source) { - _ = BroadcastSourceChangedAsync(source, _subscriptions.ToArray()); - } + var metadata = source.Metadata + .OrderBy(x => x.Key, StringComparer.Ordinal) + .ThenBy(x => x.Value, StringComparer.Ordinal) + .Select(x => $"{x.Key}={x.Value}"); - private async Task BroadcastSourceChangedAsync(CoreConsoleLogSource source, IReadOnlyCollection> subscriptions) - { - try - { - foreach (var (connectionId, subscription) in subscriptions) - { - if (!MatchesSource(source, subscription.Filter)) - continue; - - await _hubContext.Clients.Client(connectionId).ReceiveSourceChangedAsync(_mapper.ToApi(source), subscription.CancellationTokenSource.Token).ConfigureAwait(false); - } - } - catch (OperationCanceledException e) - { - _logger.LogDebug(e, "Console log source change broadcast for source {SourceId} was canceled", source.Id); - } - catch (Exception e) when (e is not OperationCanceledException) - { - _logger.LogDebug(e, "Failed to broadcast console log source change for source {SourceId}", source.Id); - } - } - - private static bool MatchesSource(CoreConsoleLogSource source, ElsaConsoleLogFilter filter) - { - return string.IsNullOrWhiteSpace(filter.SourceId) || string.Equals(source.Id, filter.SourceId, StringComparison.OrdinalIgnoreCase); + return string.Join('\u001f', + source.Id, + source.DisplayName, + source.ServiceName, + source.ProcessId?.ToString(), + source.MachineName, + source.Health.ToString(), + string.Join('\u001e', metadata)); } private sealed record ConsoleLogSubscription(ElsaConsoleLogFilter Filter, CancellationTokenSource CancellationTokenSource); diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogsHub.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogsHub.cs index 592e619d1..a0fd23346 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogsHub.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogsHub.cs @@ -1,9 +1,6 @@ -using System.Runtime.CompilerServices; -using ConsoleLogStreaming.Contracts; using ConsoleLogStreaming.Core; -using ConsoleLogStreaming.SignalR; -using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Services; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; namespace Elsa.Diagnostics.ConsoleLogs.RealTime; @@ -11,11 +8,11 @@ namespace Elsa.Diagnostics.ConsoleLogs.RealTime; /// /// SignalR hub for live Elsa console log streaming. /// +[Authorize] public sealed class ElsaConsoleLogsHub( IConsoleLogProvider provider, - IConsoleLogStreamingApiMapper mapper, - IConsoleLogStreamingHubAuthorizer authorizer, - ElsaConsoleLogSubscriptionManager subscriptionManager) : Hub + IElsaConsoleLogHubAuthorizer authorizer, + ElsaConsoleLogSubscriptionManager subscriptionManager) : Hub { /// /// Streams matching console log items as a SignalR streaming method. @@ -27,8 +24,8 @@ public sealed class ElsaConsoleLogsHub( await EnsureCanReadAsync(cancellationToken).ConfigureAwait(false); filter = ValidateFilter(filter); - await foreach (var item in provider.SubscribeAsync(mapper.ToCore(ConsoleLogFilterMapper.ToStreamingFilter(filter)), cancellationToken).ConfigureAwait(false)) - yield return mapper.ToApi(item); + await foreach (var item in provider.SubscribeAsync(ConsoleLogFilterMapper.ToStreamingFilter(filter), cancellationToken).ConfigureAwait(false)) + yield return item; } /// @@ -80,3 +77,10 @@ public sealed class ElsaConsoleLogsHub( throw new HubException("Access denied."); } } + +public interface IElsaConsoleLogsClient +{ + Task ReceiveConsoleLogLineAsync(ConsoleLogLine line, CancellationToken cancellationToken = default); + Task ReceiveDroppedLinesAsync(ConsoleLogDroppedSummary summary, CancellationToken cancellationToken = default); + Task ReceiveSourceChangedAsync(ConsoleLogSource source, CancellationToken cancellationToken = default); +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureHostedService.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureHostedService.cs new file mode 100644 index 000000000..35d55f251 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureHostedService.cs @@ -0,0 +1,11 @@ +using ConsoleLogStreaming.Core; +using Microsoft.Extensions.Hosting; + +namespace Elsa.Diagnostics.ConsoleLogs.Services; + +internal sealed class ConsoleLogCaptureHostedService(IConsoleLogCapture capture) : IHostedService +{ + public Task StartAsync(CancellationToken cancellationToken) => capture.StartAsync(cancellationToken).AsTask(); + + public Task StopAsync(CancellationToken cancellationToken) => capture.StopAsync(cancellationToken).AsTask(); +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureShellLease.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureShellLease.cs new file mode 100644 index 000000000..e1464f6b1 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogCaptureShellLease.cs @@ -0,0 +1,69 @@ +using ConsoleLogStreaming.Core; +using ConsoleLogStreaming.Core.Capture; +using CShells.Lifecycle; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Diagnostics.ConsoleLogs.Services; + +public class ConsoleLogCaptureShellLease(IServiceProvider serviceProvider) +{ + private readonly SemaphoreSlim _lock = new(1, 1); + private bool _started; + + public async Task StartAsync(CancellationToken cancellationToken = default) + { + await _lock.WaitAsync(cancellationToken); + try + { + if (_started) + return; + + ConsoleLogStreamingHost.AddReference(); + var releaseReference = true; + + try + { + var capture = serviceProvider.GetRequiredService(); + await capture.StartAsync(cancellationToken); + _started = true; + releaseReference = false; + } + finally + { + if (releaseReference) + await ConsoleLogStreamingHost.ReleaseReferenceAsync(CancellationToken.None); + } + } + finally + { + _lock.Release(); + } + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + await _lock.WaitAsync(cancellationToken); + try + { + if (!_started) + return; + + _started = false; + await ConsoleLogStreamingHost.ReleaseReferenceAsync(cancellationToken); + } + finally + { + _lock.Release(); + } + } +} + +public class ConsoleLogCaptureShellInitializer(ConsoleLogCaptureShellLease lease) : IShellInitializer +{ + public Task InitializeAsync(CancellationToken cancellationToken = default) => lease.StartAsync(cancellationToken); +} + +public class ConsoleLogCaptureShellDrainHandler(ConsoleLogCaptureShellLease lease) : IDrainHandler +{ + public Task DrainAsync(IDrainExtensionHandle extensionHandle, CancellationToken cancellationToken) => lease.StopAsync(cancellationToken); +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessor.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessor.cs index dbe4b7fb8..c78ce367d 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessor.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessor.cs @@ -1,12 +1,9 @@ -using ConsoleLogStreaming.Core; -using Elsa.Diagnostics.ConsoleLogs.Contracts; - namespace Elsa.Diagnostics.ConsoleLogs.Services; /// /// Ambient console log context backed by the current async execution context. /// -public sealed class ConsoleLogContextAccessor : IConsoleLogContextAccessor, IConsoleLogMetadataAccessor +public sealed class ConsoleLogContextAccessor : IConsoleLogContextAccessor, ConsoleLogStreaming.Core.IConsoleLogMetadataAccessor { private static readonly AsyncLocal CurrentFrame = new(); private static readonly IReadOnlyDictionary Empty = new Dictionary(); diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessorExtensions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessorExtensions.cs index 7344aa62e..030f64b09 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessorExtensions.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogContextAccessorExtensions.cs @@ -1,5 +1,3 @@ -using Elsa.Diagnostics.ConsoleLogs.Contracts; - namespace Elsa.Diagnostics.ConsoleLogs.Services; internal static class ConsoleLogContextAccessorExtensions diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogFilterMapper.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogFilterMapper.cs index b07cbe4ac..562022783 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogFilterMapper.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ConsoleLogFilterMapper.cs @@ -1,6 +1,3 @@ -using ConsoleLogStreaming.Contracts; -using Elsa.Diagnostics.ConsoleLogs.Contracts; - namespace Elsa.Diagnostics.ConsoleLogs.Services; internal static class ConsoleLogFilterMapper diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogOptions.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogOptions.cs index e9ac0fa91..7c9b7519b 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogOptions.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogOptions.cs @@ -13,12 +13,14 @@ internal static class ElsaConsoleLogOptions options.SourceDisplayName = !string.IsNullOrWhiteSpace(podName) ? podName : sourceId; options.ServiceName = Environment.GetEnvironmentVariable("OTEL_SERVICE_NAME") ?? AppDomain.CurrentDomain.FriendlyName; options.PreserveAnsi = true; + options.RecentCapacity = 2_000; + options.MaxRecentQuerySize = 250; - SetMetadata(options, ConsoleLogStreamingApiMetadataKeys.KubernetesPodName, podName); - SetMetadata(options, ConsoleLogStreamingApiMetadataKeys.KubernetesNamespace, Environment.GetEnvironmentVariable("POD_NAMESPACE")); - SetMetadata(options, ConsoleLogStreamingApiMetadataKeys.ContainerName, Environment.GetEnvironmentVariable("CONTAINER_NAME")); - SetMetadata(options, ConsoleLogStreamingApiMetadataKeys.KubernetesNodeName, Environment.GetEnvironmentVariable("NODE_NAME")); - SetMetadata(options, ConsoleLogStreamingApiMetadataKeys.ProcessStartedAt, DateTimeOffset.UtcNow.ToString("O")); + SetMetadata(options, "kubernetes.pod.name", podName); + SetMetadata(options, "kubernetes.namespace.name", Environment.GetEnvironmentVariable("POD_NAMESPACE")); + SetMetadata(options, "container.name", Environment.GetEnvironmentVariable("CONTAINER_NAME")); + SetMetadata(options, "kubernetes.node.name", Environment.GetEnvironmentVariable("NODE_NAME")); + SetMetadata(options, "process.started_at", DateTimeOffset.UtcNow.ToString("O")); } private static void SetMetadata(ConsoleLogOptions options, string key, string? value) diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogProvider.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogProvider.cs new file mode 100644 index 000000000..f36e3b1a8 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogProvider.cs @@ -0,0 +1,110 @@ +using ConsoleLogStreaming.Core; + +namespace Elsa.Diagnostics.ConsoleLogs.Services; + +internal sealed class ElsaConsoleLogProvider( + IConsoleLogProvider inner, + IConsoleLogContextAccessor contextAccessor, + ElsaConsoleLogRecentBuffer recentBuffer) : IConsoleLogProvider, IDisposable, IAsyncDisposable +{ + private static readonly IReadOnlyDictionary EmptyMetadataFilter = new Dictionary(); + + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + var enrichedLine = Enrich(line); + recentBuffer.Add(enrichedLine); + return inner.PublishAsync(enrichedLine, cancellationToken); + } + + public async ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + if (!HasMetadataFilter(filter)) + return await inner.GetRecentAsync(filter, cancellationToken); + + var result = await inner.GetRecentAsync(filter with + { + Metadata = EmptyMetadataFilter + }, cancellationToken); + var items = recentBuffer.Query(filter); + + return result with { Items = items }; + } + + public async IAsyncEnumerable SubscribeAsync( + ConsoleLogFilter filter, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + if (!HasMetadataFilter(filter)) + { + await foreach (var item in inner.SubscribeAsync(filter, cancellationToken).ConfigureAwait(false)) + yield return item; + + yield break; + } + + await foreach (var item in inner.SubscribeAsync(filter with { Metadata = EmptyMetadataFilter }, cancellationToken).ConfigureAwait(false)) + { + if (item.Line != null && !MatchesMetadata(item.Line, filter.Metadata)) + continue; + + yield return item; + } + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return inner.ListSourcesAsync(cancellationToken); + } + + public void Dispose() + { + switch (inner) + { + case IDisposable disposable: + disposable.Dispose(); + break; + case IAsyncDisposable asyncDisposable: + asyncDisposable.DisposeAsync().AsTask().GetAwaiter().GetResult(); + break; + } + } + + public async ValueTask DisposeAsync() + { + switch (inner) + { + case IAsyncDisposable asyncDisposable: + await asyncDisposable.DisposeAsync(); + break; + case IDisposable disposable: + disposable.Dispose(); + break; + } + } + + private ConsoleLogLine Enrich(ConsoleLogLine line) + { + var ambientMetadata = contextAccessor.GetMetadata(); + if (ambientMetadata.Count == 0) + return line; + + var metadata = new Dictionary(line.Metadata, StringComparer.OrdinalIgnoreCase); + foreach (var item in ambientMetadata) + metadata[item.Key] = item.Value; + + return line with { Metadata = metadata }; + } + + private static bool HasMetadataFilter(ConsoleLogFilter filter) => filter.Metadata.Count > 0; + + private static bool MatchesMetadata(ConsoleLogLine line, IReadOnlyDictionary metadata) + { + foreach (var (key, value) in metadata) + { + if (!line.Metadata.TryGetValue(key, out var candidate) || !string.Equals(candidate, value, StringComparison.OrdinalIgnoreCase)) + return false; + } + + return true; + } +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogRecentBuffer.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogRecentBuffer.cs new file mode 100644 index 000000000..38f050765 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogRecentBuffer.cs @@ -0,0 +1,69 @@ +using ConsoleLogStreaming.Core.Options; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.ConsoleLogs.Services; + +internal sealed class ElsaConsoleLogRecentBuffer +{ + private readonly object _lock = new(); + private readonly Queue _lines = new(); + private readonly int _capacity; + private readonly int _maxQuerySize; + + public ElsaConsoleLogRecentBuffer(IOptions options) + { + _capacity = Math.Max(1, options.Value.RecentCapacity); + _maxQuerySize = Math.Max(1, options.Value.MaxRecentQuerySize); + } + + public void Add(ConsoleLogLine line) + { + lock (_lock) + { + _lines.Enqueue(line); + + while (_lines.Count > _capacity) + _lines.Dequeue(); + } + } + + public IReadOnlyList Query(ConsoleLogFilter filter) + { + ConsoleLogLine[] snapshot; + + lock (_lock) + snapshot = _lines.ToArray(); + + var limit = filter.Limit is > 0 ? Math.Min(filter.Limit.Value, _maxQuerySize) : _maxQuerySize; + return snapshot + .Where(line => Matches(line, filter)) + .TakeLast(limit) + .ToArray(); + } + + private static bool Matches(ConsoleLogLine line, ConsoleLogFilter filter) + { + if (!string.IsNullOrWhiteSpace(filter.SourceId) && !string.Equals(line.Source.Id, filter.SourceId, StringComparison.OrdinalIgnoreCase)) + return false; + + if (filter.Stream.HasValue && line.Stream != filter.Stream.Value) + return false; + + if (!string.IsNullOrWhiteSpace(filter.Query) && !line.Text.Contains(filter.Query, StringComparison.OrdinalIgnoreCase)) + return false; + + if (filter.From.HasValue && line.ReceivedAt < filter.From.Value) + return false; + + if (filter.To.HasValue && line.ReceivedAt > filter.To.Value) + return false; + + foreach (var (key, value) in filter.Metadata) + { + if (!line.Metadata.TryGetValue(key, out var candidate) || !string.Equals(candidate, value, StringComparison.OrdinalIgnoreCase)) + return false; + } + + return true; + } +} diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogStreamHubAuthorizer.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogStreamHubAuthorizer.cs index 2961c06a4..f08da4b89 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogStreamHubAuthorizer.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Services/ElsaConsoleLogStreamHubAuthorizer.cs @@ -1,11 +1,15 @@ -using ConsoleLogStreaming.SignalR; using Elsa.Diagnostics.ConsoleLogs.Permissions; using FastEndpoints.Security; using Microsoft.AspNetCore.SignalR; namespace Elsa.Diagnostics.ConsoleLogs.Services; -public sealed class ElsaConsoleLogStreamingHubAuthorizer : IConsoleLogStreamingHubAuthorizer +public interface IElsaConsoleLogHubAuthorizer +{ + ValueTask CanReadAsync(HubCallerContext context, CancellationToken cancellationToken = default); +} + +public sealed class ElsaConsoleLogStreamHubAuthorizer : IElsaConsoleLogHubAuthorizer { private const string ReadAllPermission = "read:*"; private static readonly string[] ReadPermissions = [PermissionNames.All, ReadAllPermission, ConsoleLogsPermissions.Read]; diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/ShellFeatures/ConsoleLogsFeature.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/ShellFeatures/ConsoleLogsFeature.cs index ada74e6f4..955c8ec42 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/ShellFeatures/ConsoleLogsFeature.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/ShellFeatures/ConsoleLogsFeature.cs @@ -24,14 +24,11 @@ public class ConsoleLogsFeature : IFastEndpointsShellFeature, IWebShellFeature public int RecentLogCapacity { get; set; } = DefaultOptions.RecentCapacity; public int SubscriberChannelCapacity { get; set; } = DefaultOptions.SubscriberCapacity; - public int CaptureChannelCapacity { get; set; } = DefaultOptions.CaptureChannelCapacity; public int MaxRecentQuerySize { get; set; } = DefaultOptions.MaxRecentQuerySize; public int MaxLineLength { get; set; } = DefaultOptions.MaxLineLength; public TimeSpan IdleFlushTimeout { get; set; } = DefaultOptions.IdleFlushTimeout; public bool StripAnsiEscapeSequences { get; set; } = !DefaultOptions.PreserveAnsi; - public TimeSpan SourceHeartbeatTimeout { get; set; } = DefaultOptions.SourceHeartbeatTimeout; - public string RedactionReplacement { get; set; } = DefaultOptions.RedactionReplacement; - public ICollection SensitiveNames { get; set; } = [..DefaultOptions.SensitiveNames]; + public string RedactionReplacement { get; set; } = "[Redacted]"; public ICollection SensitiveTextPatterns { get; set; } = [..DefaultOptions.RedactionRules.Select(x => x.Pattern)]; public void ConfigureServices(IServiceCollection services) @@ -48,14 +45,10 @@ public class ConsoleLogsFeature : IFastEndpointsShellFeature, IWebShellFeature { options.RecentCapacity = RecentLogCapacity; options.SubscriberCapacity = SubscriberChannelCapacity; - options.CaptureChannelCapacity = CaptureChannelCapacity; options.MaxRecentQuerySize = MaxRecentQuerySize; options.MaxLineLength = MaxLineLength; options.IdleFlushTimeout = IdleFlushTimeout; options.PreserveAnsi = !StripAnsiEscapeSequences; - options.SourceHeartbeatTimeout = SourceHeartbeatTimeout; - options.RedactionReplacement = RedactionReplacement; - options.SensitiveNames = [..SensitiveNames]; options.RedactionRules.Clear(); foreach (var pattern in SensitiveTextPatterns) { diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Usings.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Usings.cs index 0fd2c0638..42fc132f3 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Usings.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Usings.cs @@ -1,5 +1,5 @@ global using System.Runtime.CompilerServices; -global using ConsoleLogStreaming.Contracts; +global using ConsoleLogStreaming.Core.Models; global using Elsa.Diagnostics.ConsoleLogs.Contracts; global using Elsa.Workflows; global using Elsa.Workflows.Pipelines.ActivityExecution; diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/AssemblyInfo.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/AssemblyInfo.cs new file mode 100644 index 000000000..479bbcf0f --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Elsa.Diagnostics.OpenTelemetry.UnitTests")] diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/ICollectorConfigurationProvider.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/ICollectorConfigurationProvider.cs new file mode 100644 index 000000000..82d810f19 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/ICollectorConfigurationProvider.cs @@ -0,0 +1,8 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface ICollectorConfigurationProvider +{ + ValueTask GetAsync(CancellationToken cancellationToken = default); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryIngestor.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryIngestor.cs new file mode 100644 index 000000000..ebe0b2037 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryIngestor.cs @@ -0,0 +1,8 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface IOpenTelemetryIngestor +{ + ValueTask IngestAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryLiveFeed.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryLiveFeed.cs new file mode 100644 index 000000000..24148cdb1 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryLiveFeed.cs @@ -0,0 +1,9 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface IOpenTelemetryLiveFeed +{ + ValueTask PublishAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default); + IAsyncEnumerable SubscribeAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryProvider.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryProvider.cs new file mode 100644 index 000000000..7a2e18b00 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryProvider.cs @@ -0,0 +1,14 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface IOpenTelemetryProvider +{ + ValueTask GetResourcesAsync(OpenTelemetryResourceFilter filter, CancellationToken cancellationToken = default); + ValueTask GetTracesAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default); + ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default); + ValueTask GetMetricsAsync(OpenTelemetryMetricFilter filter, CancellationToken cancellationToken = default); + ValueTask GetLogsAsync(OpenTelemetryLogFilter filter, CancellationToken cancellationToken = default); + ValueTask GetStorageDiagnosticsAsync(CancellationToken cancellationToken = default); + ValueTask GetCollectorConfigurationAsync(CancellationToken cancellationToken = default); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryRedactor.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryRedactor.cs new file mode 100644 index 000000000..a97f6a04e --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryRedactor.cs @@ -0,0 +1,8 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface IOpenTelemetryRedactor +{ + OpenTelemetryBatch Redact(OpenTelemetryBatch batch); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetrySourceRegistry.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetrySourceRegistry.cs new file mode 100644 index 000000000..9e314c138 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetrySourceRegistry.cs @@ -0,0 +1,10 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface IOpenTelemetrySourceRegistry +{ + long DroppedCount { get; } + void MarkSeen(TelemetryResource resource); + IReadOnlyCollection List(); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryStore.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryStore.cs new file mode 100644 index 000000000..2fac67706 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Contracts/IOpenTelemetryStore.cs @@ -0,0 +1,14 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Contracts; + +public interface IOpenTelemetryStore +{ + ValueTask WriteAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default); + ValueTask QueryResourcesAsync(OpenTelemetryResourceFilter filter, CancellationToken cancellationToken = default); + ValueTask QueryTracesAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default); + ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default); + ValueTask QueryMetricsAsync(OpenTelemetryMetricFilter filter, CancellationToken cancellationToken = default); + ValueTask QueryLogsAsync(OpenTelemetryLogFilter filter, CancellationToken cancellationToken = default); + ValueTask GetDiagnosticsAsync(CancellationToken cancellationToken = default); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj b/src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj new file mode 100644 index 000000000..5341fb4cf --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj @@ -0,0 +1,16 @@ + + + + Provides OpenTelemetry diagnostics collection and query services for Elsa hosts. + elsa module diagnostics opentelemetry otel otlp signalr operations + + + + + + + + + + + diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/CollectorConfiguration/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/CollectorConfiguration/Endpoint.cs new file mode 100644 index 000000000..18816c5fa --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/CollectorConfiguration/Endpoint.cs @@ -0,0 +1,22 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.CollectorConfiguration; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpointWithoutRequest +{ + public override void Configure() + { + Get("/diagnostics/opentelemetry/collector-configuration"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task ExecuteAsync(CancellationToken cancellationToken) + { + return await provider.GetCollectorConfigurationAsync(cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Logs/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Logs/Endpoint.cs new file mode 100644 index 000000000..edb27a692 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Logs/Endpoint.cs @@ -0,0 +1,22 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Logs; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpoint +{ + public override void Configure() + { + Post("/diagnostics/opentelemetry/logs/search"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task ExecuteAsync(OpenTelemetryLogFilter request, CancellationToken cancellationToken) + { + return await provider.GetLogsAsync(request, cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Metrics/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Metrics/Endpoint.cs new file mode 100644 index 000000000..ddf444163 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Metrics/Endpoint.cs @@ -0,0 +1,22 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Metrics; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpoint +{ + public override void Configure() + { + Post("/diagnostics/opentelemetry/metrics/search"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task ExecuteAsync(OpenTelemetryMetricFilter request, CancellationToken cancellationToken) + { + return await provider.GetMetricsAsync(request, cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Resources/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Resources/Endpoint.cs new file mode 100644 index 000000000..a38052b04 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Resources/Endpoint.cs @@ -0,0 +1,22 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Resources; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpoint +{ + public override void Configure() + { + Post("/diagnostics/opentelemetry/resources/search"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task ExecuteAsync(OpenTelemetryResourceFilter request, CancellationToken cancellationToken) + { + return await provider.GetResourcesAsync(request, cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Storage/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Storage/Endpoint.cs new file mode 100644 index 000000000..e946aebcf --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Storage/Endpoint.cs @@ -0,0 +1,22 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Storage; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpointWithoutRequest +{ + public override void Configure() + { + Get("/diagnostics/opentelemetry/storage"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task ExecuteAsync(CancellationToken cancellationToken) + { + return await provider.GetStorageDiagnosticsAsync(cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Trace/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Trace/Endpoint.cs new file mode 100644 index 000000000..c919503a6 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Trace/Endpoint.cs @@ -0,0 +1,29 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Trace; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpointWithoutRequest +{ + public override void Configure() + { + Get("/diagnostics/opentelemetry/traces/{traceId}"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task HandleAsync(CancellationToken cancellationToken) + { + var trace = await provider.GetTraceAsync(Route("traceId")!, cancellationToken); + if (trace == null) + { + await Send.NotFoundAsync(cancellationToken); + return; + } + + await Send.OkAsync(trace, cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Traces/Endpoint.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Traces/Endpoint.cs new file mode 100644 index 000000000..63056b4f0 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Endpoints/OpenTelemetry/Traces/Endpoint.cs @@ -0,0 +1,22 @@ +using Elsa.Abstractions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using JetBrains.Annotations; + +namespace Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Traces; + +[PublicAPI] +internal class Endpoint(IOpenTelemetryProvider provider) : ElsaEndpoint +{ + public override void Configure() + { + Post("/diagnostics/opentelemetry/traces/search"); + ConfigurePermissions(OpenTelemetryPermissions.Read); + } + + public override async Task ExecuteAsync(OpenTelemetryTraceFilter request, CancellationToken cancellationToken) + { + return await provider.GetTracesAsync(request, cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/EndpointRouteBuilderExtensions.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/EndpointRouteBuilderExtensions.cs new file mode 100644 index 000000000..ba497335c --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/EndpointRouteBuilderExtensions.cs @@ -0,0 +1,114 @@ +using System.Buffers; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Ingestion; +using Elsa.Diagnostics.OpenTelemetry.Ingestion.HttpProtobuf; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.RealTime; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.Extensions; + +public static class EndpointRouteBuilderExtensions +{ + public const string DefaultHubRoute = "/elsa/hubs/diagnostics/opentelemetry"; + + public static void MapOpenTelemetryHub(this IEndpointRouteBuilder endpoints) + { + var options = endpoints.ServiceProvider.GetRequiredService>().Value; + endpoints.MapHub(string.IsNullOrWhiteSpace(options.HubRoute) ? DefaultHubRoute : options.HubRoute); + } + + public static void MapOpenTelemetryHttpProtobufCollector(this IEndpointRouteBuilder endpoints) + { + var options = endpoints.ServiceProvider.GetRequiredService>().Value; + var basePath = (string.IsNullOrWhiteSpace(options.HttpEndpointPath) ? "/elsa/otlp/v1" : options.HttpEndpointPath).TrimEnd('/'); + + endpoints.MapPost($"{basePath}/traces", static async (HttpContext httpContext, IOpenTelemetryIngestor ingestor, IOptions options, CancellationToken cancellationToken) => + { + return await IngestAsync(httpContext, ingestor, options, payload => OtlpHttpProtobufParser.ParseTraces(payload.Span), cancellationToken); + }); + + endpoints.MapPost($"{basePath}/metrics", static async (HttpContext httpContext, IOpenTelemetryIngestor ingestor, IOptions options, CancellationToken cancellationToken) => + { + return await IngestAsync(httpContext, ingestor, options, payload => OtlpHttpProtobufParser.ParseMetrics(payload.Span), cancellationToken); + }); + + endpoints.MapPost($"{basePath}/logs", static async (HttpContext httpContext, IOpenTelemetryIngestor ingestor, IOptions options, CancellationToken cancellationToken) => + { + return await IngestAsync(httpContext, ingestor, options, payload => OtlpHttpProtobufParser.ParseLogs(payload.Span), cancellationToken); + }); + } + + public static void MapOpenTelemetryGrpcCollector(this IEndpointRouteBuilder endpoints) + { + var options = endpoints.ServiceProvider.GetRequiredService>().Value; + + if (!options.EnableGrpc) + return; + + if (string.IsNullOrWhiteSpace(options.GrpcEndpointPath)) + throw new InvalidOperationException("OpenTelemetry gRPC ingestion is enabled, but no gRPC endpoint path was configured."); + + // The actual gRPC service binding is host-specific. This module exposes shared ingestion + // contracts and accurate collector metadata without forcing every host to reference gRPC. + } + + private static async Task IngestAsync( + HttpContext httpContext, + IOpenTelemetryIngestor ingestor, + IOptions options, + Func, OpenTelemetryBatch> parse, + CancellationToken cancellationToken) + { + if (!OtlpIngestionSecurity.IsAuthorized(httpContext, options.Value)) + return Results.Unauthorized(); + + try + { + var payload = await ReadBodyAsync(httpContext, options.Value.MaxHttpRequestBodySize, cancellationToken); + await ingestor.IngestAsync(parse(payload), cancellationToken); + return Results.Ok(); + } + catch (RequestBodyTooLargeException) + { + return Results.StatusCode(StatusCodes.Status413PayloadTooLarge); + } + catch (InvalidDataException) + { + return Results.BadRequest(); + } + } + + private static async Task> ReadBodyAsync(HttpContext httpContext, long maxBodySize, CancellationToken cancellationToken) + { + using var stream = new MemoryStream(); + var buffer = ArrayPool.Shared.Rent(81920); + var totalBytes = 0L; + + try + { + int read; + while ((read = await httpContext.Request.Body.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken)) > 0) + { + totalBytes += read; + if (totalBytes > maxBodySize) + throw new RequestBodyTooLargeException(); + + stream.Write(buffer, 0, read); + } + } + finally + { + ArrayPool.Shared.Return(buffer); + } + + return stream.ToArray(); + } + + private sealed class RequestBodyTooLargeException : Exception; +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ModuleExtensions.cs new file mode 100644 index 000000000..d36a113c2 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ModuleExtensions.cs @@ -0,0 +1,14 @@ +using Elsa.Diagnostics.OpenTelemetry.Features; +using Elsa.Features.Services; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +public static class OpenTelemetryDiagnosticsModuleExtensions +{ + public static IModule UseOpenTelemetryDiagnostics(this IModule module, Action? configure = null) + { + module.Configure(configure); + return module; + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ServiceCollectionExtensions.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..e2580549b --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,33 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; +using Elsa.Diagnostics.OpenTelemetry.RealTime; +using Elsa.Diagnostics.OpenTelemetry.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Elsa.Diagnostics.OpenTelemetry.Extensions; + +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddOpenTelemetryDiagnosticsServices(this IServiceCollection services, Action? configureOptions = null) + { + if (configureOptions != null) + services.Configure(configureOptions); + + services.AddSignalR(); + services.AddOptions(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(sp => sp.GetRequiredService()); + services.TryAddSingleton(); + services.TryAddSingleton(sp => sp.GetRequiredService()); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + + return services; + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Features/OpenTelemetryFeature.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Features/OpenTelemetryFeature.cs new file mode 100644 index 000000000..2356e7331 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Features/OpenTelemetryFeature.cs @@ -0,0 +1,23 @@ +using Elsa.Diagnostics.OpenTelemetry.Extensions; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Extensions; +using Elsa.Features.Abstractions; +using Elsa.Features.Services; + +namespace Elsa.Diagnostics.OpenTelemetry.Features; + +public class OpenTelemetryFeature(IModule module) : FeatureBase(module) +{ + public Action? ConfigureOptions { get; set; } + + public override void Configure() + { + Module.AddFastEndpointsAssembly(); + } + + public override void Apply() + { + Services.AddOpenTelemetryDiagnosticsServices(ConfigureOptions); + Module.AddFastEndpointsFromModule(); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/FodyWeavers.xml b/src/modules/Elsa.Diagnostics.OpenTelemetry/FodyWeavers.xml new file mode 100644 index 000000000..535dce765 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/HttpProtobuf/OtlpHttpProtobufParser.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/HttpProtobuf/OtlpHttpProtobufParser.cs new file mode 100644 index 000000000..7cffcebe4 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/HttpProtobuf/OtlpHttpProtobufParser.cs @@ -0,0 +1,701 @@ +using System.Buffers.Binary; +using System.Globalization; +using System.Text; +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Ingestion.HttpProtobuf; + +internal static class OtlpHttpProtobufParser +{ + public static OpenTelemetryBatch ParseTraces(ReadOnlySpan payload) + { + var resources = new List(); + var spans = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number != 1 || field.WireType != ProtobufWireType.LengthDelimited) + continue; + + var resourceSpans = ParseResourceSpans(field.Bytes); + resources.Add(resourceSpans.Resource); + spans.AddRange(resourceSpans.Spans); + } + + return CreateBatch(resources, spans, [], [], []); + } + + public static OpenTelemetryBatch ParseMetrics(ReadOnlySpan payload) + { + var resources = new List(); + var instruments = new Dictionary(StringComparer.OrdinalIgnoreCase); + var points = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number != 1 || field.WireType != ProtobufWireType.LengthDelimited) + continue; + + var resourceMetrics = ParseResourceMetrics(field.Bytes); + resources.Add(resourceMetrics.Resource); + + foreach (var instrument in resourceMetrics.Instruments) + instruments[instrument.Id] = instrument; + + points.AddRange(resourceMetrics.Points); + } + + return CreateBatch(resources, [], instruments.Values.ToList(), points, []); + } + + public static OpenTelemetryBatch ParseLogs(ReadOnlySpan payload) + { + var resources = new List(); + var logs = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number != 1 || field.WireType != ProtobufWireType.LengthDelimited) + continue; + + var resourceLogs = ParseResourceLogs(field.Bytes); + resources.Add(resourceLogs.Resource); + logs.AddRange(resourceLogs.Logs); + } + + return CreateBatch(resources, [], [], [], logs); + } + + private static (TelemetryResource Resource, List Spans) ParseResourceSpans(ReadOnlySpan payload) + { + var resource = CreateResource(new Dictionary()); + var spans = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.WireType != ProtobufWireType.LengthDelimited) + continue; + + if (field.Number == 1) + resource = CreateResource(ParseResourceAttributes(field.Bytes)); + else if (field.Number == 2) + spans.AddRange(ParseScopeSpans(field.Bytes, resource.Id)); + } + + return (resource, spans); + } + + private static List ParseScopeSpans(ReadOnlySpan payload, string resourceId) + { + var spans = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 2 && field.WireType == ProtobufWireType.LengthDelimited) + spans.Add(ParseSpan(field.Bytes, resourceId)); + } + + return spans; + } + + private static TelemetrySpan ParseSpan(ReadOnlySpan payload, string resourceId) + { + var traceId = ""; + var spanId = ""; + string? parentSpanId = null; + var name = ""; + var kind = "unspecified"; + var start = DateTimeOffset.UnixEpoch; + var end = DateTimeOffset.UnixEpoch; + var status = SpanStatus.Unset; + string? statusDescription = null; + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var events = new List(); + var links = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + switch (field.Number) + { + case 1 when field.WireType == ProtobufWireType.LengthDelimited: + traceId = ToHex(field.Bytes); + break; + case 2 when field.WireType == ProtobufWireType.LengthDelimited: + spanId = ToHex(field.Bytes); + break; + case 4 when field.WireType == ProtobufWireType.LengthDelimited: + parentSpanId = ToHex(field.Bytes); + break; + case 5 when field.WireType == ProtobufWireType.LengthDelimited: + name = field.StringValue(); + break; + case 6: + kind = SpanKindName(field.Varint); + break; + case 7: + start = FromUnixNanos(field.Varint); + break; + case 8: + end = FromUnixNanos(field.Varint); + break; + case 9 when field.WireType == ProtobufWireType.LengthDelimited: + AddAttribute(attributes, field.Bytes); + break; + case 11 when field.WireType == ProtobufWireType.LengthDelimited: + events.Add(ParseSpanEvent(field.Bytes)); + break; + case 12 when field.WireType == ProtobufWireType.LengthDelimited: + links.Add(ParseSpanLink(field.Bytes)); + break; + case 15 when field.WireType == ProtobufWireType.LengthDelimited: + (status, statusDescription) = ParseSpanStatus(field.Bytes); + break; + } + } + + if (end < start) + end = start; + + return new TelemetrySpan($"{traceId}:{spanId}", traceId, spanId, parentSpanId, resourceId, name, kind, start, end, status, statusDescription, attributes, events, links); + } + + private static TelemetrySpanEvent ParseSpanEvent(ReadOnlySpan payload) + { + var timestamp = DateTimeOffset.UnixEpoch; + var name = ""; + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 1) + timestamp = FromUnixNanos(field.Varint); + else if (field.Number == 2 && field.WireType == ProtobufWireType.LengthDelimited) + name = field.StringValue(); + else if (field.Number == 3 && field.WireType == ProtobufWireType.LengthDelimited) + AddAttribute(attributes, field.Bytes); + } + + return new TelemetrySpanEvent(name, timestamp, attributes); + } + + private static TelemetrySpanLink ParseSpanLink(ReadOnlySpan payload) + { + var traceId = ""; + var spanId = ""; + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 1 && field.WireType == ProtobufWireType.LengthDelimited) + traceId = ToHex(field.Bytes); + else if (field.Number == 2 && field.WireType == ProtobufWireType.LengthDelimited) + spanId = ToHex(field.Bytes); + else if (field.Number == 3 && field.WireType == ProtobufWireType.LengthDelimited) + AddAttribute(attributes, field.Bytes); + } + + return new TelemetrySpanLink(traceId, spanId, attributes); + } + + private static (SpanStatus Status, string? Description) ParseSpanStatus(ReadOnlySpan payload) + { + var status = SpanStatus.Unset; + string? description = null; + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 2 && field.WireType == ProtobufWireType.LengthDelimited) + description = field.StringValue(); + else if (field.Number == 3) + status = field.Varint switch + { + 1 => SpanStatus.Ok, + 2 => SpanStatus.Error, + _ => SpanStatus.Unset + }; + } + + return (status, description); + } + + private static (TelemetryResource Resource, List Instruments, List Points) ParseResourceMetrics(ReadOnlySpan payload) + { + var resource = CreateResource(new Dictionary()); + var instruments = new List(); + var points = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.WireType != ProtobufWireType.LengthDelimited) + continue; + + if (field.Number == 1) + resource = CreateResource(ParseResourceAttributes(field.Bytes)); + else if (field.Number == 2) + ParseScopeMetrics(field.Bytes, resource.Id, instruments, points); + } + + return (resource, instruments, points); + } + + private static void ParseScopeMetrics(ReadOnlySpan payload, string resourceId, ICollection instruments, ICollection points) + { + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number != 2 || field.WireType != ProtobufWireType.LengthDelimited) + continue; + + var metric = ParseMetric(field.Bytes, resourceId); + instruments.Add(metric.Instrument); + + foreach (var point in metric.Points) + points.Add(point); + } + } + + private static (MetricInstrument Instrument, List Points) ParseMetric(ReadOnlySpan payload, string resourceId) + { + var name = ""; + string? description = null; + string? unit = null; + var kind = MetricKind.Gauge; + var points = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + switch (field.Number) + { + case 1 when field.WireType == ProtobufWireType.LengthDelimited: + name = field.StringValue(); + break; + case 2 when field.WireType == ProtobufWireType.LengthDelimited: + description = field.StringValue(); + break; + case 3 when field.WireType == ProtobufWireType.LengthDelimited: + unit = field.StringValue(); + break; + case 5 when field.WireType == ProtobufWireType.LengthDelimited: + kind = MetricKind.Gauge; + points.AddRange(ParseNumberDataPoints(field.Bytes, resourceId, () => $"{resourceId}:{name}:gauge")); + break; + case 7 when field.WireType == ProtobufWireType.LengthDelimited: + kind = MetricKind.Sum; + points.AddRange(ParseNumberDataPoints(field.Bytes, resourceId, () => $"{resourceId}:{name}:sum")); + break; + case 9 when field.WireType == ProtobufWireType.LengthDelimited: + kind = MetricKind.Histogram; + points.AddRange(ParseHistogramDataPoints(field.Bytes, resourceId, () => $"{resourceId}:{name}:histogram")); + break; + } + } + + var instrumentId = $"{resourceId}:{name}:{kind.ToString().ToLowerInvariant()}"; + var instrument = new MetricInstrument(instrumentId, resourceId, name, unit, description, kind, new Dictionary()); + points = points.Select(x => x with { InstrumentId = instrumentId, InstrumentName = name }).ToList(); + return (instrument, points); + } + + private static List ParseNumberDataPoints(ReadOnlySpan payload, string resourceId, Func instrumentIdFactory) + { + var points = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 1 && field.WireType == ProtobufWireType.LengthDelimited) + points.Add(ParseNumberDataPoint(field.Bytes, resourceId, instrumentIdFactory())); + } + + return points; + } + + private static MetricPoint ParseNumberDataPoint(ReadOnlySpan payload, string resourceId, string instrumentId) + { + var timestamp = DateTimeOffset.UnixEpoch; + double? value = null; + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 3) + timestamp = FromUnixNanos(field.Varint); + else if (field.Number == 4 && field.WireType == ProtobufWireType.Fixed64) + value = field.DoubleValue; + else if (field.Number == 6) + value = (long)field.Varint; + else if (field.Number == 7 && field.WireType == ProtobufWireType.LengthDelimited) + AddAttribute(attributes, field.Bytes); + } + + return new MetricPoint(Guid.NewGuid().ToString("N"), instrumentId, "", resourceId, timestamp, value, null, null, attributes, null, null); + } + + private static List ParseHistogramDataPoints(ReadOnlySpan payload, string resourceId, Func instrumentIdFactory) + { + var points = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 1 && field.WireType == ProtobufWireType.LengthDelimited) + points.Add(ParseHistogramDataPoint(field.Bytes, resourceId, instrumentIdFactory())); + } + + return points; + } + + private static MetricPoint ParseHistogramDataPoint(ReadOnlySpan payload, string resourceId, string instrumentId) + { + var timestamp = DateTimeOffset.UnixEpoch; + long? count = null; + double? sum = null; + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 3) + timestamp = FromUnixNanos(field.Varint); + else if (field.Number == 4) + count = (long)field.Varint; + else if (field.Number == 5 && field.WireType == ProtobufWireType.Fixed64) + sum = field.DoubleValue; + else if (field.Number == 9 && field.WireType == ProtobufWireType.LengthDelimited) + AddAttribute(attributes, field.Bytes); + } + + return new MetricPoint(Guid.NewGuid().ToString("N"), instrumentId, "", resourceId, timestamp, null, sum, count, attributes, null, null); + } + + private static (TelemetryResource Resource, List Logs) ParseResourceLogs(ReadOnlySpan payload) + { + var resource = CreateResource(new Dictionary()); + var logs = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.WireType != ProtobufWireType.LengthDelimited) + continue; + + if (field.Number == 1) + resource = CreateResource(ParseResourceAttributes(field.Bytes)); + else if (field.Number == 2) + logs.AddRange(ParseScopeLogs(field.Bytes, resource.Id)); + } + + return (resource, logs); + } + + private static List ParseScopeLogs(ReadOnlySpan payload, string resourceId) + { + var logs = new List(); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 2 && field.WireType == ProtobufWireType.LengthDelimited) + logs.Add(ParseLogRecord(field.Bytes, resourceId)); + } + + return logs; + } + + private static OtlpLogRecord ParseLogRecord(ReadOnlySpan payload, string resourceId) + { + var timestamp = DateTimeOffset.UnixEpoch; + var severityText = ""; + int? severityNumber = null; + var body = ""; + string? traceId = null; + string? spanId = null; + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + switch (field.Number) + { + case 1: + timestamp = FromUnixNanos(field.Varint); + break; + case 2: + severityNumber = (int)field.Varint; + break; + case 3 when field.WireType == ProtobufWireType.LengthDelimited: + severityText = field.StringValue(); + break; + case 5 when field.WireType == ProtobufWireType.LengthDelimited: + body = ParseAnyValue(field.Bytes) ?? ""; + break; + case 6 when field.WireType == ProtobufWireType.LengthDelimited: + AddAttribute(attributes, field.Bytes); + break; + case 9 when field.WireType == ProtobufWireType.LengthDelimited: + traceId = ToHex(field.Bytes); + break; + case 10 when field.WireType == ProtobufWireType.LengthDelimited: + spanId = ToHex(field.Bytes); + break; + } + } + + if (string.IsNullOrWhiteSpace(severityText) && severityNumber != null) + severityText = SeverityName(severityNumber.Value); + + return new OtlpLogRecord(Guid.NewGuid().ToString("N"), resourceId, timestamp, severityText, severityNumber, body, traceId, spanId, attributes); + } + + private static Dictionary ParseResourceAttributes(ReadOnlySpan payload) + { + var attributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 1 && field.WireType == ProtobufWireType.LengthDelimited) + AddAttribute(attributes, field.Bytes); + } + + return attributes; + } + + private static void AddAttribute(IDictionary attributes, ReadOnlySpan payload) + { + string? key = null; + string? value = null; + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + if (field.Number == 1 && field.WireType == ProtobufWireType.LengthDelimited) + key = field.StringValue(); + else if (field.Number == 2 && field.WireType == ProtobufWireType.LengthDelimited) + value = ParseAnyValue(field.Bytes); + } + + if (!string.IsNullOrWhiteSpace(key)) + attributes[key] = value; + } + + private static string? ParseAnyValue(ReadOnlySpan payload) + { + var reader = new ProtobufReader(payload); + + while (reader.TryReadField(out var field)) + { + return field.Number switch + { + 1 when field.WireType == ProtobufWireType.LengthDelimited => field.StringValue(), + 2 => field.Varint != 0 ? "true" : "false", + 3 => ((long)field.Varint).ToString(CultureInfo.InvariantCulture), + 4 when field.WireType == ProtobufWireType.Fixed64 => field.DoubleValue.ToString(CultureInfo.InvariantCulture), + 7 when field.WireType == ProtobufWireType.LengthDelimited => ToHex(field.Bytes), + _ => null + }; + } + + return null; + } + + private static TelemetryResource CreateResource(IDictionary attributes) + { + var serviceName = GetAttribute(attributes, "service.name") ?? "unknown_service"; + var instanceId = GetAttribute(attributes, "service.instance.id"); + var resourceId = string.IsNullOrWhiteSpace(instanceId) ? serviceName : $"{serviceName}:{instanceId}"; + return new TelemetryResource(resourceId, serviceName, instanceId, GetAttribute(attributes, "telemetry.sdk.language"), new Dictionary(attributes, StringComparer.OrdinalIgnoreCase), DateTimeOffset.UtcNow, TelemetryResourceStatus.Active); + } + + private static OpenTelemetryBatch CreateBatch( + IReadOnlyCollection resources, + IReadOnlyCollection spans, + IReadOnlyCollection instruments, + IReadOnlyCollection points, + IReadOnlyCollection logs) + { + var traces = spans + .GroupBy(x => x.TraceId, StringComparer.OrdinalIgnoreCase) + .Select(CreateTrace) + .ToList(); + + return new OpenTelemetryBatch(resources.DistinctBy(x => x.Id).ToList(), traces, spans.ToList(), instruments.ToList(), points.ToList(), logs.ToList()); + } + + private static TelemetryTrace CreateTrace(IGrouping spans) + { + var orderedSpans = spans.OrderBy(x => x.StartTime).ToList(); + var root = orderedSpans.FirstOrDefault(x => string.IsNullOrWhiteSpace(x.ParentSpanId)) ?? orderedSpans[0]; + var start = orderedSpans.Min(x => x.StartTime); + var end = orderedSpans.Max(x => x.EndTime); + var status = orderedSpans.Any(x => x.Status == SpanStatus.Error) ? SpanStatus.Error : orderedSpans.Any(x => x.Status == SpanStatus.Ok) ? SpanStatus.Ok : SpanStatus.Unset; + var workflowInstanceIds = orderedSpans + .Select(x => GetAttribute(x.Attributes, "workflow.instance.id")) + .Where(x => !string.IsNullOrWhiteSpace(x)) + .Select(x => x!) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + return new TelemetryTrace(spans.Key, root.SpanId, root.Name, start, end, end - start, status, orderedSpans.Select(x => x.ResourceId).Distinct(StringComparer.OrdinalIgnoreCase).ToList(), workflowInstanceIds, orderedSpans.Count); + } + + private static string? GetAttribute(IDictionary attributes, string key) => attributes.TryGetValue(key, out var value) ? value : null; + + private static DateTimeOffset FromUnixNanos(ulong value) + { + try + { + var ticks = checked((long)(value / 100)); + return DateTimeOffset.UnixEpoch.AddTicks(ticks); + } + catch (Exception e) when (e is OverflowException or ArgumentOutOfRangeException) + { + throw new InvalidDataException("The OTLP timestamp is outside the supported range.", e); + } + } + + private static string ToHex(ReadOnlySpan bytes) + { + return Convert.ToHexString(bytes).ToLowerInvariant(); + } + + private static string SpanKindName(ulong value) => value switch + { + 1 => "internal", + 2 => "server", + 3 => "client", + 4 => "producer", + 5 => "consumer", + _ => "unspecified" + }; + + private static string SeverityName(int value) => value switch + { + >= 21 => "Fatal", + >= 17 => "Error", + >= 13 => "Warning", + >= 9 => "Information", + >= 5 => "Debug", + >= 1 => "Trace", + _ => "Unspecified" + }; + + private enum ProtobufWireType + { + Varint = 0, + Fixed64 = 1, + LengthDelimited = 2, + Fixed32 = 5 + } + + private readonly ref struct ProtobufField + { + public ProtobufField(int number, ProtobufWireType wireType, ulong varint, ReadOnlySpan bytes, double doubleValue) + { + Number = number; + WireType = wireType; + Varint = varint; + Bytes = bytes; + DoubleValue = doubleValue; + } + + public int Number { get; } + public ProtobufWireType WireType { get; } + public ulong Varint { get; } + public ReadOnlySpan Bytes { get; } + public double DoubleValue { get; } + + public string StringValue() => Encoding.UTF8.GetString(Bytes); + } + + private ref struct ProtobufReader + { + private ReadOnlySpan _remaining; + + public ProtobufReader(ReadOnlySpan payload) + { + _remaining = payload; + } + + public bool TryReadField(out ProtobufField field) + { + field = default; + + if (_remaining.IsEmpty) + return false; + + var tag = ReadVarint(); + var number = (int)(tag >> 3); + var wireType = (ProtobufWireType)(tag & 7); + + switch (wireType) + { + case ProtobufWireType.Varint: + field = new ProtobufField(number, wireType, ReadVarint(), default, default); + return true; + case ProtobufWireType.Fixed64: + EnsureAvailable(8); + var fixed64 = BinaryPrimitives.ReadUInt64LittleEndian(_remaining[..8]); + _remaining = _remaining[8..]; + field = new ProtobufField(number, wireType, fixed64, default, BitConverter.Int64BitsToDouble((long)fixed64)); + return true; + case ProtobufWireType.LengthDelimited: + var length = checked((int)ReadVarint()); + EnsureAvailable(length); + var bytes = _remaining[..length]; + _remaining = _remaining[length..]; + field = new ProtobufField(number, wireType, default, bytes, default); + return true; + case ProtobufWireType.Fixed32: + EnsureAvailable(4); + _remaining = _remaining[4..]; + field = new ProtobufField(number, wireType, default, default, default); + return true; + default: + throw new InvalidDataException($"Unsupported protobuf wire type '{wireType}'."); + } + } + + private ulong ReadVarint() + { + ulong value = 0; + var shift = 0; + + for (var i = 0; i < 10; i++) + { + if (_remaining.IsEmpty) + throw new InvalidDataException("Unexpected end of protobuf payload."); + + var b = _remaining[0]; + _remaining = _remaining[1..]; + value |= (ulong)(b & 0x7f) << shift; + + if ((b & 0x80) == 0) + return value; + + shift += 7; + } + + throw new InvalidDataException("Invalid protobuf varint."); + } + + private readonly void EnsureAvailable(int byteCount) + { + if (_remaining.Length < byteCount) + throw new InvalidDataException("Unexpected end of protobuf payload."); + } + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/OtlpIngestionSecurity.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/OtlpIngestionSecurity.cs new file mode 100644 index 000000000..b8d13ddac --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Ingestion/OtlpIngestionSecurity.cs @@ -0,0 +1,44 @@ +using System.Net; +using System.Security.Cryptography; +using System.Text; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.AspNetCore.Http; + +namespace Elsa.Diagnostics.OpenTelemetry.Ingestion; + +public static class OtlpIngestionSecurity +{ + public static bool IsAuthorized(HttpContext httpContext, OpenTelemetryDiagnosticsOptions options) + { + if (string.IsNullOrWhiteSpace(options.ApiKey)) + return options.AllowUnauthenticatedLoopback && IsLoopback(httpContext); + + return httpContext.Request.Headers.TryGetValue(options.ApiKeyHeaderName, out var value) && ApiKeysMatch(value.ToString(), options.ApiKey); + } + + private static bool IsLoopback(HttpContext httpContext) + { + var remoteAddress = httpContext.Connection.RemoteIpAddress; + return remoteAddress != null && IPAddress.IsLoopback(remoteAddress); + } + + private static bool ApiKeysMatch(string providedApiKey, string expectedApiKey) + { + var providedBytes = Encoding.UTF8.GetBytes(providedApiKey); + var expectedBytes = Encoding.UTF8.GetBytes(expectedApiKey); + var providedHash = SHA256.HashData(providedBytes); + var expectedHash = SHA256.HashData(expectedBytes); + + try + { + return CryptographicOperations.FixedTimeEquals(providedHash, expectedHash); + } + finally + { + CryptographicOperations.ZeroMemory(providedBytes); + CryptographicOperations.ZeroMemory(expectedBytes); + CryptographicOperations.ZeroMemory(providedHash); + CryptographicOperations.ZeroMemory(expectedHash); + } + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryContracts.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryContracts.cs new file mode 100644 index 000000000..8f2d3dc77 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryContracts.cs @@ -0,0 +1,86 @@ +namespace Elsa.Diagnostics.OpenTelemetry.Models; + +public record OpenTelemetryResourceFilter +{ + public string? Search { get; init; } + public string? ServiceName { get; init; } + public TelemetryResourceStatus? Status { get; init; } + public int? Take { get; init; } +} + +public record OpenTelemetryTraceFilter +{ + public string? ResourceId { get; init; } + public string? ServiceName { get; init; } + public string? TraceId { get; init; } + public string? WorkflowInstanceId { get; init; } + public SpanStatus? Status { get; init; } + public DateTimeOffset? From { get; init; } + public DateTimeOffset? To { get; init; } + public string? Search { get; init; } + public int? Take { get; init; } +} + +public record OpenTelemetryMetricFilter +{ + public string? ResourceId { get; init; } + public string? ServiceName { get; init; } + public string? InstrumentName { get; init; } + public DateTimeOffset? From { get; init; } + public DateTimeOffset? To { get; init; } + public int? Take { get; init; } +} + +public record OpenTelemetryLogFilter +{ + public string? ResourceId { get; init; } + public string? ServiceName { get; init; } + public string? TraceId { get; init; } + public string? SpanId { get; init; } + public string? Severity { get; init; } + public DateTimeOffset? From { get; init; } + public DateTimeOffset? To { get; init; } + public string? Search { get; init; } + public int? Take { get; init; } +} + +public record OpenTelemetryResourceResult(IReadOnlyCollection Items, long DroppedCount); + +public record OpenTelemetryTraceResult(IReadOnlyCollection Items, long DroppedCount); + +public record OpenTelemetryTraceDetail( + TelemetryTrace Trace, + IReadOnlyCollection Spans, + IReadOnlyCollection Resources, + IReadOnlyCollection Logs); + +public record OpenTelemetryMetricResult(IReadOnlyCollection Instruments, IReadOnlyCollection Points, long DroppedCount); + +public record OpenTelemetryLogResult(IReadOnlyCollection Items, long DroppedCount); + +public record CollectorEndpointInfo(string Protocol, string? Endpoint, bool Enabled, string? DisabledReason); + +public record CollectorConfiguration( + CollectorEndpointInfo Http, + CollectorEndpointInfo Grpc, + string ServiceNameEnvironmentVariable, + string EndpointEnvironmentVariable, + string ProtocolEnvironmentVariable, + IReadOnlyDictionary RequiredHeaders); + +public record OpenTelemetryBatch( + IReadOnlyCollection Resources, + IReadOnlyCollection Traces, + IReadOnlyCollection Spans, + IReadOnlyCollection Instruments, + IReadOnlyCollection MetricPoints, + IReadOnlyCollection Logs); + +public record OpenTelemetryStreamItem +{ + public TelemetryResource? Resource { get; init; } + public TelemetryTrace? Trace { get; init; } + public MetricPoint? MetricPoint { get; init; } + public OtlpLogRecord? Log { get; init; } + public OpenTelemetryDroppedItemSummary? DroppedItems { get; init; } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryModels.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryModels.cs new file mode 100644 index 000000000..4e201fce8 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Models/OpenTelemetryModels.cs @@ -0,0 +1,127 @@ +namespace Elsa.Diagnostics.OpenTelemetry.Models; + +public enum OpenTelemetrySignalType +{ + Trace, + Metric, + Log +} + +public enum TelemetryResourceStatus +{ + Unknown, + Active, + Stale +} + +public enum SpanStatus +{ + Unset, + Ok, + Error +} + +public enum MetricKind +{ + Gauge, + Sum, + Histogram +} + +public record TelemetryResource( + string Id, + string ServiceName, + string? ServiceInstanceId, + string? TelemetrySdkLanguage, + IDictionary Attributes, + DateTimeOffset LastSeen, + TelemetryResourceStatus Status); + +public record TelemetrySpan( + string Id, + string TraceId, + string SpanId, + string? ParentSpanId, + string ResourceId, + string Name, + string Kind, + DateTimeOffset StartTime, + DateTimeOffset EndTime, + SpanStatus Status, + string? StatusDescription, + IDictionary Attributes, + IReadOnlyCollection Events, + IReadOnlyCollection Links); + +public record TelemetrySpanEvent( + string Name, + DateTimeOffset Timestamp, + IDictionary Attributes); + +public record TelemetrySpanLink( + string TraceId, + string SpanId, + IDictionary Attributes); + +public record TelemetryTrace( + string TraceId, + string? RootSpanId, + string? Name, + DateTimeOffset StartTime, + DateTimeOffset EndTime, + TimeSpan Duration, + SpanStatus Status, + IReadOnlyCollection ResourceIds, + IReadOnlyCollection WorkflowInstanceIds, + int SpanCount); + +public record MetricInstrument( + string Id, + string ResourceId, + string Name, + string? Unit, + string? Description, + MetricKind Kind, + IDictionary Attributes); + +public record MetricPoint( + string Id, + string InstrumentId, + string InstrumentName, + string ResourceId, + DateTimeOffset Timestamp, + double? Value, + double? Sum, + long? Count, + IDictionary Attributes, + string? TraceId, + string? SpanId); + +public record OtlpLogRecord( + string Id, + string ResourceId, + DateTimeOffset Timestamp, + string SeverityText, + int? SeverityNumber, + string Body, + string? TraceId, + string? SpanId, + IDictionary Attributes); + +public record OpenTelemetryDroppedItemSummary(OpenTelemetrySignalType SignalType, long Count, string Reason); + +public record OpenTelemetryStorageDiagnostics( + int TraceCapacity, + int SpanCapacity, + int MetricPointCapacity, + int LogRecordCapacity, + int ResourceCount, + int TraceCount, + int SpanCount, + int MetricInstrumentCount, + int MetricPointCount, + int LogRecordCount, + long DroppedTraceCount, + long DroppedSpanCount, + long DroppedMetricPointCount, + long DroppedLogRecordCount); diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Options/OpenTelemetryDiagnosticsOptions.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Options/OpenTelemetryDiagnosticsOptions.cs new file mode 100644 index 000000000..5d2d4b11a --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Options/OpenTelemetryDiagnosticsOptions.cs @@ -0,0 +1,43 @@ +namespace Elsa.Diagnostics.OpenTelemetry.Options; + +public class OpenTelemetryDiagnosticsOptions +{ + public int TraceCapacity { get; set; } = 5_000; + public int SpanCapacity { get; set; } = 25_000; + public int MetricPointCapacity { get; set; } = 25_000; + public int LogRecordCapacity { get; set; } = 10_000; + public int ResourceCapacity { get; set; } = 500; + public int SubscriberChannelCapacity { get; set; } = 1_000; + public int MaxQuerySize { get; set; } = 1_000; + public long MaxHttpRequestBodySize { get; set; } = 10 * 1024 * 1024; + public string HttpEndpointPath { get; set; } = "/elsa/otlp/v1"; + public string? GrpcEndpointPath { get; set; } + public string GrpcDisabledReason { get; set; } = "gRPC ingestion is not enabled for this host."; + public string HubRoute { get; set; } = "/elsa/hubs/diagnostics/opentelemetry"; + public bool EnableGrpc { get; set; } + public string? ApiKey { get; set; } + public string ApiKeyHeaderName { get; set; } = "x-otlp-api-key"; + public bool AllowUnauthenticatedLoopback { get; set; } = true; + + public ICollection SensitiveNames { get; set; } = + [ + "authorization", + "token", + "password", + "secret", + "api-key", + "apikey", + "cookie", + "connection-string", + "connectionstring" + ]; + + public ICollection SensitiveTextPatterns { get; set; } = + [ + "(?i)bearer\\s+[A-Za-z0-9._~+/=-]+", + "(?i)(password|secret|token|api[-_]?key)\\s*[=:]\\s*[^\\s,;]+", + "(?i)(AccountKey|SharedAccessKey)=([^;\\s]+)" + ]; + + public TimeSpan SensitiveTextPatternTimeout { get; set; } = TimeSpan.FromMilliseconds(100); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Permissions/OpenTelemetryPermissions.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Permissions/OpenTelemetryPermissions.cs new file mode 100644 index 000000000..47bb415b5 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Permissions/OpenTelemetryPermissions.cs @@ -0,0 +1,7 @@ +namespace Elsa.Diagnostics.OpenTelemetry.Permissions; + +public static class OpenTelemetryPermissions +{ + public const string Read = "read:diagnostics:opentelemetry"; + public const string Ingest = "ingest:diagnostics:opentelemetry"; +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs new file mode 100644 index 000000000..b84776c44 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs @@ -0,0 +1,166 @@ +using System.Runtime.CompilerServices; +using System.Threading.Channels; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; + +public class InMemoryOpenTelemetryLiveFeed(IOptions options) : IOpenTelemetryLiveFeed +{ + private readonly OpenTelemetryDiagnosticsOptions _options = options.Value; + private readonly object _subscribersLock = new(); + private readonly List _subscribers = []; + + public ValueTask PublishAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default) + { + List subscribers; + lock (_subscribersLock) + subscribers = _subscribers.ToList(); + + foreach (var subscriber in subscribers) + subscriber.TryWrite(batch); + + return ValueTask.CompletedTask; + } + + public async IAsyncEnumerable SubscribeAsync(OpenTelemetryTraceFilter filter, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + var subscriber = new OpenTelemetrySubscriber(filter, _options.SubscriberChannelCapacity); + + lock (_subscribersLock) + _subscribers.Add(subscriber); + + try + { + await foreach (var item in subscriber.Channel.Reader.ReadAllAsync(cancellationToken)) + { + subscriber.MarkRead(item); + yield return item; + } + } + finally + { + lock (_subscribersLock) + _subscribers.Remove(subscriber); + } + } + + private sealed class OpenTelemetrySubscriber(OpenTelemetryTraceFilter filter, int channelCapacity) + { + private readonly object _lock = new(); + private readonly int _capacity = Math.Max(1, channelCapacity); + private int _pendingItemCount; + private readonly Dictionary _droppedSinceLastSummary = []; + + public Channel Channel { get; } = System.Threading.Channels.Channel.CreateBounded(new BoundedChannelOptions(Math.Max(1, channelCapacity)) + { + SingleReader = true, + SingleWriter = false, + FullMode = BoundedChannelFullMode.Wait + }); + + public void TryWrite(OpenTelemetryBatch batch) + { + foreach (var resource in batch.Resources) + TryWrite(new OpenTelemetryStreamItem { Resource = resource }); + + foreach (var trace in batch.Traces.Where(Matches)) + TryWrite(new OpenTelemetryStreamItem { Trace = trace }); + + foreach (var log in batch.Logs.Where(x => string.IsNullOrWhiteSpace(filter.TraceId) || string.Equals(x.TraceId, filter.TraceId, StringComparison.OrdinalIgnoreCase))) + TryWrite(new OpenTelemetryStreamItem { Log = log }); + + foreach (var point in batch.MetricPoints) + TryWrite(new OpenTelemetryStreamItem { MetricPoint = point }); + } + + private void TryWrite(OpenTelemetryStreamItem item) + { + lock (_lock) + { + EnsureCapacityForWrite(); + if (Channel.Writer.TryWrite(item)) + _pendingItemCount++; + else + TrackDrop(item); + + TryWriteDroppedSummary(); + } + } + + public void MarkRead(OpenTelemetryStreamItem item) + { + lock (_lock) + { + _pendingItemCount = Math.Max(0, _pendingItemCount - 1); + + if (item.DroppedItems != null) + _droppedSinceLastSummary.Remove(item.DroppedItems.SignalType); + + TryWriteDroppedSummary(); + } + } + + private void EnsureCapacityForWrite() + { + if (_pendingItemCount < _capacity) + return; + + if (!Channel.Reader.TryRead(out var dropped)) + return; + + _pendingItemCount = Math.Max(0, _pendingItemCount - 1); + TrackDrop(dropped); + } + + private void TrackDrop(OpenTelemetryStreamItem item) + { + var signalType = GetSignalType(item); + if (signalType == null) + return; + + _droppedSinceLastSummary.TryGetValue(signalType.Value, out var count); + _droppedSinceLastSummary[signalType.Value] = count + (item.DroppedItems?.Count ?? 1); + } + + private void TryWriteDroppedSummary() + { + if (_droppedSinceLastSummary.Count == 0) + return; + + if (_pendingItemCount >= _capacity) + return; + + var dropped = _droppedSinceLastSummary.OrderBy(x => x.Key).First(); + if (Channel.Writer.TryWrite(new OpenTelemetryStreamItem { DroppedItems = new(dropped.Key, dropped.Value, "SubscriberQueueFull") })) + _pendingItemCount++; + } + + private static OpenTelemetrySignalType? GetSignalType(OpenTelemetryStreamItem item) + { + if (item.Trace != null) + return OpenTelemetrySignalType.Trace; + + if (item.MetricPoint != null) + return OpenTelemetrySignalType.Metric; + + if (item.Log != null) + return OpenTelemetrySignalType.Log; + + return item.DroppedItems?.SignalType; + } + + private bool Matches(TelemetryTrace trace) + { + if (!string.IsNullOrWhiteSpace(filter.TraceId) && !string.Equals(trace.TraceId, filter.TraceId, StringComparison.OrdinalIgnoreCase)) + return false; + + if (filter.Status != null && trace.Status != filter.Status) + return false; + + return true; + } + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs new file mode 100644 index 000000000..93ba58d27 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryStore.cs @@ -0,0 +1,227 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; + +public class InMemoryOpenTelemetryStore : IOpenTelemetryStore +{ + private readonly IOpenTelemetrySourceRegistry _sourceRegistry; + private readonly OpenTelemetryDiagnosticsOptions _options; + private readonly int _traceCapacity; + private readonly int _spanCapacity; + private readonly int _metricPointCapacity; + private readonly int _logRecordCapacity; + private readonly RingBuffer _traces; + private readonly RingBuffer _spans; + private readonly RingBuffer _metricPoints; + private readonly RingBuffer _logs; + private readonly object _instrumentLock = new(); + private readonly Dictionary _instruments = new(StringComparer.OrdinalIgnoreCase); + + public InMemoryOpenTelemetryStore(IOptions options, IOpenTelemetrySourceRegistry sourceRegistry) + { + _options = options.Value; + _sourceRegistry = sourceRegistry; + _traceCapacity = ClampCapacity(_options.TraceCapacity); + _spanCapacity = ClampCapacity(_options.SpanCapacity); + _metricPointCapacity = ClampCapacity(_options.MetricPointCapacity); + _logRecordCapacity = ClampCapacity(_options.LogRecordCapacity); + _traces = new(_traceCapacity); + _spans = new(_spanCapacity); + _metricPoints = new(_metricPointCapacity); + _logs = new(_logRecordCapacity); + } + + public ValueTask WriteAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default) + { + foreach (var resource in batch.Resources) + _sourceRegistry.MarkSeen(resource); + + foreach (var trace in batch.Traces) + _traces.Add(trace); + + foreach (var span in batch.Spans) + _spans.Add(span); + + lock (_instrumentLock) + { + foreach (var instrument in batch.Instruments) + _instruments[instrument.Id] = instrument; + } + + foreach (var point in batch.MetricPoints) + _metricPoints.Add(point); + + foreach (var log in batch.Logs) + _logs.Add(log); + + return ValueTask.CompletedTask; + } + + public ValueTask QueryResourcesAsync(OpenTelemetryResourceFilter filter, CancellationToken cancellationToken = default) + { + var take = ClampTake(filter.Take); + var items = _sourceRegistry.List() + .Where(x => string.IsNullOrWhiteSpace(filter.ServiceName) || string.Equals(x.ServiceName, filter.ServiceName, StringComparison.OrdinalIgnoreCase)) + .Where(x => filter.Status == null || x.Status == filter.Status) + .Where(x => string.IsNullOrWhiteSpace(filter.Search) || Matches(x.ServiceName, filter.Search) || Matches(x.Id, filter.Search)) + .OrderByDescending(x => x.LastSeen) + .ThenBy(x => x.ServiceName, StringComparer.OrdinalIgnoreCase) + .Take(take) + .ToList(); + + return ValueTask.FromResult(new OpenTelemetryResourceResult(items, _sourceRegistry.DroppedCount)); + } + + public ValueTask QueryTracesAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default) + { + var take = ClampTake(filter.Take); + var serviceResourceIds = ResolveResourceIds(filter.ServiceName); + var items = _traces.Snapshot() + .Where(x => string.IsNullOrWhiteSpace(filter.TraceId) || Matches(x.TraceId, filter.TraceId)) + .Where(x => filter.Status == null || x.Status == filter.Status) + .Where(x => filter.From == null || x.StartTime >= filter.From) + .Where(x => filter.To == null || x.StartTime <= filter.To) + .Where(x => string.IsNullOrWhiteSpace(filter.WorkflowInstanceId) || x.WorkflowInstanceIds.Any(id => Matches(id, filter.WorkflowInstanceId))) + .Where(x => string.IsNullOrWhiteSpace(filter.ResourceId) || x.ResourceIds.Contains(filter.ResourceId, StringComparer.OrdinalIgnoreCase)) + .Where(x => serviceResourceIds == null || x.ResourceIds.Any(serviceResourceIds.Contains)) + .Where(x => string.IsNullOrWhiteSpace(filter.Search) || Matches(x.TraceId, filter.Search) || Matches(x.Name, filter.Search)) + .OrderBy(x => x.StartTime) + .GroupBy(x => x.TraceId, StringComparer.OrdinalIgnoreCase) + .Select(x => x.Last()) + .TakeLast(take) + .ToList(); + + return ValueTask.FromResult(new OpenTelemetryTraceResult(items, _traces.DroppedCount)); + } + + public ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default) + { + var trace = _traces.Snapshot().LastOrDefault(x => string.Equals(x.TraceId, traceId, StringComparison.OrdinalIgnoreCase)); + if (trace == null) + return ValueTask.FromResult(null); + + var spans = _spans.Snapshot() + .Where(x => string.Equals(x.TraceId, traceId, StringComparison.OrdinalIgnoreCase)) + .OrderBy(x => x.StartTime) + .ThenBy(x => x.SpanId, StringComparer.OrdinalIgnoreCase) + .ToList(); + var resourceIds = trace.ResourceIds.ToHashSet(StringComparer.OrdinalIgnoreCase); + var resources = _sourceRegistry.List() + .Where(x => resourceIds.Contains(x.Id)) + .OrderBy(x => x.ServiceName, StringComparer.OrdinalIgnoreCase) + .ThenBy(x => x.Id, StringComparer.OrdinalIgnoreCase) + .ToList(); + var logs = _logs.Snapshot() + .Where(x => string.Equals(x.TraceId, traceId, StringComparison.OrdinalIgnoreCase)) + .OrderBy(x => x.Timestamp) + .ThenBy(x => x.Id, StringComparer.OrdinalIgnoreCase) + .ToList(); + + return ValueTask.FromResult(new OpenTelemetryTraceDetail(trace, spans, resources, logs)); + } + + public ValueTask QueryMetricsAsync(OpenTelemetryMetricFilter filter, CancellationToken cancellationToken = default) + { + var take = ClampTake(filter.Take); + var serviceResourceIds = ResolveResourceIds(filter.ServiceName); + + Dictionary instruments; + lock (_instrumentLock) + instruments = new(_instruments, StringComparer.OrdinalIgnoreCase); + + var instrumentFilterIds = string.IsNullOrWhiteSpace(filter.InstrumentName) + ? null + : instruments.Values + .Where(x => Matches(x.Name, filter.InstrumentName)) + .Select(x => x.Id) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + + var points = _metricPoints.Snapshot() + .Where(x => string.IsNullOrWhiteSpace(filter.ResourceId) || string.Equals(x.ResourceId, filter.ResourceId, StringComparison.OrdinalIgnoreCase)) + .Where(x => serviceResourceIds == null || serviceResourceIds.Contains(x.ResourceId)) + .Where(x => filter.From == null || x.Timestamp >= filter.From) + .Where(x => filter.To == null || x.Timestamp <= filter.To) + .Where(x => instrumentFilterIds == null || instrumentFilterIds.Contains(x.InstrumentId)) + .OrderBy(x => x.Timestamp) + .TakeLast(take) + .ToList(); + + var selectedInstruments = points + .Select(x => x.InstrumentId) + .Distinct(StringComparer.OrdinalIgnoreCase) + .Where(instruments.ContainsKey) + .Select(x => instruments[x]) + .ToList(); + + return ValueTask.FromResult(new OpenTelemetryMetricResult(selectedInstruments, points, _metricPoints.DroppedCount)); + } + + public ValueTask QueryLogsAsync(OpenTelemetryLogFilter filter, CancellationToken cancellationToken = default) + { + var take = ClampTake(filter.Take); + var serviceResourceIds = ResolveResourceIds(filter.ServiceName); + var logs = _logs.Snapshot() + .Where(x => string.IsNullOrWhiteSpace(filter.ResourceId) || string.Equals(x.ResourceId, filter.ResourceId, StringComparison.OrdinalIgnoreCase)) + .Where(x => serviceResourceIds == null || serviceResourceIds.Contains(x.ResourceId)) + .Where(x => string.IsNullOrWhiteSpace(filter.TraceId) || Matches(x.TraceId, filter.TraceId)) + .Where(x => string.IsNullOrWhiteSpace(filter.SpanId) || Matches(x.SpanId, filter.SpanId)) + .Where(x => string.IsNullOrWhiteSpace(filter.Severity) || Matches(x.SeverityText, filter.Severity)) + .Where(x => filter.From == null || x.Timestamp >= filter.From) + .Where(x => filter.To == null || x.Timestamp <= filter.To) + .Where(x => string.IsNullOrWhiteSpace(filter.Search) || Matches(x.Body, filter.Search)) + .OrderBy(x => x.Timestamp) + .TakeLast(take) + .ToList(); + + return ValueTask.FromResult(new OpenTelemetryLogResult(logs, _logs.DroppedCount)); + } + + public ValueTask GetDiagnosticsAsync(CancellationToken cancellationToken = default) + { + Dictionary instruments; + lock (_instrumentLock) + instruments = new(_instruments, StringComparer.OrdinalIgnoreCase); + + var traceSnapshot = _traces.Snapshot(); + var spanSnapshot = _spans.Snapshot(); + var metricPointSnapshot = _metricPoints.Snapshot(); + var logSnapshot = _logs.Snapshot(); + var diagnostics = new OpenTelemetryStorageDiagnostics( + _traceCapacity, + _spanCapacity, + _metricPointCapacity, + _logRecordCapacity, + _sourceRegistry.List().Count, + traceSnapshot.Count, + spanSnapshot.Count, + instruments.Count, + metricPointSnapshot.Count, + logSnapshot.Count, + _traces.DroppedCount, + _spans.DroppedCount, + _metricPoints.DroppedCount, + _logs.DroppedCount); + + return ValueTask.FromResult(diagnostics); + } + + private int ClampTake(int? take) => Math.Clamp(take ?? _options.MaxQuerySize, 0, _options.MaxQuerySize); + + private static int ClampCapacity(int capacity) => Math.Max(1, capacity); + + private HashSet? ResolveResourceIds(string? serviceName) + { + if (string.IsNullOrWhiteSpace(serviceName)) + return null; + + return _sourceRegistry.List() + .Where(x => string.Equals(x.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase)) + .Select(x => x.Id) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + } + + private static bool Matches(string? candidate, string? search) => !string.IsNullOrEmpty(candidate) && !string.IsNullOrEmpty(search) && candidate.Contains(search, StringComparison.OrdinalIgnoreCase); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/RingBuffer.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/RingBuffer.cs new file mode 100644 index 000000000..cd9dc9cd9 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/RingBuffer.cs @@ -0,0 +1,46 @@ +namespace Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; + +public class RingBuffer +{ + private readonly Queue _items = new(); + private readonly object _lock = new(); + private readonly int _capacity; + private long _droppedCount; + + public RingBuffer(int capacity) + { + if (capacity <= 0) + throw new ArgumentOutOfRangeException(nameof(capacity), "Capacity must be greater than zero."); + + _capacity = capacity; + } + + public long DroppedCount + { + get + { + lock (_lock) + return _droppedCount; + } + } + + public void Add(T item) + { + lock (_lock) + { + if (_items.Count == _capacity) + { + _items.Dequeue(); + _droppedCount++; + } + + _items.Enqueue(item); + } + } + + public IReadOnlyCollection Snapshot() + { + lock (_lock) + return _items.ToList(); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/README.md b/src/modules/Elsa.Diagnostics.OpenTelemetry/README.md new file mode 100644 index 000000000..cf204accb --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/README.md @@ -0,0 +1,41 @@ +# Elsa Diagnostics OpenTelemetry + +Provides the OpenTelemetry diagnostics collector surface for Elsa hosts. + +This module owns the Core-side OTEL contracts, HTTP/protobuf ingestion, bounded in-memory diagnostics store, feature registration, permissions, read APIs, live update hub, and collector metadata that Studio consumes. + +## Scope + +`Elsa.Diagnostics.OpenTelemetry` is collector/read-side diagnostics infrastructure. It does not create workflow spans, mutate `Activity.Current`, export telemetry to vendors, or provide durable OpenTelemetry persistence. Workflow telemetry production remains owned by existing `Elsa.Workflows` `ActivitySource` and `Meter` instrumentation. + +The historical `Elsa.OpenTelemetry` module from `elsa-extensions` is intentionally not ported into this feature. It is producer-side workflow tracing middleware, duplicates current `Elsa.Workflows` instrumentation, and mutates `Activity.Current`; this module is collector/read-side diagnostics infrastructure. + +## Routes + +OTLP HTTP/protobuf ingestion is exposed under `OpenTelemetryDiagnosticsOptions.HttpEndpointPath`, which defaults to `/elsa/otlp/v1`: + +- `POST /elsa/otlp/v1/traces` +- `POST /elsa/otlp/v1/metrics` +- `POST /elsa/otlp/v1/logs` + +Diagnostics read APIs are exposed through Elsa API endpoints: + +- `POST /diagnostics/opentelemetry/resources/search` +- `POST /diagnostics/opentelemetry/traces/search` +- `GET /diagnostics/opentelemetry/traces/{traceId}` +- `POST /diagnostics/opentelemetry/metrics/search` +- `POST /diagnostics/opentelemetry/logs/search` +- `GET /diagnostics/opentelemetry/storage` +- `GET /diagnostics/opentelemetry/collector-configuration` + +Live updates are exposed through SignalR at `OpenTelemetryDiagnosticsOptions.HubRoute`, which defaults to `/elsa/hubs/diagnostics/opentelemetry`. + +## Security + +All diagnostics read APIs require the OpenTelemetry diagnostics read permission. OTLP ingestion allows unauthenticated loopback traffic by default for local development only when no API key is configured. When `OpenTelemetryDiagnosticsOptions.ApiKey` is set, every sender must provide the configured API key header, including loopback senders. + +Collector configuration returns endpoint and required-header names only. It never returns secret header values. + +## Storage + +The default provider is bounded in-memory storage. Capacity options cover traces, spans, metric points, OTLP log records, and live subscriber queues. When a buffer exceeds capacity, the oldest item for that signal is dropped and diagnostics counters are incremented. diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/IOpenTelemetryClient.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/IOpenTelemetryClient.cs new file mode 100644 index 000000000..e7242dbed --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/IOpenTelemetryClient.cs @@ -0,0 +1,8 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.RealTime; + +public interface IOpenTelemetryClient +{ + Task ReceiveAsync(OpenTelemetryStreamItem item); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetryHub.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetryHub.cs new file mode 100644 index 000000000..eea15d662 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetryHub.cs @@ -0,0 +1,50 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using FastEndpoints.Security; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; + +namespace Elsa.Diagnostics.OpenTelemetry.RealTime; + +[Authorize] +public class OpenTelemetryHub(OpenTelemetrySubscriptionManager subscriptionManager) : Hub +{ + private const string ReadAllPermission = "read:*"; + private static readonly string[] ReadPermissions = [PermissionNames.All, ReadAllPermission, OpenTelemetryPermissions.Read]; + + public Task SubscribeAsync(OpenTelemetryTraceFilter? filter) + { + EnsureCanReadOpenTelemetry(); + return subscriptionManager.SubscribeAsync(Context.ConnectionId, ValidateFilter(filter), Context.ConnectionAborted); + } + + public Task UnsubscribeAsync() + { + return subscriptionManager.UnsubscribeAsync(Context.ConnectionId); + } + + public override async Task OnDisconnectedAsync(Exception? exception) + { + await UnsubscribeAsync().ConfigureAwait(false); + await base.OnDisconnectedAsync(exception).ConfigureAwait(false); + } + + private static OpenTelemetryTraceFilter ValidateFilter(OpenTelemetryTraceFilter? filter) + { + filter ??= new(); + + if (filter.From is { } from && filter.To is { } to && from > to) + throw new HubException("The OpenTelemetry filter 'from' timestamp must be earlier than or equal to 'to'."); + + return filter; + } + + private void EnsureCanReadOpenTelemetry() + { + var user = Context.User; + + if (user?.Identity?.IsAuthenticated != true || !ReadPermissions.Any(user.HasPermission)) + throw new HubException("Access denied."); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetrySubscriptionManager.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetrySubscriptionManager.cs new file mode 100644 index 000000000..c676e1ac3 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/RealTime/OpenTelemetrySubscriptionManager.cs @@ -0,0 +1,82 @@ +using System.Collections.Concurrent; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; + +namespace Elsa.Diagnostics.OpenTelemetry.RealTime; + +public sealed class OpenTelemetrySubscriptionManager( + IOpenTelemetryLiveFeed liveFeed, + IHubContext hubContext, + ILogger logger) : IDisposable +{ + private readonly ConcurrentDictionary _subscriptions = new(StringComparer.Ordinal); + + public Task SubscribeAsync(string connectionId, OpenTelemetryTraceFilter filter, CancellationToken cancellationToken) + { + Unsubscribe(connectionId); + var subscriptionCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + var subscription = new OpenTelemetrySubscription(filter, subscriptionCancellation); + _subscriptions[connectionId] = subscription; + + _ = StreamAsync(connectionId, filter, subscription, subscriptionCancellation.Token); + return Task.CompletedTask; + } + + public Task UnsubscribeAsync(string connectionId) + { + Unsubscribe(connectionId); + return Task.CompletedTask; + } + + public void Dispose() + { + foreach (var subscription in _subscriptions.Values) + { + subscription.CancellationTokenSource.Cancel(); + subscription.CancellationTokenSource.Dispose(); + } + + _subscriptions.Clear(); + } + + private async Task StreamAsync(string connectionId, OpenTelemetryTraceFilter filter, OpenTelemetrySubscription subscription, CancellationToken cancellationToken) + { + try + { + await foreach (var item in liveFeed.SubscribeAsync(filter, cancellationToken).ConfigureAwait(false)) + await hubContext.Clients.Client(connectionId).ReceiveAsync(item).ConfigureAwait(false); + } + catch (OperationCanceledException e) + { + logger.LogDebug(e, "OpenTelemetry subscription for connection {ConnectionId} was canceled", connectionId); + } + catch (Exception e) when (e is not OperationCanceledException) + { + logger.LogWarning(e, "OpenTelemetry subscription for connection {ConnectionId} stopped unexpectedly", connectionId); + } + finally + { + Remove(connectionId, subscription); + } + } + + private void Unsubscribe(string connectionId) + { + if (!_subscriptions.TryRemove(connectionId, out var subscription)) + return; + + subscription.CancellationTokenSource.Cancel(); + subscription.CancellationTokenSource.Dispose(); + } + + private void Remove(string connectionId, OpenTelemetrySubscription subscription) + { + var entry = new KeyValuePair(connectionId, subscription); + if (((ICollection>)_subscriptions).Remove(entry)) + subscription.CancellationTokenSource.Dispose(); + } + + private sealed record OpenTelemetrySubscription(OpenTelemetryTraceFilter Filter, CancellationTokenSource CancellationTokenSource); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/CollectorConfigurationProvider.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/CollectorConfigurationProvider.cs new file mode 100644 index 000000000..8001aadda --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/CollectorConfigurationProvider.cs @@ -0,0 +1,34 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.Services; + +public class CollectorConfigurationProvider(IOptions options) : ICollectorConfigurationProvider +{ + private readonly OpenTelemetryDiagnosticsOptions _options = options.Value; + + public ValueTask GetAsync(CancellationToken cancellationToken = default) + { + var headers = string.IsNullOrWhiteSpace(_options.ApiKey) + ? new Dictionary() + : new Dictionary { [_options.ApiKeyHeaderName] = "" }; + var grpcEnabled = _options.EnableGrpc && !string.IsNullOrWhiteSpace(_options.GrpcEndpointPath); + var grpcDisabledReason = grpcEnabled + ? null + : _options.EnableGrpc + ? "gRPC endpoint path is not configured." + : _options.GrpcDisabledReason; + + var configuration = new CollectorConfiguration( + new CollectorEndpointInfo("http/protobuf", _options.HttpEndpointPath, true, null), + new CollectorEndpointInfo("grpc", grpcEnabled ? _options.GrpcEndpointPath : null, grpcEnabled, grpcDisabledReason), + "OTEL_SERVICE_NAME", + "OTEL_EXPORTER_OTLP_ENDPOINT", + "OTEL_EXPORTER_OTLP_PROTOCOL", + headers); + + return ValueTask.FromResult(configuration); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/DefaultOpenTelemetryProvider.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/DefaultOpenTelemetryProvider.cs new file mode 100644 index 000000000..5dddb9d66 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/DefaultOpenTelemetryProvider.cs @@ -0,0 +1,21 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Services; + +public class DefaultOpenTelemetryProvider(IOpenTelemetryStore store, ICollectorConfigurationProvider collectorConfigurationProvider) : IOpenTelemetryProvider +{ + public ValueTask GetResourcesAsync(OpenTelemetryResourceFilter filter, CancellationToken cancellationToken = default) => store.QueryResourcesAsync(filter, cancellationToken); + + public ValueTask GetTracesAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default) => store.QueryTracesAsync(filter, cancellationToken); + + public ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default) => store.GetTraceAsync(traceId, cancellationToken); + + public ValueTask GetMetricsAsync(OpenTelemetryMetricFilter filter, CancellationToken cancellationToken = default) => store.QueryMetricsAsync(filter, cancellationToken); + + public ValueTask GetLogsAsync(OpenTelemetryLogFilter filter, CancellationToken cancellationToken = default) => store.QueryLogsAsync(filter, cancellationToken); + + public ValueTask GetStorageDiagnosticsAsync(CancellationToken cancellationToken = default) => store.GetDiagnosticsAsync(cancellationToken); + + public ValueTask GetCollectorConfigurationAsync(CancellationToken cancellationToken = default) => collectorConfigurationProvider.GetAsync(cancellationToken); +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryIngestor.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryIngestor.cs new file mode 100644 index 000000000..472562990 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryIngestor.cs @@ -0,0 +1,14 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.Services; + +public class OpenTelemetryIngestor(IOpenTelemetryRedactor redactor, IOpenTelemetryStore store, IOpenTelemetryLiveFeed liveFeed) : IOpenTelemetryIngestor +{ + public async ValueTask IngestAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default) + { + var redactedBatch = redactor.Redact(batch); + await store.WriteAsync(redactedBatch, cancellationToken); + await liveFeed.PublishAsync(redactedBatch, cancellationToken); + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryRedactor.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryRedactor.cs new file mode 100644 index 000000000..d1630f465 --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetryRedactor.cs @@ -0,0 +1,84 @@ +using System.Text.RegularExpressions; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.Services; + +public class OpenTelemetryRedactor(IOptions options) : IOpenTelemetryRedactor +{ + private const string Redacted = "[Redacted]"; + private readonly HashSet _sensitiveNames = options.Value.SensitiveNames.ToHashSet(StringComparer.OrdinalIgnoreCase); + private readonly IReadOnlyCollection _sensitiveTextPatterns = options.Value.SensitiveTextPatterns + .Select(pattern => new Regex(pattern, RegexOptions.Compiled | RegexOptions.CultureInvariant, options.Value.SensitiveTextPatternTimeout)) + .ToList(); + + public OpenTelemetryBatch Redact(OpenTelemetryBatch batch) + { + return batch with + { + Resources = batch.Resources.Select(RedactResource).ToList(), + Spans = batch.Spans.Select(RedactSpan).ToList(), + Instruments = batch.Instruments.Select(x => x with { Attributes = RedactDictionary(x.Attributes) }).ToList(), + MetricPoints = batch.MetricPoints.Select(x => x with { Attributes = RedactDictionary(x.Attributes) }).ToList(), + Logs = batch.Logs.Select(RedactLog).ToList() + }; + } + + private TelemetryResource RedactResource(TelemetryResource resource) => resource with { Attributes = RedactDictionary(resource.Attributes) }; + + private TelemetrySpan RedactSpan(TelemetrySpan span) + { + return span with + { + Name = RedactValue("span.name", span.Name) ?? string.Empty, + StatusDescription = RedactValue("span.status.description", span.StatusDescription), + Attributes = RedactDictionary(span.Attributes), + Events = span.Events.Select(x => x with { Attributes = RedactDictionary(x.Attributes) }).ToList(), + Links = span.Links.Select(x => x with { Attributes = RedactDictionary(x.Attributes) }).ToList() + }; + } + + private OtlpLogRecord RedactLog(OtlpLogRecord log) + { + return log with + { + Body = RedactValue("log.body", log.Body) ?? string.Empty, + Attributes = RedactDictionary(log.Attributes) + }; + } + + private Dictionary RedactDictionary(IDictionary values) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var (key, value) in values) + result[key] = RedactValue(key, value); + + return result; + } + + private string? RedactValue(string name, string? value) + { + if (value == null) + return null; + + if (_sensitiveNames.Any(sensitiveName => name.Contains(sensitiveName, StringComparison.OrdinalIgnoreCase))) + return Redacted; + + return _sensitiveTextPatterns.Aggregate(value, RedactPattern); + } + + private static string RedactPattern(string value, Regex pattern) + { + try + { + return pattern.Replace(value, Redacted); + } + catch (RegexMatchTimeoutException) + { + return value; + } + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetrySourceRegistry.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetrySourceRegistry.cs new file mode 100644 index 000000000..07413cb7a --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Services/OpenTelemetrySourceRegistry.cs @@ -0,0 +1,59 @@ +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.Extensions.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.Services; + +public class OpenTelemetrySourceRegistry : IOpenTelemetrySourceRegistry +{ + private readonly object _lock = new(); + private readonly Dictionary _resources = new(StringComparer.OrdinalIgnoreCase); + private readonly int _capacity; + private long _droppedCount; + + public OpenTelemetrySourceRegistry(IOptions options) + { + _capacity = Math.Max(1, options.Value.ResourceCapacity); + } + + public OpenTelemetrySourceRegistry() : this(Microsoft.Extensions.Options.Options.Create(new OpenTelemetryDiagnosticsOptions())) + { + } + + public long DroppedCount + { + get + { + lock (_lock) + return _droppedCount; + } + } + + public void MarkSeen(TelemetryResource resource) + { + lock (_lock) + { + if (!_resources.ContainsKey(resource.Id) && _resources.Count >= _capacity) + RemoveOldestResource(); + + _resources[resource.Id] = resource; + } + } + + public IReadOnlyCollection List() + { + lock (_lock) + return _resources.Values.OrderBy(x => x.ServiceName, StringComparer.OrdinalIgnoreCase).ThenBy(x => x.Id, StringComparer.OrdinalIgnoreCase).ToList(); + } + + private void RemoveOldestResource() + { + var oldest = _resources.Values.OrderBy(x => x.LastSeen).ThenBy(x => x.Id, StringComparer.OrdinalIgnoreCase).FirstOrDefault(); + if (oldest == null) + return; + + _resources.Remove(oldest.Id); + _droppedCount++; + } +} diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/ShellFeatures/OpenTelemetryFeature.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/ShellFeatures/OpenTelemetryFeature.cs new file mode 100644 index 000000000..d154398af --- /dev/null +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/ShellFeatures/OpenTelemetryFeature.cs @@ -0,0 +1,101 @@ +using CShells.AspNetCore.Features; +using CShells.FastEndpoints.Features; +using CShells.Features; +using Elsa.Diagnostics.OpenTelemetry.Extensions; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.PackageManifest.Generator.Hints; +using JetBrains.Annotations; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Elsa.Diagnostics.OpenTelemetry.ShellFeatures; + +[ShellFeature( + DisplayName = "OpenTelemetry Diagnostics", + Description = "Provides OpenTelemetry diagnostics collection, query services, and live updates", + DependsOn = ["ElsaFastEndpoints"])] +[UsedImplicitly] +public class OpenTelemetryFeature : IFastEndpointsShellFeature, IWebShellFeature +{ + private static readonly OpenTelemetryDiagnosticsOptions DefaultOptions = new(); + + [ManifestSetting( + DisplayName = "Trace Capacity", + Description = "Maximum number of recent traces retained in memory.", + Category = "Diagnostics", + DefaultValue = "5000", + RestartRequired = true)] + public int TraceCapacity { get; set; } = DefaultOptions.TraceCapacity; + + [ManifestSetting( + DisplayName = "Span Capacity", + Description = "Maximum number of recent spans retained in memory.", + Category = "Diagnostics", + DefaultValue = "25000", + RestartRequired = true)] + public int SpanCapacity { get; set; } = DefaultOptions.SpanCapacity; + + [ManifestSetting( + DisplayName = "Metric Point Capacity", + Description = "Maximum number of recent metric points retained in memory.", + Category = "Diagnostics", + DefaultValue = "25000", + RestartRequired = true)] + public int MetricPointCapacity { get; set; } = DefaultOptions.MetricPointCapacity; + + [ManifestSetting( + DisplayName = "Log Record Capacity", + Description = "Maximum number of recent OTLP log records retained in memory.", + Category = "Diagnostics", + DefaultValue = "10000", + RestartRequired = true)] + public int LogRecordCapacity { get; set; } = DefaultOptions.LogRecordCapacity; + + [ManifestSetting( + DisplayName = "Resource Capacity", + Description = "Maximum number of recent telemetry resources retained in memory.", + Category = "Diagnostics", + DefaultValue = "500", + RestartRequired = true)] + public int ResourceCapacity { get; set; } = DefaultOptions.ResourceCapacity; + + [ManifestSetting( + DisplayName = "Subscriber Channel Capacity", + Description = "Maximum queued live updates per subscriber before updates are dropped.", + Category = "Diagnostics", + DefaultValue = "1000", + RestartRequired = true)] + public int SubscriberChannelCapacity { get; set; } = DefaultOptions.SubscriberChannelCapacity; + + [ManifestSetting( + DisplayName = "Max HTTP Request Body Size", + Description = "Maximum OTLP HTTP/protobuf request body size in bytes.", + Category = "Diagnostics", + DefaultValue = "10485760", + RestartRequired = true)] + public long MaxHttpRequestBodySize { get; set; } = DefaultOptions.MaxHttpRequestBodySize; + + public void ConfigureServices(IServiceCollection services) + { + services.AddOpenTelemetryDiagnosticsServices(ConfigureOptions); + } + + public void MapEndpoints(IEndpointRouteBuilder endpoints, IHostEnvironment? environment) + { + endpoints.MapOpenTelemetryHttpProtobufCollector(); + endpoints.MapOpenTelemetryGrpcCollector(); + endpoints.MapOpenTelemetryHub(); + } + + private void ConfigureOptions(OpenTelemetryDiagnosticsOptions options) + { + options.TraceCapacity = TraceCapacity; + options.SpanCapacity = SpanCapacity; + options.MetricPointCapacity = MetricPointCapacity; + options.LogRecordCapacity = LogRecordCapacity; + options.ResourceCapacity = ResourceCapacity; + options.SubscriberChannelCapacity = SubscriberChannelCapacity; + options.MaxHttpRequestBodySize = MaxHttpRequestBodySize; + } +} diff --git a/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs b/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs index b41b8bec2..043008a60 100644 --- a/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs +++ b/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs @@ -1,5 +1,4 @@ using Elsa.Caching.Features; -using Elsa.Expressions.Options; using Elsa.Common.Features; using Elsa.Expressions.Features; using Elsa.Extensions; @@ -60,7 +59,6 @@ public class JavaScriptFeature : FeatureBase public override void Apply() { Services.Configure(JintOptions); - Services.Configure(JavaScriptExceptionTypeAliasRegistrar.Register); // JavaScript services. Services @@ -96,4 +94,4 @@ public class JavaScriptFeature : FeatureBase // UI property handlers. Services.AddScoped(); } -} +} \ No newline at end of file diff --git a/src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs b/src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs deleted file mode 100644 index dea8c76a7..000000000 --- a/src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Reflection; -using Acornima; -using Elsa.Expressions.Options; -using Jint; -using Jint.Runtime; - -namespace Elsa.Expressions.JavaScript; - -internal static class JavaScriptExceptionTypeAliasRegistrar -{ - public static void Register(ExpressionOptions options) - { - options.RegisterTypeAlias(typeof(ScriptPreparationException), nameof(ScriptPreparationException)); - options.RegisterTypeAlias(typeof(JavaScriptException), nameof(JavaScriptException)); - options.RegisterTypeAlias(typeof(SyntaxErrorException), nameof(SyntaxErrorException)); - - var wrapperExceptionType = typeof(JavaScriptException).GetNestedType("JavaScriptErrorWrapperException", BindingFlags.Public | BindingFlags.NonPublic); - if (wrapperExceptionType != null) - options.RegisterTypeAlias(wrapperExceptionType, "Jint.JavaScriptErrorWrapperException"); - } -} diff --git a/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs b/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs index 1b5f26760..8111b335b 100644 --- a/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs +++ b/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs @@ -8,7 +8,6 @@ using Elsa.Expressions.JavaScript.Providers; using Elsa.Expressions.JavaScript.Services; using Elsa.Expressions.JavaScript.TypeDefinitions.Contracts; using Elsa.Expressions.JavaScript.TypeDefinitions.Services; -using Elsa.Expressions.Options; using Elsa.Extensions; using Elsa.PackageManifest.Generator.Hints; using Elsa.Workflows; @@ -105,7 +104,6 @@ public class JavaScriptFeature : IShellFeature options.DisableWrappers = DisableWrappers; options.DisableVariableCopying = DisableVariableCopying; }); - services.Configure(JavaScriptExceptionTypeAliasRegistrar.Register); // JavaScript services. services diff --git a/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs b/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs index 5e448a8a2..866344e0b 100644 --- a/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs +++ b/src/modules/Elsa.Expressions/Options/ExpressionOptions.cs @@ -51,7 +51,7 @@ public class ExpressionOptions /// Gets the type alias dictionary. /// public IDictionary AliasTypeDictionary { get; set; } - + /// /// Registers a well-known type alias. /// diff --git a/src/modules/Elsa.Http/Features/HttpFeature.cs b/src/modules/Elsa.Http/Features/HttpFeature.cs index 441789ee4..6df56020f 100644 --- a/src/modules/Elsa.Http/Features/HttpFeature.cs +++ b/src/modules/Elsa.Http/Features/HttpFeature.cs @@ -1,5 +1,5 @@ using System.Net; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -247,7 +247,7 @@ public class HttpFeature(IModule module) : FeatureBase(module) foreach (var httpWorkflowInstanceIdSelectorType in HttpWorkflowInstanceIdSelectorTypes) Services.AddScoped(typeof(IHttpWorkflowInstanceIdSelector), httpWorkflowInstanceIdSelectorType); - Services.Configure(options => + Services.Configure(options => { options.AddTypeAlias("HttpRequest"); options.AddTypeAlias("HttpResponse"); diff --git a/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs b/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs index 956460357..b59c0874b 100644 --- a/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs +++ b/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs @@ -1,7 +1,7 @@ using System.Net; using CShells.AspNetCore.Features; using CShells.Features; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Http.Bookmarks; using Elsa.Http.ContentWriters; @@ -218,7 +218,7 @@ public class HttpFeature : IMiddlewareShellFeature foreach (var httpWorkflowInstanceIdSelectorType in HttpWorkflowInstanceIdSelectorTypes) services.AddScoped(typeof(IHttpWorkflowInstanceIdSelector), httpWorkflowInstanceIdSelectorType); - services.Configure(options => + services.Configure(options => { options.AddTypeAlias("HttpRequest"); options.AddTypeAlias("HttpResponse"); diff --git a/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs b/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs index 104a90694..0c8e27392 100644 --- a/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs +++ b/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs @@ -1,4 +1,3 @@ -using Elsa.Expressions.Options; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Workflows.Management.Entities; @@ -27,7 +26,6 @@ public class EFCoreWorkflowDefinitionPersistenceFeature(IModule module) : Persis public override void Apply() { base.Apply(); - Services.Configure(options => options.RegisterTypeAlias(EFCoreWorkflowDefinitionStore.WorkflowDefinitionStateType, "EFCoreWorkflowDefinitionState")); AddEntityStore(); } -} +} \ No newline at end of file diff --git a/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionStore.cs b/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionStore.cs index 451792359..e805caeaa 100644 --- a/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionStore.cs @@ -22,8 +22,6 @@ namespace Elsa.Persistence.EFCore.Modules.Management; public class EFCoreWorkflowDefinitionStore(EntityStore store, IPayloadSerializer payloadSerializer, ILogger logger) : IWorkflowDefinitionStore { - internal static Type WorkflowDefinitionStateType => typeof(WorkflowDefinitionState); - /// public async Task FindAsync(WorkflowDefinitionFilter filter, CancellationToken cancellationToken = default) { @@ -269,4 +267,4 @@ public class EFCoreWorkflowDefinitionStore(EntityStore Outcomes { get; set; } = new List(); public IDictionary CustomProperties { get; set; } = new Dictionary(); } -} +} \ No newline at end of file diff --git a/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs b/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs index 7bac060de..df06db78e 100644 --- a/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs +++ b/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs @@ -1,6 +1,6 @@ using Elsa.Common.Features; using Elsa.Common.Multitenancy; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -58,7 +58,7 @@ public class SchedulingFeature : FeatureBase // Graceful shutdown: register scheduled-trigger ingress for diagnostic visibility (FR-006). .AddSingleton(); - Services.Configure(options => + Services.Configure(options => { options.AddTypeAlias(); options.AddTypeAlias(); diff --git a/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs b/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs index 0c960b2cc..1459795d7 100644 --- a/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs +++ b/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs @@ -1,6 +1,7 @@ using CShells.Features; using Elsa.Common.Multitenancy; using Elsa.Common.ShellFeatures; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Scheduling.Bookmarks; using Elsa.Scheduling.Handlers; @@ -49,5 +50,15 @@ public class SchedulingFeature : IShellFeature .AddHandlersFrom() .AddTriggerPayloadValidator() .AddActivitiesFrom(); + + services.Configure(options => + { + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + }); } } diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs index 829720b25..819d95a64 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs @@ -15,14 +15,22 @@ internal class Endpoint(IActivityExecutionStore store) : ElsaEndpointWithoutRequ /// public override void Configure() { - Get("/activity-executions/{id}"); + Get("/activity-executions/{id}", "/activity-executions/{*id}", "/activity-executions/by-id"); ConfigurePermissions("read:activity-execution"); } /// public override async Task HandleAsync(CancellationToken cancellationToken) { - var id = Route("id"); + var id = Query("id", false) ?? Route("id", false); + + if (string.IsNullOrWhiteSpace(id)) + { + AddError("The activity execution ID is required."); + await Send.ErrorsAsync(cancellation: cancellationToken); + return; + } + var filter = new ActivityExecutionRecordFilter { Id = id @@ -38,4 +46,4 @@ internal class Endpoint(IActivityExecutionStore store) : ElsaEndpointWithoutRequ await Send.OkAsync(record, cancellationToken); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs index b65421cd1..71bfbb4a6 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs @@ -1,12 +1,13 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; using Elsa.Extensions; using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Memory; using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; using JetBrains.Annotations; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Activities.Flowchart.Serialization; @@ -14,7 +15,7 @@ namespace Elsa.Workflows.Activities.Flowchart.Serialization; /// A JSON converter for . /// [UsedImplicitly] -public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IWellKnownTypeRegistry wellKnownTypeRegistry, ILoggerFactory loggerFactory) : JsonConverter +public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IOptions workflowJsonOptions, ILoggerFactory loggerFactory) : JsonConverter { private const string AllActivitiesKey = "allActivities"; private const string AllConnectionsKey = "allConnections"; @@ -47,7 +48,7 @@ public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IWellK var variables = variablesElement.ValueKind != JsonValueKind.Undefined ? variablesElement.Deserialize>(options) ?? new List() : new List(); var polymorphicOptions = options.Clone(); - polymorphicOptions.Converters.Add(new PolymorphicDictionaryConverter(options, wellKnownTypeRegistry)); + polymorphicOptions.Converters.Add(new PolymorphicDictionaryConverter(options, workflowJsonOptions.Value)); var metadataElement = doc.RootElement.TryGetProperty("metadata", out var metadataEl) ? metadataEl : default; var metadata = metadataElement.ValueKind != JsonValueKind.Undefined ? metadataElement.Deserialize>(polymorphicOptions) ?? new Dictionary() : new Dictionary(); @@ -105,7 +106,7 @@ public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IWellK var flowchartSerializerOptions = new JsonSerializerOptions(options); flowchartSerializerOptions.Converters.Add(new ConnectionJsonConverter(activityDictionary, loggerFactory)); - flowchartSerializerOptions.Converters.Add(new PolymorphicDictionaryConverter(options, wellKnownTypeRegistry)); + flowchartSerializerOptions.Converters.Add(new PolymorphicDictionaryConverter(options, workflowJsonOptions.Value)); JsonSerializer.Serialize(writer, model, flowchartSerializerOptions); } @@ -218,4 +219,4 @@ public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IWellK // drop any half‑baked entries return raw.Where(c => c != null && c.Source.Activity != null! && c.Target.Activity != null!).Cast().ToList(); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs new file mode 100644 index 000000000..851cc8214 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs @@ -0,0 +1,66 @@ +using Elsa.Common.Models; +using Elsa.Extensions; +using Elsa.Workflows; +using Elsa.Workflows.Activities.Flowchart.Models; +using Elsa.Workflows.Exceptions; +using Elsa.Workflows.IncidentStrategies; +using Elsa.Workflows.Memory; +using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Services; +using Elsa.Workflows.State; +using Newtonsoft.Json.Linq; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +/// +/// Extends . +/// +public static class WorkflowJsonOptionsExtensions +{ + /// + /// Registers using its CLR type name. + /// + public static void AddTypeAlias(this WorkflowJsonOptions options) => options.RegisterTypeAlias(typeof(T), typeof(T).Name); + + /// + /// Registers using the specified alias. + /// + public static void AddTypeAlias(this WorkflowJsonOptions options, string alias) => options.RegisterTypeAlias(typeof(T), alias); + + /// + /// Registers the built-in workflow JSON aliases. + /// + public static void RegisterWorkflowTypeAliases(this WorkflowJsonOptions options) + { + options.RegisterTypeAlias(typeof(ExceptionState), nameof(ExceptionState)); + options.RegisterTypeAlias(typeof(FaultException), nameof(FaultException)); + options.RegisterTypeAlias(typeof(VariablesDictionary), nameof(VariablesDictionary)); + options.RegisterTypeAlias(typeof(Token), nameof(Token)); + options.RegisterTypeAlias(typeof(FlowJoinMode), "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core"); + options.RegisterTypeAlias(typeof(FlowJoinMode), typeof(FlowJoinMode).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(FlowJoinMode), nameof(FlowJoinMode)); + options.RegisterTypeAlias(typeof(WorkflowStorageDriver), typeof(WorkflowStorageDriver).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); + options.RegisterTypeAlias(typeof(WorkflowInstanceStorageDriver), typeof(WorkflowInstanceStorageDriver).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(WorkflowInstanceStorageDriver), nameof(WorkflowInstanceStorageDriver)); + options.RegisterTypeAlias(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(MemoryStorageDriver), nameof(MemoryStorageDriver)); + options.RegisterTypeAlias(typeof(FaultStrategy), typeof(FaultStrategy).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(FaultStrategy), nameof(FaultStrategy)); + options.RegisterTypeAlias(typeof(ContinueWithIncidentsStrategy), typeof(ContinueWithIncidentsStrategy).GetSimpleAssemblyQualifiedName()); + options.RegisterTypeAlias(typeof(ContinueWithIncidentsStrategy), nameof(ContinueWithIncidentsStrategy)); + options.RegisterTypeAlias(typeof(Exception), nameof(Exception)); + options.RegisterTypeAlias(typeof(ArgumentException), nameof(ArgumentException)); + options.RegisterTypeAlias(typeof(ArgumentNullException), nameof(ArgumentNullException)); + options.RegisterTypeAlias(typeof(InvalidOperationException), nameof(InvalidOperationException)); + options.RegisterTypeAlias(typeof(NullReferenceException), nameof(NullReferenceException)); + options.RegisterTypeAlias(typeof(OperationCanceledException), nameof(OperationCanceledException)); + options.RegisterTypeAlias(typeof(TaskCanceledException), nameof(TaskCanceledException)); + options.RegisterTypeAlias(typeof(TimeoutException), nameof(TimeoutException)); + options.RegisterTypeAlias(typeof(NotSupportedException), nameof(NotSupportedException)); + options.RegisterTypeAlias(typeof(JObject), nameof(JObject)); + options.RegisterTypeAlias(typeof(JArray), nameof(JArray)); + } +} diff --git a/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs b/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs index ab3a000a2..5414125df 100644 --- a/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs +++ b/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs @@ -4,6 +4,7 @@ using Elsa.Features.Services; using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Activities.Flowchart.Options; using Elsa.Workflows.Activities.Flowchart.Serialization; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.Features; @@ -33,10 +34,7 @@ public class FlowchartFeature : FeatureBase if (FlowchartOptionsConfigurator != null) Services.Configure(FlowchartOptionsConfigurator); - } - public override void Configure() - { - Module.AddTypeAlias("FlowScope"); + Services.Configure(options => options.AddTypeAlias("FlowScope")); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs index 4822214f9..005b87d09 100644 --- a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs +++ b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs @@ -2,16 +2,14 @@ using Elsa.Common; using Elsa.Common.Features; using Elsa.Common.Serialization; using Elsa.Expressions.Features; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Workflows.ActivationValidators; -using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Builders; using Elsa.Workflows.CommitStates; -using Elsa.Workflows.Exceptions; using Elsa.Workflows.IncidentStrategies; using Elsa.Workflows.LogPersistence; using Elsa.Workflows.LogPersistence.Strategies; @@ -24,14 +22,12 @@ using Elsa.Workflows.Serialization.Configurators; using Elsa.Workflows.Serialization.Helpers; using Elsa.Workflows.Serialization.Serializers; using Elsa.Workflows.Services; -using Elsa.Workflows.State; using Elsa.Workflows.UIHints.CheckList; using Elsa.Workflows.UIHints.Dictionary; using Elsa.Workflows.UIHints.Dropdown; using Elsa.Workflows.UIHints.JsonEditor; using Elsa.Workflows.UIHints.RadioList; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json.Linq; namespace Elsa.Workflows.Features; @@ -91,7 +87,12 @@ public class WorkflowsFeature : FeatureBase /// /// A delegate to configure the . /// - public Action ActivityExecutionPipeline { get; set; } = builder => builder.UseDefaultActivityInvoker(); + public Action ActivityExecutionPipeline { get; set; } = builder => builder + .UseLogging() + .UseExceptionHandling() + .UseExecutionLogging() + .UseNotifications() + .UseDefaultActivityInvoker(); /// /// Fluent method to set . @@ -164,35 +165,7 @@ public class WorkflowsFeature : FeatureBase private void AddElsaCore(IServiceCollection services) { - services.Configure(options => - { - options.RegisterTypeAlias(typeof(ExceptionState), nameof(ExceptionState)); - options.RegisterTypeAlias(typeof(FaultException), nameof(FaultException)); - options.RegisterTypeAlias(typeof(VariablesDictionary), nameof(VariablesDictionary)); - options.RegisterTypeAlias(typeof(Token), nameof(Token)); - options.RegisterTypeAlias(typeof(FlowJoinMode), "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core"); - options.RegisterTypeAlias(typeof(FlowJoinMode), typeof(FlowJoinMode).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(FlowJoinMode), nameof(FlowJoinMode)); - options.RegisterTypeAlias(typeof(WorkflowStorageDriver), typeof(WorkflowStorageDriver).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); - options.RegisterTypeAlias(typeof(WorkflowInstanceStorageDriver), typeof(WorkflowInstanceStorageDriver).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(WorkflowInstanceStorageDriver), nameof(WorkflowInstanceStorageDriver)); - options.RegisterTypeAlias(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(MemoryStorageDriver), nameof(MemoryStorageDriver)); - options.RegisterTypeAlias(typeof(FaultStrategy), typeof(FaultStrategy).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(FaultStrategy), nameof(FaultStrategy)); - options.RegisterTypeAlias(typeof(Exception), nameof(Exception)); - options.RegisterTypeAlias(typeof(ArgumentException), nameof(ArgumentException)); - options.RegisterTypeAlias(typeof(ArgumentNullException), nameof(ArgumentNullException)); - options.RegisterTypeAlias(typeof(InvalidOperationException), nameof(InvalidOperationException)); - options.RegisterTypeAlias(typeof(NullReferenceException), nameof(NullReferenceException)); - options.RegisterTypeAlias(typeof(OperationCanceledException), nameof(OperationCanceledException)); - options.RegisterTypeAlias(typeof(TaskCanceledException), nameof(TaskCanceledException)); - options.RegisterTypeAlias(typeof(TimeoutException), nameof(TimeoutException)); - options.RegisterTypeAlias(typeof(NotSupportedException), nameof(NotSupportedException)); - options.RegisterTypeAlias(typeof(JObject), nameof(JObject)); - options.RegisterTypeAlias(typeof(JArray), nameof(JArray)); - }); + services.Configure(options => options.RegisterWorkflowTypeAliases()); services diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ExcludeFromHashConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ExcludeFromHashConverter.cs index b425eb865..4c84b5de9 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ExcludeFromHashConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ExcludeFromHashConverter.cs @@ -35,7 +35,9 @@ public class ExcludeFromHashConverter : JsonConverter var propertyValue = property.GetValue(value); if (ShouldIgnoreProperty(metadata.JsonIgnoreCondition, property.PropertyType, propertyValue)) + { continue; + } writer.WritePropertyName(property.Name); JsonSerializer.Serialize(writer, propertyValue, newOptions); diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs index ecefa40b6..888c732e9 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs @@ -1,9 +1,10 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; -using Elsa.Expressions.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Helpers; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Converters; @@ -12,12 +13,12 @@ namespace Elsa.Workflows.Serialization.Converters; /// public class OutputJsonConverter : JsonConverter?> { - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; + private readonly WorkflowJsonOptions _workflowJsonOptions; /// - public OutputJsonConverter(IWellKnownTypeRegistry wellKnownTypeRegistry) + public OutputJsonConverter(IOptions workflowJsonOptions) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; + _workflowJsonOptions = workflowJsonOptions.Value; } /// @@ -50,7 +51,7 @@ public class OutputJsonConverter : JsonConverter?> public override void Write(Utf8JsonWriter writer, Output? value, JsonSerializerOptions options) { var valueType = typeof(T); - var valueTypeAlias = _wellKnownTypeRegistry.GetAliasOrDefault(valueType); + var valueTypeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, valueType); var model = new { @@ -63,4 +64,4 @@ public class OutputJsonConverter : JsonConverter?> JsonSerializer.Serialize(writer, model, options); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs index 3e0060aa8..12653413a 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs @@ -1,6 +1,6 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; +using Elsa.Workflows.Serialization.Options; namespace Elsa.Workflows.Serialization.Converters; @@ -12,9 +12,9 @@ public class PolymorphicDictionaryConverter : JsonConverter _objectConverter; /// - public PolymorphicDictionaryConverter(JsonSerializerOptions options, IWellKnownTypeRegistry wellKnownTypeRegistry) + public PolymorphicDictionaryConverter(JsonSerializerOptions options, WorkflowJsonOptions workflowJsonOptions) { - var factory = (JsonConverterFactory)(options.Converters.FirstOrDefault(x => x is PolymorphicObjectConverterFactory) ?? new PolymorphicObjectConverterFactory(wellKnownTypeRegistry)); + var factory = (JsonConverterFactory)(options.Converters.FirstOrDefault(x => x is PolymorphicObjectConverterFactory) ?? new PolymorphicObjectConverterFactory(workflowJsonOptions)); _objectConverter = (JsonConverter)factory.CreateConverter(typeof(object), options)!; } @@ -53,4 +53,4 @@ public class PolymorphicDictionaryConverter : JsonConverter private const string IdPropertyName = "$id"; private const string RefPropertyName = "$ref"; private const string ValuesPropertyName = "$values"; - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; + private readonly WorkflowJsonOptions _workflowJsonOptions; /// /// Initializes a new instance of the class. /// - public PolymorphicObjectConverter(IWellKnownTypeRegistry wellKnownTypeRegistry) + public PolymorphicObjectConverter(IOptions workflowJsonOptions) + : this(workflowJsonOptions.Value) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; + } + + /// + /// Initializes a new instance of the class. + /// + public PolymorphicObjectConverter(WorkflowJsonOptions workflowJsonOptions) + { + _workflowJsonOptions = workflowJsonOptions; } /// /// Initializes a new instance of the class. /// public PolymorphicObjectConverter() + : this(new WorkflowJsonOptions()) { - _wellKnownTypeRegistry = WellKnownTypeRegistry.CreateDefault(); } /// @@ -350,14 +358,12 @@ public class PolymorphicObjectConverter : JsonConverter } // If we found the _type property, attempt to resolve the type. - return typeName != null ? WorkflowJsonTypeResolver.ResolveType(_wellKnownTypeRegistry, typeName) : default; + return typeName != null ? WorkflowJsonTypeResolver.ResolveType(_workflowJsonOptions, typeName, _workflowJsonOptions.AllowLegacyClrTypeNames) : default; } private void WriteTypeMetadata(Utf8JsonWriter writer, Type type) { - if (!WorkflowJsonTypeResolver.TryGetAlias(_wellKnownTypeRegistry, type, out var typeAlias)) - return; - + var typeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, type); writer.WritePropertyName(TypePropertyName); writer.WriteStringValue(typeAlias); } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs index 9bf659435..d1994e820 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs @@ -1,8 +1,8 @@ using System.Dynamic; using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; -using Elsa.Expressions.Services; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Converters; @@ -11,22 +11,30 @@ namespace Elsa.Workflows.Serialization.Converters; /// public class PolymorphicObjectConverterFactory : JsonConverterFactory { - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; + private readonly WorkflowJsonOptions _workflowJsonOptions; /// /// A JSON converter factory that creates instances. /// - public PolymorphicObjectConverterFactory(IWellKnownTypeRegistry wellKnownTypeRegistry) + public PolymorphicObjectConverterFactory(IOptions workflowJsonOptions) + : this(workflowJsonOptions.Value) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; + } + + /// + /// A JSON converter factory that creates instances. + /// + public PolymorphicObjectConverterFactory(WorkflowJsonOptions workflowJsonOptions) + { + _workflowJsonOptions = workflowJsonOptions; } /// /// Default constructor for use with attributes. /// public PolymorphicObjectConverterFactory() + : this(new WorkflowJsonOptions()) { - _wellKnownTypeRegistry = WellKnownTypeRegistry.CreateDefault(); } /// @@ -49,8 +57,8 @@ public class PolymorphicObjectConverterFactory : JsonConverterFactory public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { if (typeof(IDictionary).IsAssignableFrom(typeToConvert)) - return new PolymorphicDictionaryConverter(options, _wellKnownTypeRegistry); + return new PolymorphicDictionaryConverter(options, _workflowJsonOptions); - return new PolymorphicObjectConverter(_wellKnownTypeRegistry); + return new PolymorphicObjectConverter(_workflowJsonOptions); } } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs index c74191e41..34165b414 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs @@ -1,29 +1,36 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; -using Elsa.Extensions; using Elsa.Workflows.Serialization.Helpers; +using Elsa.Workflows.Serialization.Options; using JetBrains.Annotations; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Converters; /// /// Serializes objects to a simple alias representing the type. -/// Unregistered types are written as metadata-only aliases and intentionally deserialize to instead of loading the original CLR type. /// [UsedImplicitly] public class TypeJsonConverter : JsonConverter { - /// - /// Prefix for unregistered type metadata that is not used for CLR type loading during deserialization. - /// - private const string UnregisteredTypeAliasPrefix = "UnregisteredClrType:"; - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; + private readonly WorkflowJsonOptions _workflowJsonOptions; /// - public TypeJsonConverter(IWellKnownTypeRegistry wellKnownTypeRegistry) + public TypeJsonConverter() + : this(new WorkflowJsonOptions()) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; + } + + /// + public TypeJsonConverter(IOptions workflowJsonOptions) + : this(workflowJsonOptions.Value) + { + } + + /// + public TypeJsonConverter(WorkflowJsonOptions workflowJsonOptions) + { + _workflowJsonOptions = workflowJsonOptions; } /// @@ -36,18 +43,14 @@ public class TypeJsonConverter : JsonConverter public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var typeAlias = reader.GetString(); - if (typeAlias?.StartsWith(UnregisteredTypeAliasPrefix, StringComparison.Ordinal) == true) - return typeof(Exception); - return WorkflowJsonTypeResolver.ResolveType(_wellKnownTypeRegistry, typeAlias); + return WorkflowJsonTypeResolver.ResolveType(_workflowJsonOptions, typeAlias, _workflowJsonOptions.AllowLegacyClrTypeNames); } /// public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) { - if (!WorkflowJsonTypeResolver.TryGetAlias(_wellKnownTypeRegistry, value, out var typeAlias)) - typeAlias = $"{UnregisteredTypeAliasPrefix}{value.GetSimpleAssemblyQualifiedName()}"; - + var typeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, value); writer.WriteStringValue(typeAlias); } } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs index 6dcc60b4e..b5f7bf522 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs @@ -1,9 +1,10 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Converters; @@ -17,9 +18,16 @@ public class VariableConverter : JsonConverter /// // ReSharper disable once ContextualLoggerProblem - public VariableConverter(IWellKnownTypeRegistry wellKnownTypeRegistry, ILogger logger) + public VariableConverter(ILogger logger) { - _mapper = new VariableMapper(wellKnownTypeRegistry, logger); + _mapper = new VariableMapper(logger); + } + + /// + // ReSharper disable once ContextualLoggerProblem + public VariableConverter(ILogger logger, IOptions workflowJsonOptions) + { + _mapper = new VariableMapper(logger, workflowJsonOptions); } /// @@ -49,4 +57,4 @@ public class VariableConverter : JsonConverter _options = newOptions; return newOptions; } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs index 293ce4e35..56971c510 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs @@ -1,8 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; using Elsa.Workflows.Memory; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Converters; @@ -11,20 +12,31 @@ namespace Elsa.Workflows.Serialization.Converters; /// public class VariableConverterFactory : JsonConverterFactory { - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; private readonly ILoggerFactory _loggerFactory; + private readonly IOptions? _workflowJsonOptions; /// // ReSharper disable once ContextualLoggerProblem - public VariableConverterFactory(IWellKnownTypeRegistry wellKnownTypeRegistry, ILoggerFactory loggerFactory) + public VariableConverterFactory(ILoggerFactory loggerFactory) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; _loggerFactory = loggerFactory; } + /// + // ReSharper disable once ContextualLoggerProblem + public VariableConverterFactory(ILoggerFactory loggerFactory, IOptions workflowJsonOptions) + { + _loggerFactory = loggerFactory; + _workflowJsonOptions = workflowJsonOptions; + } + /// public override bool CanConvert(Type typeToConvert) => typeof(Variable).IsAssignableFrom(typeToConvert); /// - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => new VariableConverter(_wellKnownTypeRegistry, _loggerFactory.CreateLogger()); -} \ No newline at end of file + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var logger = _loggerFactory.CreateLogger(); + return _workflowJsonOptions != null ? new VariableConverter(logger, _workflowJsonOptions) : new VariableConverter(logger); + } +} diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs b/src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs index 86771b0e8..d5258b9ae 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs @@ -2,13 +2,13 @@ using System.Collections; using System.Collections.ObjectModel; using System.Reflection; using System.Text.Json; -using Elsa.Expressions.Contracts; using Elsa.Extensions; +using Elsa.Workflows.Serialization.Options; namespace Elsa.Workflows.Serialization.Helpers; /// -/// Resolves workflow JSON type aliases without loading arbitrary CLR type names. +/// Resolves workflow JSON type aliases and CLR type names. /// public static class WorkflowJsonTypeResolver { @@ -52,85 +52,47 @@ public static class WorkflowJsonTypeResolver [typeof(IDictionary)] = typeof(Dictionary) }; - /// - /// Resolves the specified workflow JSON type alias. - /// - public static Type ResolveType(IWellKnownTypeRegistry wellKnownTypeRegistry, string? typeAlias) + public static Type ResolveType(WorkflowJsonOptions workflowJsonOptions, string? typeAlias, bool allowLegacyClrTypeNames = true) { if (string.IsNullOrWhiteSpace(typeAlias)) throw new JsonException("The workflow JSON type alias is missing."); - if (TryResolveType(wellKnownTypeRegistry, typeAlias, out var type)) + if (TryResolveType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, out var type)) return type; - throw new JsonException( - $"Unknown workflow JSON type alias '{typeAlias}'. Only registered aliases and supported compound aliases can be deserialized."); + var supportedTypeNames = allowLegacyClrTypeNames + ? "Registered aliases, supported compound aliases, and CLR type names" + : "Registered aliases, supported compound aliases, and registered legacy CLR type names"; + throw new JsonException($"Unknown workflow JSON type alias '{typeAlias}'. {supportedTypeNames} can be deserialized."); } - /// - /// Attempts to resolve the specified workflow JSON type alias. - /// - public static bool TryResolveType(IWellKnownTypeRegistry wellKnownTypeRegistry, string typeAlias, out Type type) + public static bool TryResolveType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, out Type type) + { + return TryResolveType(workflowJsonOptions, typeAlias, true, out type); + } + + public static bool TryResolveType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, out Type type) { IReadOnlyList? registeredTypes = null; - return TryResolveType(wellKnownTypeRegistry, typeAlias, ref registeredTypes, out type); + return TryResolveType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type); } - private static bool TryResolveType(IWellKnownTypeRegistry wellKnownTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) + public static bool TryGetAlias(WorkflowJsonOptions workflowJsonOptions, Type type, out string alias) { - if (wellKnownTypeRegistry.TryGetType(typeAlias, out var registeredType)) - { - type = registeredType; - return true; - } - - if (TryResolveArrayType(wellKnownTypeRegistry, typeAlias, ref registeredTypes, out var arrayType)) - { - type = arrayType; - return true; - } - - if (TryResolveGenericCollectionType(wellKnownTypeRegistry, typeAlias, ref registeredTypes, out var genericCollectionType)) - { - type = genericCollectionType; - return true; - } - - if (TryResolveRegisteredLegacyTypeName(wellKnownTypeRegistry, typeAlias, ref registeredTypes, out var legacyType)) - { - type = legacyType; - return true; - } - - type = null!; - return false; - } - - /// - /// Attempts to return a workflow JSON type alias that this resolver can read back. - /// - public static bool TryGetAlias(IWellKnownTypeRegistry wellKnownTypeRegistry, Type type, out string alias) - { - if (wellKnownTypeRegistry.TryGetAlias(type, out alias!)) + if (workflowJsonOptions.TryGetAlias(type, out alias!)) return true; - if (type.IsArray) + if (type.IsArray && TryGetAlias(workflowJsonOptions, type.GetElementType()!, out var elementTypeAlias)) { - var elementType = type.GetElementType()!; - - if (TryGetAlias(wellKnownTypeRegistry, elementType, out var elementTypeAlias)) - { - alias = $"{elementTypeAlias}[]"; - return true; - } + alias = $"{elementTypeAlias}[]"; + return true; } if (type is { IsGenericType: true, GenericTypeArguments.Length: 1 }) { var genericTypeDefinition = type.GetGenericTypeDefinition(); - if (TryGetWritableGenericCollectionAlias(genericTypeDefinition, out var genericTypeAlias) && - TryGetAlias(wellKnownTypeRegistry, type.GenericTypeArguments[0], out var elementTypeAlias)) + TryGetAlias(workflowJsonOptions, type.GenericTypeArguments[0], out elementTypeAlias)) { alias = $"{genericTypeAlias}<{elementTypeAlias}>"; return true; @@ -141,9 +103,17 @@ public static class WorkflowJsonTypeResolver return false; } - /// - /// Attempts to map a supported collection interface type to an instantiable concrete type. - /// + public static string GetAliasOrLegacyClrTypeName(WorkflowJsonOptions workflowJsonOptions, Type type) + { + if (TryGetAlias(workflowJsonOptions, type, out var alias)) + return alias; + + if (!workflowJsonOptions.AllowLegacyClrTypeNames) + throw new JsonException($"Type '{type}' is not registered as a workflow JSON type alias."); + + return type.GetSimpleAssemblyQualifiedName(); + } + public static bool TryGetInstantiableCollectionType(Type type, out Type instantiableType) { if (type.IsGenericType) @@ -163,22 +133,41 @@ public static class WorkflowJsonTypeResolver return false; } - private static bool TryResolveArrayType(IWellKnownTypeRegistry wellKnownTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) + private static bool TryResolveType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) + { + if (workflowJsonOptions.TryGetType(typeAlias, out type!)) + return true; + + if (TryResolveArrayType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) + return true; + + if (TryResolveGenericCollectionType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) + return true; + + if (TryResolveRegisteredLegacyTypeName(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) + return true; + + if (allowLegacyClrTypeNames && TryResolveClrTypeName(typeAlias, out type)) + return true; + + type = null!; + return false; + } + + private static bool TryResolveArrayType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) { type = null!; - if (!typeAlias.EndsWith("[]", StringComparison.Ordinal)) return false; - var elementTypeAlias = typeAlias[..^2]; - if (!TryResolveType(wellKnownTypeRegistry, elementTypeAlias, ref registeredTypes, out var elementType)) + if (!TryResolveType(workflowJsonOptions, typeAlias[..^2], allowLegacyClrTypeNames, ref registeredTypes, out var elementType)) return false; type = elementType.MakeArrayType(); return true; } - private static bool TryResolveGenericCollectionType(IWellKnownTypeRegistry wellKnownTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) + private static bool TryResolveGenericCollectionType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) { type = null!; var genericStart = typeAlias.IndexOf('<', StringComparison.Ordinal); @@ -186,12 +175,10 @@ public static class WorkflowJsonTypeResolver if (genericStart <= 0 || !typeAlias.EndsWith(">", StringComparison.Ordinal)) return false; - var genericTypeAlias = typeAlias[..genericStart]; - if (!GenericCollectionTypes.TryGetValue(genericTypeAlias, out var genericTypeDefinition)) + if (!GenericCollectionTypes.TryGetValue(typeAlias[..genericStart], out var genericTypeDefinition)) return false; - var elementTypeAlias = typeAlias[(genericStart + 1)..^1]; - if (!TryResolveType(wellKnownTypeRegistry, elementTypeAlias, ref registeredTypes, out var elementType)) + if (!TryResolveType(workflowJsonOptions, typeAlias[(genericStart + 1)..^1], allowLegacyClrTypeNames, ref registeredTypes, out var elementType)) return false; type = genericTypeDefinition.MakeGenericType(elementType); @@ -205,59 +192,60 @@ public static class WorkflowJsonTypeResolver if (GenericCollectionInterfaceMappings.TryGetValue(genericTypeDefinition, out var instantiableGenericTypeDefinition) && GenericCollectionAliases.TryGetValue(instantiableGenericTypeDefinition, out alias!)) - { return true; - } alias = null!; return false; } - private static bool TryResolveRegisteredLegacyTypeName(IWellKnownTypeRegistry wellKnownTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) + private static bool TryResolveClrTypeName(string typeAlias, out Type type) { - registeredTypes ??= GetRegisteredTypes(wellKnownTypeRegistry); + try + { + type = Type.GetType(typeAlias, false)!; + return type != null; + } + catch (Exception e) when (e is ArgumentException or FileLoadException or FileNotFoundException or TypeLoadException or BadImageFormatException) + { + type = null!; + return false; + } + } + + private static bool TryResolveRegisteredLegacyTypeName(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) + { + registeredTypes ??= workflowJsonOptions.ListTypes().ToArray(); var registeredTypeSnapshot = registeredTypes; - if (TryResolveRegisteredSimpleAssemblyQualifiedName(registeredTypeSnapshot, typeAlias, out type)) + type = registeredTypeSnapshot.FirstOrDefault(x => + string.Equals(x.GetSimpleAssemblyQualifiedName(), typeAlias, StringComparison.Ordinal) || + string.Equals(x.AssemblyQualifiedName, typeAlias, StringComparison.Ordinal))!; + + if (type != null) return true; - if (TryResolveLegacyGenericCollectionTypeName(wellKnownTypeRegistry, typeAlias, ref registeredTypes, out type)) + if (TryResolveLegacyGenericCollectionTypeName(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) return true; - Type? resolvedType; - try { - resolvedType = Type.GetType( + var resolvedType = Type.GetType( typeAlias, assemblyName => ResolveAssembly(registeredTypeSnapshot, assemblyName), (assembly, typeName, ignoreCase) => ResolveType(registeredTypeSnapshot, assembly, typeName, ignoreCase), false); + + type = resolvedType!; + return resolvedType != null; } catch (Exception e) when (e is ArgumentException or FileLoadException) { - resolvedType = null; + type = null!; + return false; } - - type = resolvedType!; - return resolvedType != null; } - private static IReadOnlyList GetRegisteredTypes(IWellKnownTypeRegistry wellKnownTypeRegistry) - { - return wellKnownTypeRegistry.ListTypes().ToArray(); - } - - private static bool TryResolveRegisteredSimpleAssemblyQualifiedName(IEnumerable registeredTypes, string typeAlias, out Type type) - { - type = registeredTypes.FirstOrDefault(x => - string.Equals(x.GetSimpleAssemblyQualifiedName(), typeAlias, StringComparison.Ordinal) || - string.Equals(x.AssemblyQualifiedName, typeAlias, StringComparison.Ordinal))!; - - return type != null; - } - - private static bool TryResolveLegacyGenericCollectionTypeName(IWellKnownTypeRegistry wellKnownTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) + private static bool TryResolveLegacyGenericCollectionTypeName(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) { type = null!; @@ -273,11 +261,9 @@ public static class WorkflowJsonTypeResolver if (!string.Equals(assemblyName, genericTypeDefinition.Assembly.GetName().Name, StringComparison.Ordinal)) continue; - var elementTypeAlias = typeAlias[prefix.Length..separatorIndex]; - if (!TryResolveType(wellKnownTypeRegistry, elementTypeAlias, ref registeredTypes, out var elementType)) + if (!TryResolveType(workflowJsonOptions, typeAlias[prefix.Length..separatorIndex], allowLegacyClrTypeNames, ref registeredTypes, out var elementType)) return false; - // The resolver only closes known collection definitions over registered element types. #pragma warning disable IL2055 type = genericTypeDefinition.MakeGenericType(elementType); #pragma warning restore IL2055 diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs b/src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs new file mode 100644 index 000000000..204257a52 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs @@ -0,0 +1,91 @@ +using System.Dynamic; +using System.Text.Json; +using System.Text.Json.Nodes; +using Elsa.Extensions; + +namespace Elsa.Workflows.Serialization.Options; + +/// +/// Options used by workflow JSON serializers to map stable type aliases to CLR types. +/// +public class WorkflowJsonOptions +{ + private readonly Dictionary _typesByAlias = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _aliasesByType = new(); + + /// + /// Initializes a new instance of the class. + /// + public WorkflowJsonOptions() + { + RegisterDefaultTypeAliases(); + } + + /// + /// Gets or sets a value indicating whether unrestricted CLR type names can be resolved for backwards compatibility. + /// + public bool AllowLegacyClrTypeNames { get; set; } = true; + + /// + /// Registers a type alias. + /// + public WorkflowJsonOptions RegisterTypeAlias(Type type, string alias) + { + _typesByAlias[alias] = type; + _aliasesByType[type] = alias; + + if (type.IsPrimitive || type.IsValueType && Nullable.GetUnderlyingType(type) == null) + { + var nullableType = typeof(Nullable<>).MakeGenericType(type); + var nullableAlias = alias + "?"; + _typesByAlias[nullableAlias] = nullableType; + _aliasesByType[nullableType] = nullableAlias; + } + + return this; + } + + /// + /// Attempts to resolve the specified alias to a type. + /// + public bool TryGetType(string alias, out Type type) => _typesByAlias.TryGetValue(alias, out type!); + + /// + /// Attempts to get the primary alias registered for the specified type. + /// + public bool TryGetAlias(Type type, out string alias) => _aliasesByType.TryGetValue(type, out alias!); + + /// + /// Lists all registered types. + /// + public IEnumerable ListTypes() => _typesByAlias.Values.Distinct(); + + private void RegisterDefaultTypeAliases() + { + this.AddTypeAlias("Int16"); + this.AddTypeAlias("Int32"); + this.AddTypeAlias("Int64"); + this.AddTypeAlias("Long"); + this.AddTypeAlias("Single"); + this.AddTypeAlias("Object"); + this.AddTypeAlias("String"); + this.AddTypeAlias("Boolean"); + this.AddTypeAlias("Decimal"); + this.AddTypeAlias("Double"); + this.AddTypeAlias("ByteArray"); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias("JSON"); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias(); + this.AddTypeAlias>("StringDictionary"); + this.AddTypeAlias>("ObjectDictionary"); + this.AddTypeAlias>("StringMap"); + this.AddTypeAlias>("ObjectMap"); + } +} diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs index 9dab96949..60899d5c2 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs @@ -1,6 +1,7 @@ using System.Text.Json; -using Elsa.Expressions.Contracts; using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Serializers; @@ -12,7 +13,15 @@ public class BookmarkPayloadSerializer : IBookmarkPayloadSerializer /// /// Initializes a new instance of the class. /// - public BookmarkPayloadSerializer(IWellKnownTypeRegistry wellKnownTypeRegistry) + public BookmarkPayloadSerializer() + : this(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) + { + } + + /// + /// Initializes a new instance of the class. + /// + public BookmarkPayloadSerializer(IOptions workflowJsonOptions) { _settings = new JsonSerializerOptions { @@ -21,7 +30,7 @@ public class BookmarkPayloadSerializer : IBookmarkPayloadSerializer PropertyNameCaseInsensitive = true, }; - _settings.Converters.Add(new TypeJsonConverter(wellKnownTypeRegistry)); + _settings.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); _settings.Converters.Add(new FuncExpressionValueConverter()); } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs index faf4215b8..989cf6265 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs @@ -1,11 +1,12 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using Elsa.Common.Serialization; -using Elsa.Expressions.Contracts; using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.ReferenceHandlers; using Elsa.Workflows.State; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Serializers; @@ -13,18 +14,26 @@ namespace Elsa.Workflows.Serialization.Serializers; /// Serializes and deserializes workflow states from and to JSON. /// public class JsonWorkflowStateSerializer : ConfigurableSerializer, IWorkflowStateSerializer -{ - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; - private readonly ILoggerFactory _loggerFactory; + { + private readonly ILoggerFactory _loggerFactory; + private readonly IOptions _workflowJsonOptions; /// /// Initializes a new instance of the class. /// - public JsonWorkflowStateSerializer(IServiceProvider serviceProvider, IWellKnownTypeRegistry wellKnownTypeRegistry, ILoggerFactory loggerFactory) + public JsonWorkflowStateSerializer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) + : this(serviceProvider, loggerFactory, Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) + { + } + + /// + /// Initializes a new instance of the class. + /// + public JsonWorkflowStateSerializer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IOptions workflowJsonOptions) : base(serviceProvider) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; _loggerFactory = loggerFactory; + _workflowJsonOptions = workflowJsonOptions; } /// @@ -135,9 +144,9 @@ public class JsonWorkflowStateSerializer : ConfigurableSerializer, IWorkflowStat /// protected override void AddConverters(JsonSerializerOptions options) { - options.Converters.Add(new TypeJsonConverter(_wellKnownTypeRegistry)); - options.Converters.Add(new PolymorphicObjectConverterFactory(_wellKnownTypeRegistry)); - options.Converters.Add(new VariableConverterFactory(_wellKnownTypeRegistry, _loggerFactory)); + options.Converters.Add(new TypeJsonConverter(_workflowJsonOptions)); + options.Converters.Add(new PolymorphicObjectConverterFactory(_workflowJsonOptions)); + options.Converters.Add(new VariableConverterFactory(_loggerFactory, _workflowJsonOptions)); options.Converters.Add(new FuncExpressionValueConverter()); } } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs index 281e24b13..9a828338f 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs @@ -3,7 +3,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Common.Serialization; using Elsa.Expressions.Contracts; -using Elsa.Expressions.Services; using Elsa.Workflows.Serialization.Converters; using Microsoft.Extensions.DependencyInjection; @@ -72,10 +71,9 @@ public class SafeSerializer : ConfigurableSerializer, ISafeSerializer protected override void AddConverters(JsonSerializerOptions options) { var expressionDescriptorRegistry = ServiceProvider.GetRequiredService(); - var wellKnownTypeRegistry = ServiceProvider.GetRequiredService(); options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); - options.Converters.Add(new TypeJsonConverter(wellKnownTypeRegistry)); + options.Converters.Add(CreateInstance()); options.Converters.Add(new SafeValueConverterFactory()); options.Converters.Add(new ExpressionJsonConverterFactory(expressionDescriptorRegistry)); options.Converters.Add(new FuncExpressionValueConverter()); diff --git a/src/modules/Elsa.Workflows.Core/Services/Hasher.cs b/src/modules/Elsa.Workflows.Core/Services/Hasher.cs index 808a8684b..b80b373a8 100644 --- a/src/modules/Elsa.Workflows.Core/Services/Hasher.cs +++ b/src/modules/Elsa.Workflows.Core/Services/Hasher.cs @@ -2,8 +2,9 @@ using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.Options; namespace Elsa.Workflows; @@ -12,7 +13,12 @@ public class Hasher : IHasher { private readonly JsonSerializerOptions _serializerOptions; - public Hasher(IWellKnownTypeRegistry wellKnownTypeRegistry) + public Hasher() + : this(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) + { + } + + public Hasher(IOptions workflowJsonOptions) { _serializerOptions = new JsonSerializerOptions { @@ -21,7 +27,7 @@ public class Hasher : IHasher DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; - _serializerOptions.Converters.Add(new TypeJsonConverter(wellKnownTypeRegistry)); + _serializerOptions.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); _serializerOptions.Converters.Add(new ExcludeFromHashConverterFactory()); } @@ -50,4 +56,4 @@ public class Hasher : IHasher return JsonSerializer.Serialize(payload, payload.GetType(), _serializerOptions); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs b/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs index 91c19fd03..cb4fc0019 100644 --- a/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs +++ b/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs @@ -1,13 +1,12 @@ -using Elsa.Expressions.Contracts; -using Elsa.Expressions.Extensions; using Elsa.Expressions.Helpers; -using Elsa.Expressions.Services; using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; using Elsa.Workflows.Serialization.Helpers; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; namespace Elsa.Workflows; @@ -17,21 +16,40 @@ namespace Elsa.Workflows; public class VariableMapper { private readonly ILogger _logger; - private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry; + private readonly WorkflowJsonOptions _workflowJsonOptions; /// /// Initializes a new instance of the class. /// - /// The well-known type registry. /// The logger. - public VariableMapper(IWellKnownTypeRegistry wellKnownTypeRegistry, ILogger logger) + public VariableMapper(ILogger logger) + : this(logger, Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The workflow JSON options. + public VariableMapper(ILogger logger, IOptions workflowJsonOptions) + : this(logger, workflowJsonOptions.Value) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The workflow JSON options. + public VariableMapper(ILogger logger, WorkflowJsonOptions workflowJsonOptions) { - _wellKnownTypeRegistry = wellKnownTypeRegistry; _logger = logger; + _workflowJsonOptions = workflowJsonOptions; } /// - public VariableMapper() : this(new WellKnownTypeRegistry(), NullLogger.Instance) + public VariableMapper() : this(NullLogger.Instance) { } @@ -42,7 +60,6 @@ public class VariableMapper public Variable Map(VariableModel source) { var type = ResolveVariableType(source.TypeName); - var variableGenericType = typeof(Variable<>).MakeGenericType(type); var variable = (Variable)Activator.CreateInstance(variableGenericType)!; @@ -67,8 +84,8 @@ public class VariableMapper var variableType = source.GetType(); var value = source.Value; var valueType = variableType.IsConstructedGenericType ? variableType.GetGenericArguments().FirstOrDefault() ?? typeof(object) : typeof(object); - var valueTypeAlias = _wellKnownTypeRegistry.GetAliasOrDefault(valueType); - var storageDriverTypeName = source.StorageDriverType?.GetSimpleAssemblyQualifiedName(); + var valueTypeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, valueType); + var storageDriverTypeName = source.StorageDriverType != null ? WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, source.StorageDriverType) : null; var serializedValue = value.Format(); return new(source.Id, source.Name, valueTypeAlias, serializedValue, storageDriverTypeName); @@ -79,7 +96,7 @@ public class VariableMapper if (string.IsNullOrWhiteSpace(typeAlias)) return typeof(object); - if (WorkflowJsonTypeResolver.TryResolveType(_wellKnownTypeRegistry, typeAlias, out var type)) + if (WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, typeAlias, _workflowJsonOptions.AllowLegacyClrTypeNames, out var type)) return type; _logger.LogWarning("Failed to resolve variable type alias {VariableTypeName}", typeAlias); @@ -91,7 +108,7 @@ public class VariableMapper if (string.IsNullOrWhiteSpace(typeAlias)) return null; - if (WorkflowJsonTypeResolver.TryResolveType(_wellKnownTypeRegistry, typeAlias, out var type) && IsStorageDriverType(type)) + if (WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, typeAlias, _workflowJsonOptions.AllowLegacyClrTypeNames, out var type) && IsStorageDriverType(type)) return type; _logger.LogWarning("Failed to resolve storage driver type alias {StorageDriverTypeName}", typeAlias); diff --git a/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs b/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs index b7d9fdce3..9efb4ce38 100644 --- a/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs +++ b/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs @@ -1,7 +1,9 @@ using CShells.Features; using Elsa.Extensions; +using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Activities.Flowchart.Options; using Elsa.Workflows.Activities.Flowchart.Serialization; +using Elsa.Workflows.Serialization.Options; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; @@ -30,6 +32,7 @@ public class FlowchartFeature : IShellFeature if (FlowchartOptionsConfigurator != null) services.Configure(FlowchartOptionsConfigurator); + + services.Configure(options => options.AddTypeAlias("FlowScope")); } } - diff --git a/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs index b3617a45a..04e3b6bc8 100644 --- a/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs +++ b/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs @@ -19,6 +19,7 @@ using Elsa.Workflows.Pipelines.WorkflowExecution; using Elsa.Workflows.PortResolvers; using Elsa.Workflows.Serialization.Configurators; using Elsa.Workflows.Serialization.Helpers; +using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.Serializers; using Elsa.Workflows.Services; using Elsa.Workflows.UIHints.CheckList; @@ -54,7 +55,12 @@ public class WorkflowsFeature : IShellFeature /// /// A delegate to configure the . /// - public Action ActivityExecutionPipeline { get; set; } = builder => builder.UseDefaultActivityInvoker(); + public Action ActivityExecutionPipeline { get; set; } = builder => builder + .UseLogging() + .UseExceptionHandling() + .UseExecutionLogging() + .UseNotifications() + .UseDefaultActivityInvoker(); /// /// A factory that instantiates a concrete . @@ -78,6 +84,8 @@ public class WorkflowsFeature : IShellFeature public void ConfigureServices(IServiceCollection services) { + services.Configure(options => options.RegisterWorkflowTypeAliases()); + services // Core. .AddScoped() @@ -184,7 +192,7 @@ public class WorkflowsFeature : IShellFeature // Logging .AddLogging(); - + // Overridable services services.AddScoped(); } diff --git a/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs index 0eadcf65b..8dbdc87e3 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs @@ -1,7 +1,8 @@ using System.Reflection; -using Elsa.Expressions.Extensions; +using Elsa.Extensions; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Options; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.DependencyInjection; // ReSharper disable once CheckNamespace @@ -100,6 +101,6 @@ public static class ManagementServiceCollectionExtensions { return services .AddVariableDescriptor(category) - .AddTypeAlias(alias); + .Configure(options => options.AddTypeAlias(alias)); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs index 55e72f630..be1d8ecba 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs @@ -2,6 +2,8 @@ using Elsa.Features.Services; using Elsa.Workflows; using Elsa.Workflows.Activities; using Elsa.Workflows.Management.Features; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.DependencyInjection; // ReSharper disable once CheckNamespace namespace Elsa.Extensions; @@ -72,9 +74,9 @@ public static class ModuleExtensions /// public static IModule AddVariableTypeAndAlias(this IModule module, string alias, string category) { - return module - .UseWorkflowManagement(management => management.AddVariableType(category)) - .AddTypeAlias(alias); + module.UseWorkflowManagement(management => management.AddVariableType(category)); + module.Services.Configure(options => options.AddTypeAlias(alias)); + return module; } /// @@ -85,4 +87,4 @@ public static class ModuleExtensions feature.Module.Configure(configure); return feature; } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs index 12d91f384..57801be2d 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs @@ -1,6 +1,8 @@ using Elsa.Extensions; using Elsa.Workflows.Management.Features; +using Elsa.Workflows.Serialization.Options; using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.Management; @@ -15,7 +17,7 @@ public static class WorkflowManagementFeatureExtensions public static WorkflowManagementFeature AddVariableTypeAndAlias(this WorkflowManagementFeature management, string alias, string category) { management.AddVariableType(category); - management.Module.AddTypeAlias(alias); + management.Module.Services.Configure(options => options.AddTypeAlias(alias)); return management; } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs index 46608c0c7..d6769d71f 100644 --- a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs +++ b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs @@ -8,7 +8,7 @@ using Elsa.Caching.Features; using Elsa.Common.Codecs; using Elsa.Common.Features; using Elsa.Expressions.Contracts; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -313,8 +313,8 @@ public class WorkflowManagementFeature(IModule module) : FeatureBase(module) options.IsReadOnlyMode = IsReadOnlyMode; }); - Services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); Services.Configure(_ => { }); Services.Configure(_ => { }); + Services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); } } diff --git a/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs b/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs index cd0bc53b7..0f6644630 100644 --- a/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs +++ b/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs @@ -1,26 +1,28 @@ -using Elsa.Expressions.Contracts; -using Elsa.Expressions.Extensions; using Elsa.Expressions.Helpers; using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Helpers; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Management.Mappers; /// /// Maps s to s and vice versa. /// -public class VariableDefinitionMapper(IWellKnownTypeRegistry wellKnownTypeRegistry, IServiceScopeFactory scopeFactory, ILogger logger) +public class VariableDefinitionMapper(IOptions workflowJsonOptions, IServiceScopeFactory scopeFactory, ILogger logger) { + private readonly WorkflowJsonOptions _workflowJsonOptions = workflowJsonOptions.Value; + /// /// Maps a to a . /// public Variable? Map(VariableDefinition source) { - var aliasedType = wellKnownTypeRegistry.TryGetType(source.TypeName, out var aliasedTypeValue) ? aliasedTypeValue : null; - var type = aliasedType ?? Type.GetType(source.TypeName); + var type = WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, source.TypeName, _workflowJsonOptions.AllowLegacyClrTypeNames, out var resolvedType) ? resolvedType : null; if (type == null) { @@ -28,7 +30,7 @@ public class VariableDefinitionMapper(IWellKnownTypeRegistry wellKnownTypeRegist return null; } - var valueType = aliasedType is { IsArray: true } ? source.IsArray ? aliasedType.MakeArrayType() : aliasedType : source.IsArray ? type.MakeArrayType() : type; + var valueType = type.IsArray ? source.IsArray ? type.MakeArrayType() : type : source.IsArray ? type.MakeArrayType() : type; var variableGenericType = typeof(Variable<>).MakeGenericType(valueType); var variable = (Variable)Activator.CreateInstance(variableGenericType)!; @@ -70,10 +72,10 @@ public class VariableDefinitionMapper(IWellKnownTypeRegistry wellKnownTypeRegist { var variableType = source.GetType(); var valueType = variableType.IsConstructedGenericType ? variableType.GetGenericArguments().FirstOrDefault() ?? typeof(object) : typeof(object); - var valueTypeAlias = wellKnownTypeRegistry.TryGetAlias(valueType, out var alias) ? alias : null; + var valueTypeAlias = WorkflowJsonTypeResolver.TryGetAlias(_workflowJsonOptions, valueType, out var alias) ? alias : null; var value = source.Value; var serializedValue = value.Format(); - var storageDriverTypeName = source.StorageDriverType?.GetSimpleAssemblyQualifiedName(); + var storageDriverTypeName = source.StorageDriverType != null ? WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, source.StorageDriverType) : null; // Handles the case where an alias exists for an array or collection type. E.g. byte[] -> ByteArray. if (valueTypeAlias != null && (valueType.IsArray || valueType.IsCollectionType())) @@ -82,7 +84,7 @@ public class VariableDefinitionMapper(IWellKnownTypeRegistry wellKnownTypeRegist var isArray = valueType.IsArray; var isCollection = valueType.IsCollectionType(); var elementValueType = isArray ? valueType.GetElementType()! : isCollection ? valueType.GenericTypeArguments[0] : valueType; - var elementTypeAlias = wellKnownTypeRegistry.GetAliasOrDefault(elementValueType); + var elementTypeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, elementValueType); return new(source.Id, source.Name, elementTypeAlias, isArray, serializedValue, storageDriverTypeName); } @@ -97,9 +99,7 @@ public class VariableDefinitionMapper(IWellKnownTypeRegistry wellKnownTypeRegist if (string.IsNullOrEmpty(storageDriverTypeName)) return null; - var type = Type.GetType(storageDriverTypeName); - - if (type != null) + if (WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, storageDriverTypeName, _workflowJsonOptions.AllowLegacyClrTypeNames, out var type) && typeof(IStorageDriver).IsAssignableFrom(type)) return type; // TODO: The following code handles backward compatibility with variable definitions referencing older .NET type namespaces. @@ -115,4 +115,4 @@ public class VariableDefinitionMapper(IWellKnownTypeRegistry wellKnownTypeRegist return null; } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs b/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs index d34feb336..2622f6be7 100644 --- a/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs +++ b/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs @@ -5,6 +5,7 @@ using CShells.Features; using Elsa.Caching.Features; using Elsa.Common.Features; using Elsa.Expressions.Contracts; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Attributes; using Elsa.Workflows.Features; @@ -131,5 +132,7 @@ public class WorkflowManagementFeature : IShellFeature // Register the default variable descriptors declared on this feature. services.AddVariableDescriptors(VariableDescriptors); + + services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs b/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs index 45498dd5e..17a05faf8 100644 --- a/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs +++ b/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs @@ -1,10 +1,10 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; -using Elsa.Expressions.Contracts; -using Elsa.Expressions.Services; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.Options; namespace Elsa.Workflows.Runtime.Comparers; @@ -18,14 +18,23 @@ public class WorkflowTriggerEqualityComparer : IEqualityComparer /// /// Initializes a new instance of the class. /// - public WorkflowTriggerEqualityComparer() : this(WellKnownTypeRegistry.CreateDefault()) + public WorkflowTriggerEqualityComparer() + : this(new WorkflowJsonOptions()) { } /// /// Initializes a new instance of the class. /// - public WorkflowTriggerEqualityComparer(IWellKnownTypeRegistry wellKnownTypeRegistry) + public WorkflowTriggerEqualityComparer(IOptions workflowJsonOptions) + : this(workflowJsonOptions.Value) + { + } + + /// + /// Initializes a new instance of the class. + /// + public WorkflowTriggerEqualityComparer(WorkflowJsonOptions workflowJsonOptions) { _settings = new() { @@ -44,8 +53,8 @@ public class WorkflowTriggerEqualityComparer : IEqualityComparer // polymorphic object properties serialize identically to their stored representation. _settings.Converters.Add(new JsonStringEnumConverter()); _settings.Converters.Add(JsonMetadataServices.TimeSpanConverter); - _settings.Converters.Add(new PolymorphicObjectConverterFactory(wellKnownTypeRegistry)); - _settings.Converters.Add(new TypeJsonConverter(wellKnownTypeRegistry)); + _settings.Converters.Add(new PolymorphicObjectConverterFactory(workflowJsonOptions)); + _settings.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); } /// diff --git a/src/modules/Elsa.Workflows.Runtime/Discovery/WorkflowTypeScanner.cs b/src/modules/Elsa.Workflows.Runtime/Discovery/WorkflowTypeScanner.cs new file mode 100644 index 000000000..207a0d212 --- /dev/null +++ b/src/modules/Elsa.Workflows.Runtime/Discovery/WorkflowTypeScanner.cs @@ -0,0 +1,14 @@ +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +namespace Elsa.Workflows.Runtime.Discovery; + +internal static class WorkflowTypeScanner +{ + [RequiresUnreferencedCode("The assembly is required to be referenced.")] + public static IEnumerable GetWorkflowTypes(Assembly assembly) + { + return assembly.GetExportedTypes() + .Where(x => typeof(IWorkflow).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false }); + } +} diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs index 40ef0c3f1..614c0d4c6 100644 --- a/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs @@ -1,5 +1,11 @@ +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Elsa.Workflows.Serialization.Options; +using Elsa.Extensions; +using Elsa.Workflows; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Contracts; +using Elsa.Workflows.Runtime.Discovery; using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Providers; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -51,4 +57,42 @@ public static class DependencyInjectionExtensions /// /// The type of the workflows provider to add. Must implement . public static IServiceCollection AddWorkflowsProvider(this IServiceCollection services) where T : class, IWorkflowsProvider => services.AddScoped(); -} \ No newline at end of file + + /// + /// Registers the specified code-first workflow type. + /// + public static IServiceCollection AddWorkflow(this IServiceCollection services) where T : IWorkflow => services.AddWorkflow(typeof(T)); + + /// + /// Registers the specified code-first workflow type. + /// + public static IServiceCollection AddWorkflow(this IServiceCollection services, Type workflowType) + { + AddWorkflowRegistration(services, workflowType); + return services; + } + + /// + /// Registers all code-first workflows contained in the assembly containing the specified marker type. + /// + [RequiresUnreferencedCode("The assembly is required to be referenced.")] + public static IServiceCollection AddWorkflowsFrom(this IServiceCollection services) => services.AddWorkflowsFrom(typeof(TMarker).Assembly); + + /// + /// Registers all code-first workflows in the specified assembly. + /// + [RequiresUnreferencedCode("The assembly is required to be referenced.")] + public static IServiceCollection AddWorkflowsFrom(this IServiceCollection services, Assembly assembly) + { + foreach (var workflowType in WorkflowTypeScanner.GetWorkflowTypes(assembly)) + AddWorkflowRegistration(services, workflowType); + + return services; + } + + private static void AddWorkflowRegistration(IServiceCollection services, Type workflowType) + { + services.PostConfigure(options => options.Workflows.Add(workflowType)); + services.Configure(options => options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName())); + } +} diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDictionaryExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDictionaryExtensions.cs index 952c28da7..0967c0276 100644 --- a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDictionaryExtensions.cs +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDictionaryExtensions.cs @@ -1,5 +1,4 @@ using Elsa.Workflows; -using Elsa.Workflows.Runtime.Helpers; using Microsoft.Extensions.DependencyInjection; // ReSharper disable once CheckNamespace @@ -23,7 +22,10 @@ public static class WorkflowDictionaryExtensions /// public static void Add(this IDictionary>> dictionary, Type workflowType) { - WorkflowTypeValidator.Validate(workflowType); + ValidateWorkflowType(workflowType); + + if (string.IsNullOrWhiteSpace(workflowType.FullName)) + throw new ArgumentException($"Workflow type '{workflowType.Name}' must have a full name.", nameof(workflowType)); var key = workflowType.GetSimpleAssemblyQualifiedName(); var legacyKey = workflowType.FullName; @@ -45,8 +47,16 @@ public static class WorkflowDictionaryExtensions if (!string.IsNullOrWhiteSpace(legacyKey) && legacyKey != key) dictionary[legacyKey] = factory!; - - if (dictionary is IWorkflowTypeRegistry workflowTypeRegistry) - workflowTypeRegistry.AddWorkflowType(workflowType); } + + private static void ValidateWorkflowType(Type workflowType) + { + if (!typeof(IWorkflow).IsAssignableFrom(workflowType)) + throw new ArgumentException($"Workflow type '{GetDisplayName(workflowType)}' must implement {nameof(IWorkflow)}.", nameof(workflowType)); + + if (workflowType.IsAbstract || workflowType.IsInterface || workflowType.ContainsGenericParameters) + throw new ArgumentException($"Workflow type '{GetDisplayName(workflowType)}' must be a concrete, closed type.", nameof(workflowType)); + } + + private static string GetDisplayName(Type type) => type.FullName ?? type.Name; } diff --git a/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs b/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs index 870c4148d..8393bf829 100644 --- a/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs +++ b/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs @@ -4,7 +4,7 @@ using Elsa.Common; using Elsa.Common.DistributedHosting; using Elsa.Common.Features; using Elsa.Common.RecurringTasks; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -15,14 +15,12 @@ using Elsa.Workflows.Management; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Runtime.ActivationValidators; -using Elsa.Workflows.Runtime.Bookmarks; +using Elsa.Workflows.Runtime.Comparers; +using Elsa.Workflows.Runtime.Discovery; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Handlers; -using Elsa.Workflows.Runtime.Helpers; -using Elsa.Workflows.Runtime.Models; using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Providers; -using Elsa.Workflows.Runtime.Stimuli; using Elsa.Workflows.Runtime.Stores; using Elsa.Workflows.Runtime.Tasks; using Elsa.Workflows.Runtime.UIHints; @@ -46,8 +44,7 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) /// /// A list of workflow builders configured during application startup. /// - public IDictionary>> Workflows { get; set; } = new WorkflowFactoryDictionary(); - private ISet WorkflowTypes { get; } = new HashSet(); + public IDictionary>> Workflows { get; set; } = new Dictionary>>(); /// /// A factory that instantiates a concrete . @@ -202,9 +199,8 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) /// public WorkflowRuntimeFeature AddWorkflow(Type workflowType) { - WorkflowTypeValidator.Validate(workflowType); Workflows.Add(workflowType); - WorkflowTypes.Add(workflowType); + Services.Configure(options => options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName())); return this; } @@ -214,11 +210,7 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) [RequiresUnreferencedCode("The assembly is required to be referenced.")] public WorkflowRuntimeFeature AddWorkflowsFrom(Assembly assembly) { - var workflowTypes = assembly.GetExportedTypes() - .Where(x => typeof(IWorkflow).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false }) - .ToList(); - - foreach (var workflowType in workflowTypes) + foreach (var workflowType in WorkflowTypeScanner.GetWorkflowTypes(assembly)) AddWorkflow(workflowType); return this; @@ -275,7 +267,6 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) Services.Configure(WorkflowInboxCleanupOptions); Services.Configure(WorkflowDispatcherOptions); Services.Configure(BookmarkQueuePurgeOptions); - Services.Configure(RegisterWorkflowTypeAliases); Services.Configure(options => { options.Workflows = Workflows; }); Services.Configure(options => { @@ -314,6 +305,7 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) Services // Core. + .AddSingleton() .AddScoped() .AddScoped() .AddScoped() @@ -447,13 +439,4 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) Services.TryAddScoped(WorkflowDispatchOutboxStore); Services.TryAddScoped(); } - - private void RegisterWorkflowTypeAliases(ExpressionOptions options) - { - var workflowTypes = Workflows is IWorkflowTypeRegistry workflowTypeRegistry - ? WorkflowTypes.Concat(workflowTypeRegistry.WorkflowTypes) - : WorkflowTypes; - - WorkflowRuntimeTypeAliasRegistrar.Register(options, workflowTypes); - } } diff --git a/src/modules/Elsa.Workflows.Runtime/Helpers/IWorkflowTypeRegistry.cs b/src/modules/Elsa.Workflows.Runtime/Helpers/IWorkflowTypeRegistry.cs deleted file mode 100644 index 4b7b977f2..000000000 --- a/src/modules/Elsa.Workflows.Runtime/Helpers/IWorkflowTypeRegistry.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Elsa.Workflows.Runtime.Helpers; - -internal interface IWorkflowTypeRegistry -{ - IEnumerable WorkflowTypes { get; } - - void AddWorkflowType(Type workflowType); -} diff --git a/src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowFactoryDictionary.cs b/src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowFactoryDictionary.cs deleted file mode 100644 index 872f80423..000000000 --- a/src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowFactoryDictionary.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Elsa.Workflows; - -namespace Elsa.Workflows.Runtime.Helpers; - -internal sealed class WorkflowFactoryDictionary : Dictionary>>, IWorkflowTypeRegistry -{ - private readonly ISet _workflowTypes = new HashSet(); - - public IEnumerable WorkflowTypes => _workflowTypes; - - public void AddWorkflowType(Type workflowType) - { - WorkflowTypeValidator.Validate(workflowType); - _workflowTypes.Add(workflowType); - } -} diff --git a/src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowTypeValidator.cs b/src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowTypeValidator.cs deleted file mode 100644 index 069aed8ab..000000000 --- a/src/modules/Elsa.Workflows.Runtime/Helpers/WorkflowTypeValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Elsa.Workflows; - -namespace Elsa.Workflows.Runtime.Helpers; - -internal static class WorkflowTypeValidator -{ - public static void Validate(Type workflowType) - { - if (!typeof(IWorkflow).IsAssignableFrom(workflowType)) - throw new ArgumentException($"Workflow type '{GetDisplayName(workflowType)}' must implement {nameof(IWorkflow)}.", nameof(workflowType)); - - if (workflowType.IsAbstract || workflowType.IsInterface || workflowType.IsGenericTypeDefinition || workflowType.ContainsGenericParameters) - throw new ArgumentException($"Workflow type '{GetDisplayName(workflowType)}' must be a concrete, closed type.", nameof(workflowType)); - } - - private static string GetDisplayName(Type type) => type.FullName ?? type.Name; -} diff --git a/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs b/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs index c69353ac9..b04d0f130 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs @@ -31,9 +31,9 @@ public class TriggerIndexer : ITriggerIndexer private readonly IServiceProvider _serviceProvider; private readonly IStimulusHasher _hasher; private readonly IDistributedLockProvider _distributedLockProvider; - private readonly WorkflowTriggerEqualityComparer _triggerEqualityComparer; private readonly DistributedLockingOptions _lockingOptions; private readonly ILogger _logger; + private readonly WorkflowTriggerEqualityComparer _triggerEqualityComparer; /// /// Constructor. @@ -49,8 +49,8 @@ public class TriggerIndexer : ITriggerIndexer IServiceProvider serviceProvider, IStimulusHasher hasher, IDistributedLockProvider distributedLockProvider, - IWellKnownTypeRegistry wellKnownTypeRegistry, IOptions lockingOptions, + WorkflowTriggerEqualityComparer triggerEqualityComparer, ILogger logger) { _activityVisitor = activityVisitor; @@ -62,8 +62,8 @@ public class TriggerIndexer : ITriggerIndexer _serviceProvider = serviceProvider; _hasher = hasher; _distributedLockProvider = distributedLockProvider; - _triggerEqualityComparer = new WorkflowTriggerEqualityComparer(wellKnownTypeRegistry); _lockingOptions = lockingOptions.Value; + _triggerEqualityComparer = triggerEqualityComparer; _logger = logger; _workflowDefinitionService = workflowDefinitionService; } diff --git a/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs b/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs index c66a829f5..d680b6529 100644 --- a/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs +++ b/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs @@ -3,7 +3,7 @@ using System.Reflection; using CShells.Features; using Elsa.Common; using Elsa.Common.RecurringTasks; -using Elsa.Expressions.Options; +using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Mediator.Contracts; using Elsa.Workflows.CommitStates; @@ -11,9 +11,10 @@ using Elsa.Workflows.Management; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Runtime.ActivationValidators; +using Elsa.Workflows.Runtime.Comparers; +using Elsa.Workflows.Runtime.Discovery; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Handlers; -using Elsa.Workflows.Runtime.Helpers; using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Providers; using Elsa.Workflows.Runtime.Services; @@ -42,7 +43,7 @@ public class WorkflowRuntimeFeature : IShellFeature /// /// A list of workflow builders configured during application startup. /// - public IDictionary>> Workflows { get; set; } = new WorkflowFactoryDictionary(); + public IDictionary>> Workflows { get; set; } = new Dictionary>>(); private ISet WorkflowTypes { get; } = new HashSet(); /// @@ -164,7 +165,6 @@ public class WorkflowRuntimeFeature : IShellFeature /// public WorkflowRuntimeFeature AddWorkflow(Type workflowType) { - WorkflowTypeValidator.Validate(workflowType); Workflows.Add(workflowType); WorkflowTypes.Add(workflowType); return this; @@ -176,11 +176,7 @@ public class WorkflowRuntimeFeature : IShellFeature [RequiresUnreferencedCode("The assembly is required to be referenced.")] public WorkflowRuntimeFeature AddWorkflowsFrom(Assembly assembly) { - var workflowTypes = assembly.GetExportedTypes() - .Where(x => typeof(IWorkflow).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false }) - .ToList(); - - foreach (var workflowType in workflowTypes) + foreach (var workflowType in WorkflowTypeScanner.GetWorkflowTypes(assembly)) AddWorkflow(workflowType); return this; @@ -189,7 +185,7 @@ public class WorkflowRuntimeFeature : IShellFeature public void ConfigureServices(IServiceCollection services) { // Options. - services.Configure(RegisterWorkflowTypeAliases); + services.Configure(RegisterWorkflowTypeAliases); services.Configure(options => { options.Workflows = Workflows; }); services.Configure(options => { @@ -231,6 +227,7 @@ public class WorkflowRuntimeFeature : IShellFeature .AddTransient() // Core. + .AddSingleton() .AddScoped() .AddScoped() .AddScoped() @@ -240,6 +237,7 @@ public class WorkflowRuntimeFeature : IShellFeature .AddScoped(StimulusDispatcher) .AddScoped(WorkflowCancellationDispatcher) .AddScoped(RunTaskDispatcher) + .AddScoped(DispatchWorkflowCommandHandler) .AddScoped(ActivityExecutionLogSink) .AddScoped(WorkflowExecutionLogSink) .AddSingleton(BackgroundActivityScheduler) @@ -366,12 +364,9 @@ public class WorkflowRuntimeFeature : IShellFeature services.TryAddScoped(); } - private void RegisterWorkflowTypeAliases(ExpressionOptions options) + private void RegisterWorkflowTypeAliases(WorkflowJsonOptions options) { - var workflowTypes = Workflows is IWorkflowTypeRegistry workflowTypeRegistry - ? WorkflowTypes.Concat(workflowTypeRegistry.WorkflowTypes) - : WorkflowTypes; - - WorkflowRuntimeTypeAliasRegistrar.Register(options, workflowTypes); + foreach (var workflowType in WorkflowTypes) + options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName()); } } diff --git a/src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs b/src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs deleted file mode 100644 index b3811a01e..000000000 --- a/src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Elsa.Expressions.Options; -using Elsa.Extensions; -using Elsa.Workflows; -using Elsa.Workflows.Runtime.Bookmarks; -using Elsa.Workflows.Runtime.Stimuli; - -namespace Elsa.Workflows.Runtime; - -internal static class WorkflowRuntimeTypeAliasRegistrar -{ - public static void Register(ExpressionOptions options, IEnumerable workflowTypes) - { - options.RegisterTypeAlias(typeof(EventBookmarkPayload), nameof(EventBookmarkPayload)); - options.RegisterTypeAlias(typeof(ExecuteWorkflowPayload), nameof(ExecuteWorkflowPayload)); - options.RegisterTypeAlias(typeof(RunTaskBookmarkPayload), nameof(RunTaskBookmarkPayload)); - options.RegisterTypeAlias(typeof(BookmarkTokenPayload), nameof(BookmarkTokenPayload)); - options.RegisterTypeAlias(typeof(EventTokenPayload), nameof(EventTokenPayload)); - options.RegisterTypeAlias(typeof(ExecuteWorkflowResult), nameof(ExecuteWorkflowResult)); - options.RegisterTypeAlias(typeof(WorkflowInterruptedPayload), nameof(WorkflowInterruptedPayload)); - options.RegisterTypeAlias(typeof(BackgroundActivityStimulus), nameof(BackgroundActivityStimulus)); - options.RegisterTypeAlias(typeof(BulkDispatchWorkflowsStimulus), nameof(BulkDispatchWorkflowsStimulus)); - options.RegisterTypeAlias(typeof(DispatchWorkflowStimulus), nameof(DispatchWorkflowStimulus)); - options.RegisterTypeAlias(typeof(EventStimulus), nameof(EventStimulus)); - options.RegisterTypeAlias(typeof(ExecuteWorkflowStimulus), nameof(ExecuteWorkflowStimulus)); - options.RegisterTypeAlias(typeof(RunTaskStimulus), nameof(RunTaskStimulus)); - - foreach (var workflowType in workflowTypes.Where(IsConcreteWorkflowType).Distinct()) - options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName()); - } - - private static bool IsConcreteWorkflowType(Type type) - { - return typeof(IWorkflow).IsAssignableFrom(type) && type is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false }; - } -} diff --git a/test/TlsSmoke/Directory.Build.props b/test/TlsSmoke/Directory.Build.props new file mode 100644 index 000000000..aa6d9a312 --- /dev/null +++ b/test/TlsSmoke/Directory.Build.props @@ -0,0 +1,5 @@ + + + + + diff --git a/test/TlsSmoke/Program.cs b/test/TlsSmoke/Program.cs new file mode 100644 index 000000000..e2b8d9a3b --- /dev/null +++ b/test/TlsSmoke/Program.cs @@ -0,0 +1,16 @@ +if (args.Length != 1 || !Uri.TryCreate(args[0], UriKind.Absolute, out var uri)) +{ + Console.Error.WriteLine("Usage: TlsSmoke "); + return 2; +} + +using var httpClient = new HttpClient +{ + Timeout = TimeSpan.FromSeconds(30) +}; + +using var response = await httpClient.GetAsync(uri); +response.EnsureSuccessStatusCode(); + +Console.WriteLine($"TLS request to {uri} returned {(int)response.StatusCode}."); +return 0; diff --git a/test/TlsSmoke/TlsSmoke.csproj b/test/TlsSmoke/TlsSmoke.csproj new file mode 100644 index 000000000..cd19a3563 --- /dev/null +++ b/test/TlsSmoke/TlsSmoke.csproj @@ -0,0 +1,10 @@ + + + + Exe + net10.0 + enable + enable + + + diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Composition/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Composition/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs index 4ad856b7e..847bdebee 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Composition/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Composition/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs @@ -142,24 +142,25 @@ public class BulkDispatchWorkflowsTests : AppComponentTest return (T?)variables.FirstOrDefault(v => v.Variable.Name == variableName)?.Value; } - private async Task<(TestWorkflowExecutionResult Result, List CompletedChildWorkflows)> RunWorkflowAndWaitForChildWorkflowsAsync( + private async Task<(TestWorkflowExecutionResult Result, List CompletedChildWorkflows)> RunWorkflowAndWaitForChildWorkflowsAsync( string parentWorkflowDefinitionId, string childWorkflowDefinitionId, int expectedChildCount) { var result = await RunWorkflowAsync(parentWorkflowDefinitionId); - var completedChildWorkflows = await WaitForCompletedChildWorkflowInstancesAsync(result.WorkflowExecutionContext.Id, childWorkflowDefinitionId, expectedChildCount); + var completedChildWorkflows = await WaitForCompletedChildWorkflowsAsync(result.WorkflowExecutionContext.Id, childWorkflowDefinitionId, expectedChildCount); return (result, completedChildWorkflows); } - private async Task> WaitForCompletedChildWorkflowInstancesAsync(string parentWorkflowInstanceId, string childWorkflowDefinitionId, int expectedChildCount) + private async Task> WaitForCompletedChildWorkflowsAsync(string parentWorkflowInstanceId, string childWorkflowDefinitionId, int expectedChildCount) { + var workflowInstanceStore = Scope.ServiceProvider.GetRequiredService(); var timeoutAt = DateTimeOffset.UtcNow.AddSeconds(ChildWorkflowTimeoutSeconds); while (DateTimeOffset.UtcNow < timeoutAt) { - var completedChildWorkflows = await FindChildWorkflowInstancesAsync(parentWorkflowInstanceId, childWorkflowDefinitionId, WorkflowStatus.Finished); + var completedChildWorkflows = await FindChildWorkflowStatesAsync(workflowInstanceStore, parentWorkflowInstanceId, childWorkflowDefinitionId, WorkflowStatus.Finished); if (completedChildWorkflows.Count >= expectedChildCount) return completedChildWorkflows; @@ -167,12 +168,13 @@ public class BulkDispatchWorkflowsTests : AppComponentTest await Task.Delay(TimeSpan.FromMilliseconds(100)); } - var childWorkflows = await FindChildWorkflowInstancesAsync(parentWorkflowInstanceId, childWorkflowDefinitionId); + var childWorkflows = await FindChildWorkflowStatesAsync(workflowInstanceStore, parentWorkflowInstanceId, childWorkflowDefinitionId); var observedStates = string.Join(", ", childWorkflows.Select(x => $"{x.Id}:{x.Status}:{x.SubStatus}")); throw new TimeoutException($"Expected {expectedChildCount} completed child workflows with definition ID {childWorkflowDefinitionId}, but observed {childWorkflows.Count(x => x.Status == WorkflowStatus.Finished)}. Observed child workflow states: {observedStates}"); } - private async Task> FindChildWorkflowInstancesAsync( + private static async Task> FindChildWorkflowStatesAsync( + IWorkflowInstanceStore workflowInstanceStore, string parentWorkflowInstanceId, string childWorkflowDefinitionId, WorkflowStatus? workflowStatus = null) @@ -183,8 +185,8 @@ public class BulkDispatchWorkflowsTests : AppComponentTest ParentWorkflowInstanceIds = new[] { parentWorkflowInstanceId }, WorkflowStatus = workflowStatus }; - var instances = await _workflowInstanceStore.FindManyAsync(filter); - return instances.OrderBy(x => x.CreatedAt).ToList(); + var instances = await workflowInstanceStore.FindManyAsync(filter); + return instances.Select(x => x.WorkflowState).ToList(); } private async Task> WaitForChildWorkflowInstancesAsync( diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Primitives/Event/PublishEventTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Primitives/Event/PublishEventTests.cs index 8b6b696c5..b1390b510 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Primitives/Event/PublishEventTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/Primitives/Event/PublishEventTests.cs @@ -73,10 +73,9 @@ public class PublishEventTests : AppComponentTest Assert.NotNull(receivedPayload); // Verify the payload structure and content - var payloadJson = JsonSerializer.Serialize(receivedPayload); - using var payloadDocument = JsonDocument.Parse(payloadJson); - var statusProperty = Assert.Single(payloadDocument.RootElement.EnumerateObject(), x => string.Equals(x.Name, "Status", StringComparison.OrdinalIgnoreCase)); - Assert.Equal("Shipped", statusProperty.Value.GetString()); + using var payloadDocument = JsonDocument.Parse(JsonSerializer.Serialize(receivedPayload)); + Assert.True(payloadDocument.RootElement.TryGetProperty("Status", out var status), "Received payload should contain a Status property"); + Assert.Equal("Shipped", status.GetString()); } private async Task GetSingleWorkflowInstanceAsync(string definitionId, string correlationId, int timeoutMs = 5000) diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs index 74969a8fd..90d00d2c3 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs @@ -1,15 +1,15 @@ using System.Reflection; using System.Security.Claims; -using System.Text.Json; -using ConsoleLogStreaming.Contracts; +using System.Text; +using ConsoleLogStreaming.Core.Models; using ConsoleLogStreaming.Core; -using ConsoleLogStreaming.SignalR; using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Features; using Elsa.Diagnostics.ConsoleLogs.Permissions; using Elsa.Diagnostics.ConsoleLogs.RealTime; using Elsa.Diagnostics.ConsoleLogs.Services; using FastEndpoints; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging.Abstractions; @@ -60,18 +60,15 @@ public class ConsoleLogsAuthorizationTests { var endpointType = typeof(ConsoleLogsFeature).Assembly.GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent.Endpoint", throwOnError: true)!; var provider = new TestConsoleLogProvider(); - var endpoint = Activator.CreateInstance(endpointType, provider, new ConsoleLogStreamingApiMapper())!; - var (requestDtoType, _) = GetEndpointDtoTypes(endpointType); - var request = JsonSerializer.Deserialize( + var endpoint = Activator.CreateInstance(endpointType, provider)!; + SetJsonRequest(endpointType, endpoint, """ { "workflowInstanceId": "workflow-instance-a" } - """, - requestDtoType, - new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!; + """); - var result = endpointType.GetMethod("ExecuteAsync")!.Invoke(endpoint, [request, CancellationToken.None]); + var result = endpointType.GetMethod("ExecuteAsync", [typeof(CancellationToken)])!.Invoke(endpoint, [CancellationToken.None]); await Assert.IsAssignableFrom(result); Assert.NotNull(provider.LastFilter); @@ -80,14 +77,59 @@ public class ConsoleLogsAuthorizationTests Assert.Equal("workflow-instance-a", workflowInstanceId); } + [Theory] + [InlineData("stdout", ConsoleStream.Stdout)] + [InlineData("stderr", ConsoleStream.Stderr)] + public async Task RecentEndpoint_MapsLowercaseStreamFilter(string stream, ConsoleStream expected) + { + var endpointType = typeof(ConsoleLogsFeature).Assembly.GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent.Endpoint", throwOnError: true)!; + var provider = new TestConsoleLogProvider(); + var endpoint = Activator.CreateInstance(endpointType, provider)!; + SetJsonRequest(endpointType, endpoint, + $$""" + { + "stream": "{{stream}}" + } + """); + + var result = endpointType.GetMethod("ExecuteAsync", [typeof(CancellationToken)])!.Invoke(endpoint, [CancellationToken.None]); + await Assert.IsAssignableFrom(result); + + Assert.NotNull(provider.LastFilter); + Assert.Equal(expected, provider.LastFilter.Stream); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("all")] + public async Task RecentEndpoint_MapsAllStreamFilterToNull(string? stream) + { + var endpointType = typeof(ConsoleLogsFeature).Assembly.GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent.Endpoint", throwOnError: true)!; + var provider = new TestConsoleLogProvider(); + var endpoint = Activator.CreateInstance(endpointType, provider)!; + var streamJson = stream == null ? "null" : $"\"{stream}\""; + SetJsonRequest(endpointType, endpoint, + $$""" + { + "stream": {{streamJson}} + } + """); + + var result = endpointType.GetMethod("ExecuteAsync", [typeof(CancellationToken)])!.Invoke(endpoint, [CancellationToken.None]); + await Assert.IsAssignableFrom(result); + + Assert.NotNull(provider.LastFilter); + Assert.Null(provider.LastFilter.Stream); + } + [Fact] public async Task RecentEndpoint_MapsActivityFiltersToMetadataFilter() { var endpointType = typeof(ConsoleLogsFeature).Assembly.GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent.Endpoint", throwOnError: true)!; var provider = new TestConsoleLogProvider(); - var endpoint = Activator.CreateInstance(endpointType, provider, new ConsoleLogStreamingApiMapper())!; - var (requestDtoType, _) = GetEndpointDtoTypes(endpointType); - var request = JsonSerializer.Deserialize( + var endpoint = Activator.CreateInstance(endpointType, provider)!; + SetJsonRequest(endpointType, endpoint, """ { "workflowInstanceId": "workflow-instance-a", @@ -95,17 +137,30 @@ public class ConsoleLogsAuthorizationTests "activityId": "activity-a", "activityNodeId": "node-a" } - """, - requestDtoType, - new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!; + """); - var result = endpointType.GetMethod("ExecuteAsync")!.Invoke(endpoint, [request, CancellationToken.None]); + var result = endpointType.GetMethod("ExecuteAsync", [typeof(CancellationToken)])!.Invoke(endpoint, [CancellationToken.None]); await Assert.IsAssignableFrom(result); Assert.NotNull(provider.LastFilter); AssertActivityMetadata(provider.LastFilter.Metadata); } + [Fact] + public async Task RecentEndpoint_WhenJsonRequestHasUnknownEmptyBody_UsesEmptyFilter() + { + var endpointType = typeof(ConsoleLogsFeature).Assembly.GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent.Endpoint", throwOnError: true)!; + var provider = new TestConsoleLogProvider(); + var endpoint = Activator.CreateInstance(endpointType, provider)!; + SetJsonRequest(endpointType, endpoint, "", includeContentLength: false); + + var result = endpointType.GetMethod("ExecuteAsync", [typeof(CancellationToken)])!.Invoke(endpoint, [CancellationToken.None]); + await Assert.IsAssignableFrom(result); + + Assert.NotNull(provider.LastFilter); + Assert.Empty(provider.LastFilter.Metadata); + } + [Fact] public async Task HubStream_MapsWorkflowInstanceIdToMetadataFilter() { @@ -167,13 +222,24 @@ public class ConsoleLogsAuthorizationTests Assert.Equal("node-a", metadata[ConsoleLogMetadataKeys.ActivityNodeId]); } + private static void SetJsonRequest(Type endpointType, object endpoint, string json, bool includeContentLength = true) + { + var bytes = Encoding.UTF8.GetBytes(json); + var context = new DefaultHttpContext(); + context.Request.Body = new MemoryStream(bytes); + if (includeContentLength) + context.Request.ContentLength = bytes.Length; + context.Request.ContentType = "application/json"; + + endpointType + .GetProperty("HttpContext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)! + .SetValue(endpoint, context); + } + private static IReadOnlyCollection GetConfiguredPermissions(string endpointTypeName) { var endpointType = typeof(ConsoleLogsFeature).Assembly.GetType(endpointTypeName, throwOnError: true)!; - var mapper = new ConsoleLogStreamingApiMapper(); - var endpoint = endpointTypeName.EndsWith(".Recent.Endpoint", StringComparison.Ordinal) - ? Activator.CreateInstance(endpointType, new TestConsoleLogProvider(), mapper)! - : Activator.CreateInstance(endpointType, new TestConsoleLogProvider(), mapper)!; + var endpoint = Activator.CreateInstance(endpointType, new TestConsoleLogProvider())!; var (requestDtoType, responseDtoType) = GetEndpointDtoTypes(endpointType); var definition = new EndpointDefinition(endpointType, requestDtoType, responseDtoType); @@ -205,13 +271,13 @@ public class ConsoleLogsAuthorizationTests var genericTypeDefinition = type.GetGenericTypeDefinition(); var genericArguments = type.GetGenericArguments(); - if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpoint<,>)) + if (genericTypeDefinition == typeof(Abstractions.ElsaEndpoint<,>)) return (genericArguments[0], genericArguments[1]); - if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpoint<,,>)) + if (genericTypeDefinition == typeof(Abstractions.ElsaEndpoint<,,>)) return (genericArguments[0], genericArguments[1]); - if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpointWithoutRequest<>)) + if (genericTypeDefinition == typeof(Abstractions.ElsaEndpointWithoutRequest<>)) return (typeof(EmptyRequest), genericArguments[0]); } @@ -225,13 +291,11 @@ public class ConsoleLogsAuthorizationTests private static ElsaConsoleLogsHub CreateHub(TestConsoleLogProvider provider, params string[] permissions) { - var sourceRegistry = new TestConsoleLogSourceRegistry(); - var mapper = new ConsoleLogStreamingApiMapper(); var hubContext = new TestHubContext(); - var subscriptionManager = new ElsaConsoleLogSubscriptionManager(provider, sourceRegistry, mapper, hubContext, NullLogger.Instance); - var authorizer = new ElsaConsoleLogStreamingHubAuthorizer(); + var subscriptionManager = new ElsaConsoleLogSubscriptionManager(provider, hubContext, NullLogger.Instance); + var authorizer = new ElsaConsoleLogStreamHubAuthorizer(); - return new ElsaConsoleLogsHub(provider, mapper, authorizer, subscriptionManager) + return new ElsaConsoleLogsHub(provider, authorizer, subscriptionManager) { Context = new TestHubCallerContext(CreateUser(permissions)) }; @@ -250,83 +314,58 @@ public class ConsoleLogsAuthorizationTests private class TestConsoleLogProvider : IConsoleLogProvider { - private readonly TaskCompletionSource _subscriptionFilterSet = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _subscriptionFilterSet = new(TaskCreationOptions.RunContinuationsAsynchronously); - public ConsoleLogStreaming.Core.Models.ConsoleLogFilter? LastFilter { get; private set; } - public ConsoleLogStreaming.Core.Models.ConsoleLogFilter? LastSubscriptionFilter { get; private set; } + public ConsoleLogFilter? LastFilter { get; private set; } + public ConsoleLogFilter? LastSubscriptionFilter { get; private set; } - public Task WaitForSubscriptionFilterAsync() => + public Task WaitForSubscriptionFilterAsync() => _subscriptionFilterSet.Task.WaitAsync(TimeSpan.FromSeconds(5)); - public ValueTask PublishAsync(ConsoleLogStreaming.Core.Models.ConsoleLogLine line, CancellationToken cancellationToken = default) + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) { return ValueTask.CompletedTask; } - public ValueTask GetRecentAsync(ConsoleLogStreaming.Core.Models.ConsoleLogFilter filter, CancellationToken cancellationToken = default) + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) { LastFilter = filter; - return ValueTask.FromResult(new ConsoleLogStreaming.Core.Models.RecentConsoleLogsResult()); + return ValueTask.FromResult(new RecentConsoleLogsResult()); } - public IAsyncEnumerable SubscribeAsync( - ConsoleLogStreaming.Core.Models.ConsoleLogFilter filter, + public IAsyncEnumerable SubscribeAsync( + ConsoleLogFilter filter, CancellationToken cancellationToken = default) { LastSubscriptionFilter = filter; _subscriptionFilterSet.TrySetResult(filter); - return AsyncEnumerable.Empty(); + return AsyncEnumerable.Empty(); } - public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) { - return ValueTask.FromResult>([]); + return ValueTask.FromResult>([]); } } - private class TestConsoleLogSourceRegistry : IConsoleLogSourceRegistry + private class TestHubContext : IHubContext { - public event Action? SourceChanged - { - add { } - remove { } - } - - public ConsoleLogStreaming.Core.Models.ConsoleLogSource Current { get; } = new() - { - Id = "test", - DisplayName = "Test" - }; - - public ConsoleLogStreaming.Core.Models.ConsoleLogSource MarkSeen(ConsoleLogStreaming.Core.Models.ConsoleLogSource source, DateTimeOffset timestamp) - { - return source with { LastSeen = timestamp }; - } - - public IReadOnlyCollection List() - { - return [Current]; - } - } - - private class TestHubContext : IHubContext - { - public IHubClients Clients { get; } = new TestHubClients(); + public IHubClients Clients { get; } = new TestHubClients(); public IGroupManager Groups { get; } = new TestGroupManager(); } - private class TestHubClients : IHubClients + private class TestHubClients : IHubClients { - public IConsoleLogsClient All => throw new NotSupportedException(); - public IConsoleLogsClient AllExcept(IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); - public IConsoleLogsClient Client(string connectionId) => throw new NotSupportedException(); - public IConsoleLogsClient Clients(IReadOnlyList connectionIds) => throw new NotSupportedException(); - public IConsoleLogsClient Group(string groupName) => throw new NotSupportedException(); - public IConsoleLogsClient GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); - public IConsoleLogsClient Groups(IReadOnlyList groupNames) => throw new NotSupportedException(); - public IConsoleLogsClient User(string userId) => throw new NotSupportedException(); - public IConsoleLogsClient Users(IReadOnlyList userIds) => throw new NotSupportedException(); + public IElsaConsoleLogsClient All => throw new NotSupportedException(); + public IElsaConsoleLogsClient AllExcept(IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); + public IElsaConsoleLogsClient Client(string connectionId) => throw new NotSupportedException(); + public IElsaConsoleLogsClient Clients(IReadOnlyList connectionIds) => throw new NotSupportedException(); + public IElsaConsoleLogsClient Group(string groupName) => throw new NotSupportedException(); + public IElsaConsoleLogsClient GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); + public IElsaConsoleLogsClient Groups(IReadOnlyList groupNames) => throw new NotSupportedException(); + public IElsaConsoleLogsClient User(string userId) => throw new NotSupportedException(); + public IElsaConsoleLogsClient Users(IReadOnlyList userIds) => throw new NotSupportedException(); } private class TestGroupManager : IGroupManager diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs index ca31b3050..321d1a6f1 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs @@ -1,4 +1,9 @@ -using ConsoleLogStreaming.SignalR; +using ConsoleLogStreaming.Core; +using ConsoleLogStreaming.Core.Models; +using Elsa.Diagnostics.ConsoleLogs.Contracts; +using Elsa.Diagnostics.ConsoleLogs.RealTime; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging.Abstractions; namespace Elsa.Diagnostics.ConsoleLogs.IntegrationTests; @@ -7,6 +12,98 @@ public class ConsoleLogsHubSourceStatusTests [Fact] public void ClientContract_ExposesSourceChangeMethod() { - Assert.NotNull(typeof(IConsoleLogsClient).GetMethod(nameof(IConsoleLogsClient.ReceiveSourceChangedAsync))); + Assert.NotNull(typeof(IElsaConsoleLogsClient).GetMethod(nameof(IElsaConsoleLogsClient.ReceiveSourceChangedAsync))); + } + + [Fact] + public async Task PushedSubscription_ForwardsSourceChangeFromConsoleLines() + { + var source = new ConsoleLogSource { Id = "source-1", DisplayName = "Source 1" }; + var provider = new SingleLineProvider(new ConsoleLogLine { Text = "message", Source = source }); + var client = new TestConsoleLogsClient(); + var hubContext = new TestHubContext(client); + var manager = new ElsaConsoleLogSubscriptionManager(provider, hubContext, NullLogger.Instance); + + await manager.SubscribeAsync("connection-1", new ElsaConsoleLogFilter(), CancellationToken.None); + + Assert.Same(source, await client.SourceChanged.Task.WaitAsync(TimeSpan.FromSeconds(5))); + } + + private sealed class SingleLineProvider(ConsoleLogLine line) : IConsoleLogProvider + { + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + return ValueTask.CompletedTask; + } + + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(new RecentConsoleLogsResult()); + } + + public async IAsyncEnumerable SubscribeAsync(ConsoleLogFilter filter, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return ConsoleLogStreamingItem.FromLine(line); + await Task.Yield(); + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return ValueTask.FromResult>([line.Source]); + } + } + + private sealed class TestConsoleLogsClient : IElsaConsoleLogsClient + { + public TaskCompletionSource SourceChanged { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously); + + public Task ReceiveConsoleLogLineAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + + public Task ReceiveDroppedLinesAsync(ConsoleLogDroppedSummary summary, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + + public Task ReceiveSourceChangedAsync(ConsoleLogSource source, CancellationToken cancellationToken = default) + { + SourceChanged.TrySetResult(source); + return Task.CompletedTask; + } + } + + private sealed class TestHubContext(IElsaConsoleLogsClient client) : IHubContext + { + public IHubClients Clients { get; } = new TestHubClients(client); + + public IGroupManager Groups { get; } = new TestGroupManager(); + } + + private sealed class TestHubClients(IElsaConsoleLogsClient client) : IHubClients + { + public IElsaConsoleLogsClient All => client; + public IElsaConsoleLogsClient AllExcept(IReadOnlyList excludedConnectionIds) => client; + public IElsaConsoleLogsClient Client(string connectionId) => client; + public IElsaConsoleLogsClient Clients(IReadOnlyList connectionIds) => client; + public IElsaConsoleLogsClient Group(string groupName) => client; + public IElsaConsoleLogsClient GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => client; + public IElsaConsoleLogsClient Groups(IReadOnlyList groupNames) => client; + public IElsaConsoleLogsClient User(string userId) => client; + public IElsaConsoleLogsClient Users(IReadOnlyList userIds) => client; + } + + private sealed class TestGroupManager : IGroupManager + { + public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + + public Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } } } diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsModuleTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsModuleTests.cs index 0dd1fc06f..40d05a073 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsModuleTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsModuleTests.cs @@ -25,5 +25,6 @@ public class ConsoleLogsModuleTests Assert.DoesNotContain("Elsa.Diagnostics.StructuredLogs", references); Assert.DoesNotContain("Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite", references); + Assert.DoesNotContain("ConsoleLogStreaming.Persistence.Sqlite", references); } } diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsRecentEndpointTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsRecentEndpointTests.cs index ac94f5456..7b226a5df 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsRecentEndpointTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsRecentEndpointTests.cs @@ -5,7 +5,7 @@ public class ConsoleLogsRecentEndpointTests [Fact] public void RecentEndpoint_ExistsInConsoleLogsAssembly() { - var endpointType = typeof(Elsa.Diagnostics.ConsoleLogs.Features.ConsoleLogsFeature) + var endpointType = typeof(Features.ConsoleLogsFeature) .Assembly .GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent.Endpoint"); diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsSourcesEndpointTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsSourcesEndpointTests.cs index 715d31b59..8fd387e33 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsSourcesEndpointTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsSourcesEndpointTests.cs @@ -5,7 +5,7 @@ public class ConsoleLogsSourcesEndpointTests [Fact] public void SourcesEndpoint_ExistsInConsoleLogsAssembly() { - var endpointType = typeof(Elsa.Diagnostics.ConsoleLogs.Features.ConsoleLogsFeature) + var endpointType = typeof(Features.ConsoleLogsFeature) .Assembly .GetType("Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Sources.Endpoint"); diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/Elsa.Diagnostics.ConsoleLogs.IntegrationTests.csproj b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/Elsa.Diagnostics.ConsoleLogs.IntegrationTests.csproj index 67ef05beb..ac46ee106 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/Elsa.Diagnostics.ConsoleLogs.IntegrationTests.csproj +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/Elsa.Diagnostics.ConsoleLogs.IntegrationTests.csproj @@ -7,6 +7,7 @@ + diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj new file mode 100644 index 000000000..ce0f941e2 --- /dev/null +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj @@ -0,0 +1,14 @@ + + + + [Elsa.Diagnostics.OpenTelemetry]* + 0 + true + + + + + + + + diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryAuthorizationTests.cs b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryAuthorizationTests.cs new file mode 100644 index 000000000..b5c8d37a3 --- /dev/null +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryAuthorizationTests.cs @@ -0,0 +1,102 @@ +using System.Reflection; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Features; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using FastEndpoints; + +namespace Elsa.Diagnostics.OpenTelemetry.IntegrationTests; + +public class OpenTelemetryAuthorizationTests +{ + [Theory] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Resources.Endpoint")] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Traces.Endpoint")] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Trace.Endpoint")] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Metrics.Endpoint")] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Logs.Endpoint")] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Storage.Endpoint")] + [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.CollectorConfiguration.Endpoint")] + public void RestEndpoints_RequireOpenTelemetryReadPermission(string endpointTypeName) + { + var permissions = GetConfiguredPermissions(endpointTypeName); + + Assert.Contains(OpenTelemetryPermissions.Read, permissions); + } + + private static IReadOnlyCollection GetConfiguredPermissions(string endpointTypeName) + { + var endpointType = typeof(OpenTelemetryFeature).Assembly.GetType(endpointTypeName, throwOnError: true)!; + var endpoint = Activator.CreateInstance(endpointType, new TestOpenTelemetryProvider())!; + var (requestDtoType, responseDtoType) = GetEndpointDtoTypes(endpointType); + var definition = new EndpointDefinition(endpointType, requestDtoType, responseDtoType); + + endpointType + .GetProperty("Definition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)! + .SetValue(endpoint, definition); + + endpointType.GetMethod("Configure")!.Invoke(endpoint, null); + + var permissions = definition + .GetType() + .GetProperty("AllowedPermissions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)! + .GetValue(definition); + + return Assert.IsAssignableFrom>(permissions).ToArray(); + } + + private static (Type RequestDtoType, Type ResponseDtoType) GetEndpointDtoTypes(Type endpointType) + { + var type = endpointType; + + while (type.BaseType != null) + { + type = type.BaseType; + + if (!type.IsGenericType) + continue; + + var genericTypeDefinition = type.GetGenericTypeDefinition(); + var genericArguments = type.GetGenericArguments(); + + if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpoint<,>)) + return (genericArguments[0], genericArguments[1]); + + if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpoint<,,>)) + return (genericArguments[0], genericArguments[1]); + + if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpointWithoutRequest<>)) + return (typeof(EmptyRequest), genericArguments[0]); + } + + throw new InvalidOperationException($"Unsupported endpoint type '{endpointType.FullName}'."); + } + + private class TestOpenTelemetryProvider : IOpenTelemetryProvider + { + public ValueTask GetResourcesAsync(OpenTelemetryResourceFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryResourceResult([], 0)); + + public ValueTask GetTracesAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryTraceResult([], 0)); + + public ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default) => ValueTask.FromResult(null); + + public ValueTask GetMetricsAsync(OpenTelemetryMetricFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryMetricResult([], [], 0)); + + public ValueTask GetLogsAsync(OpenTelemetryLogFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryLogResult([], 0)); + + public ValueTask GetStorageDiagnosticsAsync(CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryStorageDiagnostics(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + + public ValueTask GetCollectorConfigurationAsync(CancellationToken cancellationToken = default) + { + var configuration = new CollectorConfiguration( + new CollectorEndpointInfo("http/protobuf", "/elsa/otlp/v1", true, null), + new CollectorEndpointInfo("grpc", null, false, "Disabled"), + "OTEL_SERVICE_NAME", + "OTEL_EXPORTER_OTLP_ENDPOINT", + "OTEL_EXPORTER_OTLP_PROTOCOL", + new Dictionary()); + + return ValueTask.FromResult(configuration); + } + } +} diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs new file mode 100644 index 000000000..d65e12d8e --- /dev/null +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs @@ -0,0 +1,238 @@ +using System.Security.Claims; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Permissions; +using Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; +using Elsa.Diagnostics.OpenTelemetry.RealTime; +using FastEndpoints; +using FastEndpoints.Security; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit.Sdk; +using OptionsFactory = Microsoft.Extensions.Options.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.IntegrationTests; + +public class OpenTelemetryHubTests +{ + private readonly DateTimeOffset _now = new(2026, 5, 26, 10, 0, 0, TimeSpan.Zero); + + [Fact] + public async Task SubscribeAsync_WhenUserLacksPermission_DeniesAccess() + { + var hub = CreateHub(new TestLiveFeed(), "write:diagnostics:opentelemetry"); + + await Assert.ThrowsAsync(() => hub.SubscribeAsync(new())); + } + + [Theory] + [InlineData(OpenTelemetryPermissions.Read)] + [InlineData(PermissionNames.All)] + [InlineData("read:*")] + public async Task SubscribeAsync_WhenUserCanRead_ForwardsItemsToCaller(string permission) + { + var liveFeed = new TestLiveFeed(new OpenTelemetryStreamItem { Trace = Trace("trace-1") }); + var caller = new CapturingOpenTelemetryClient(); + var hub = CreateHub(liveFeed, permission, caller); + + await hub.SubscribeAsync(new OpenTelemetryTraceFilter { TraceId = "trace-1" }); + + await AssertEventuallyAsync(() => + { + Assert.Equal("trace-1", Assert.Single(caller.Items).Trace?.TraceId); + Assert.Equal("trace-1", liveFeed.Filter?.TraceId); + }); + } + + [Fact] + public async Task SubscribeAsync_WhenFilterTimeRangeIsInvalid_RejectsFilter() + { + var hub = CreateHub(new TestLiveFeed(), OpenTelemetryPermissions.Read); + + await Assert.ThrowsAsync(() => hub.SubscribeAsync(new OpenTelemetryTraceFilter + { + From = _now.AddMinutes(1), + To = _now + })); + } + + [Fact] + public async Task LiveFeed_WhenTraceFilterIsSet_OnlyPublishesMatchingTraces() + { + var liveFeed = new InMemoryOpenTelemetryLiveFeed(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions())); + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + await using var enumerator = liveFeed.SubscribeAsync(new OpenTelemetryTraceFilter { TraceId = "trace-keep" }, timeout.Token).GetAsyncEnumerator(timeout.Token); + var next = enumerator.MoveNextAsync().AsTask(); + + await liveFeed.PublishAsync(new OpenTelemetryBatch([], [Trace("trace-skip"), Trace("trace-keep")], [], [], [], []), timeout.Token); + + Assert.True(await next); + Assert.Equal("trace-keep", enumerator.Current.Trace?.TraceId); + } + + [Fact] + public async Task LiveFeed_WhenSubscriberQueueOverflows_PublishesDroppedItemSummary() + { + var liveFeed = new InMemoryOpenTelemetryLiveFeed(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions { SubscriberChannelCapacity = 1 })); + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + await using var enumerator = liveFeed.SubscribeAsync(new OpenTelemetryTraceFilter(), timeout.Token).GetAsyncEnumerator(timeout.Token); + var first = enumerator.MoveNextAsync().AsTask(); + + await liveFeed.PublishAsync(new OpenTelemetryBatch([], [Trace("trace-1"), Trace("trace-2"), Trace("trace-3")], [], [], [], []), timeout.Token); + + Assert.True(await first); + + OpenTelemetryStreamItem? summary = enumerator.Current.DroppedItems != null ? enumerator.Current : null; + for (var i = 0; summary == null && i < 5 && await enumerator.MoveNextAsync(); i++) + { + if (enumerator.Current.DroppedItems != null) + summary = enumerator.Current; + } + + Assert.NotNull(summary); + var nonNullSummary = summary!; + Assert.Equal(OpenTelemetrySignalType.Trace, nonNullSummary.DroppedItems!.SignalType); + Assert.Equal("SubscriberQueueFull", nonNullSummary.DroppedItems.Reason); + Assert.True(nonNullSummary.DroppedItems.Count > 0); + } + + private OpenTelemetryHub CreateHub(IOpenTelemetryLiveFeed liveFeed, string permission, IOpenTelemetryClient? caller = null) + { + caller ??= new CapturingOpenTelemetryClient(); + var hubContext = new TestHubContext(caller); + var subscriptionManager = new OpenTelemetrySubscriptionManager(liveFeed, hubContext, NullLogger.Instance); + + return new OpenTelemetryHub(subscriptionManager) + { + Context = new TestHubCallerContext(CreateUser(permission)), + Clients = new TestHubCallerClients(caller) + }; + } + + private ClaimsPrincipal CreateUser(string permission) + { + var permissionClaimType = (string)typeof(SecurityOptions) + .GetProperty(nameof(SecurityOptions.PermissionsClaimType))! + .GetValue(new Config().Security)!; + var identity = new ClaimsIdentity([new Claim(permissionClaimType, permission)], "Test"); + + return new ClaimsPrincipal(identity); + } + + private TelemetryTrace Trace(string traceId) + { + return new(traceId, $"{traceId}-root", traceId, _now, _now.AddMilliseconds(10), TimeSpan.FromMilliseconds(10), SpanStatus.Ok, [], [], 1); + } + + private class TestLiveFeed(params OpenTelemetryStreamItem[] items) : IOpenTelemetryLiveFeed + { + public OpenTelemetryTraceFilter? Filter { get; private set; } + + public ValueTask PublishAsync(OpenTelemetryBatch batch, CancellationToken cancellationToken = default) => ValueTask.CompletedTask; + + public async IAsyncEnumerable SubscribeAsync(OpenTelemetryTraceFilter filter, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) + { + Filter = filter; + + foreach (var item in items) + { + cancellationToken.ThrowIfCancellationRequested(); + yield return item; + await Task.Yield(); + } + } + } + + private class CapturingOpenTelemetryClient : IOpenTelemetryClient + { + public List Items { get; } = []; + + public Task ReceiveAsync(OpenTelemetryStreamItem item) + { + Items.Add(item); + return Task.CompletedTask; + } + } + + private class TestHubCallerClients(IOpenTelemetryClient caller) : IHubCallerClients + { + public IOpenTelemetryClient Caller { get; } = caller; + public IOpenTelemetryClient Others => throw new NotSupportedException(); + public IOpenTelemetryClient All => throw new NotSupportedException(); + public IOpenTelemetryClient AllExcept(IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); + public IOpenTelemetryClient Client(string connectionId) => throw new NotSupportedException(); + public IOpenTelemetryClient Clients(IReadOnlyList connectionIds) => throw new NotSupportedException(); + public IOpenTelemetryClient Group(string groupName) => throw new NotSupportedException(); + public IOpenTelemetryClient GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); + public IOpenTelemetryClient Groups(IReadOnlyList groupNames) => throw new NotSupportedException(); + public IOpenTelemetryClient OthersInGroup(string groupName) => throw new NotSupportedException(); + public IOpenTelemetryClient User(string userId) => throw new NotSupportedException(); + public IOpenTelemetryClient Users(IReadOnlyList userIds) => throw new NotSupportedException(); + } + + private class TestHubContext(IOpenTelemetryClient caller) : IHubContext + { + public IHubClients Clients { get; } = new TestHubClients(caller); + + public IGroupManager Groups { get; } = new TestGroupManager(); + } + + private class TestHubClients(IOpenTelemetryClient caller) : IHubClients + { + public IOpenTelemetryClient All => throw new NotSupportedException(); + public IOpenTelemetryClient AllExcept(IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); + public IOpenTelemetryClient Client(string connectionId) => caller; + public IOpenTelemetryClient Clients(IReadOnlyList connectionIds) => throw new NotSupportedException(); + public IOpenTelemetryClient Group(string groupName) => throw new NotSupportedException(); + public IOpenTelemetryClient GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => throw new NotSupportedException(); + public IOpenTelemetryClient Groups(IReadOnlyList groupNames) => throw new NotSupportedException(); + public IOpenTelemetryClient User(string userId) => throw new NotSupportedException(); + public IOpenTelemetryClient Users(IReadOnlyList userIds) => throw new NotSupportedException(); + } + + private class TestGroupManager : IGroupManager + { + public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default) => Task.CompletedTask; + + public Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default) => Task.CompletedTask; + } + + private static async Task AssertEventuallyAsync(Action assertion) + { + var deadline = DateTimeOffset.UtcNow.AddSeconds(3); + Exception? lastException = null; + + while (DateTimeOffset.UtcNow < deadline) + { + try + { + assertion(); + return; + } + catch (XunitException e) + { + lastException = e; + await Task.Delay(25); + } + } + + if (lastException != null) + throw lastException; + } + + private class TestHubCallerContext(ClaimsPrincipal user) : HubCallerContext + { + public override string ConnectionId { get; } = "connection-1"; + public override string? UserIdentifier { get; } = "user-1"; + public override ClaimsPrincipal? User { get; } = user; + public override IDictionary Items { get; } = new Dictionary(); + public override IFeatureCollection Features { get; } = new FeatureCollection(); + public override CancellationToken ConnectionAborted { get; } = CancellationToken.None; + + public override void Abort() + { + } + } +} diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpHttpIngestionTests.cs b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpHttpIngestionTests.cs new file mode 100644 index 000000000..d0c48fb7a --- /dev/null +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpHttpIngestionTests.cs @@ -0,0 +1,189 @@ +using System.Buffers.Binary; +using System.Net; +using System.Text; +using Elsa.Diagnostics.OpenTelemetry.Contracts; +using Elsa.Diagnostics.OpenTelemetry.Extensions; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Diagnostics.OpenTelemetry.IntegrationTests; + +public class OtlpHttpIngestionTests : IAsyncLifetime +{ + private static readonly byte[] TraceId = Convert.FromHexString("00112233445566778899aabbccddeeff"); + private static readonly byte[] SpanId = Convert.FromHexString("0011223344556677"); + private static readonly byte[] ChildSpanId = Convert.FromHexString("8899aabbccddeeff"); + private static readonly DateTimeOffset Timestamp = new(2026, 5, 26, 10, 0, 0, TimeSpan.Zero); + + private WebApplication? _app; + private HttpClient _httpClient = null!; + + public async Task InitializeAsync() + { + var builder = WebApplication.CreateSlimBuilder(); + builder.WebHost.UseTestServer(); + builder.Services.AddOpenTelemetryDiagnosticsServices(options => + { + options.AllowUnauthenticatedLoopback = true; + options.HttpEndpointPath = "/elsa/otlp/v1"; + }); + + _app = builder.Build(); + _app.Use((context, next) => + { + context.Connection.RemoteIpAddress = IPAddress.Loopback; + return next(); + }); + _app.MapOpenTelemetryHttpProtobufCollector(); + + await _app.StartAsync(); + _httpClient = _app.GetTestClient(); + } + + public async Task DisposeAsync() + { + _httpClient.Dispose(); + + if (_app == null) + return; + + await _app.StopAsync(); + await _app.DisposeAsync(); + } + + [Fact] + public async Task PostTraces_WhenPayloadIsValid_StoresQueryableTrace() + { + using var content = new ByteArrayContent(CreateTracePayload()); + content.Headers.ContentType = new("application/x-protobuf"); + + var response = await _httpClient.PostAsync("/elsa/otlp/v1/traces", content); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var provider = _app!.Services.GetRequiredService(); + var result = await provider.GetTracesAsync(new OpenTelemetryTraceFilter { TraceId = "00112233445566778899aabbccddeeff" }); + var trace = Assert.Single(result.Items); + + Assert.Equal("Workflow/Approve", trace.Name); + Assert.Equal("wf-1", Assert.Single(trace.WorkflowInstanceIds)); + + var detail = await provider.GetTraceAsync(trace.TraceId); + + Assert.NotNull(detail); + Assert.Equal(2, detail.Spans.Count); + + var rootSpan = Assert.Single(detail.Spans, x => x.SpanId == "0011223344556677"); + Assert.Equal("order-workflow", rootSpan.Attributes["workflow.definition.id"]); + Assert.Equal("wf-1", rootSpan.Attributes["workflow.instance.id"]); + + var activitySpan = Assert.Single(detail.Spans, x => x.SpanId == "8899aabbccddeeff"); + Assert.Equal("0011223344556677", activitySpan.ParentSpanId); + Assert.Equal("approve-task", activitySpan.Attributes["activity.id"]); + Assert.Equal("node-approve", activitySpan.Attributes["activity.node.id"]); + } + + [Fact] + public async Task PostTraces_WhenPayloadExceedsConfiguredLimit_ReturnsPayloadTooLarge() + { + _app!.Services.GetRequiredService>().Value.MaxHttpRequestBodySize = 1; + using var content = new ByteArrayContent(CreateTracePayload()); + content.Headers.ContentType = new("application/x-protobuf"); + + var response = await _httpClient.PostAsync("/elsa/otlp/v1/traces", content); + + Assert.Equal(HttpStatusCode.RequestEntityTooLarge, response.StatusCode); + } + + [Fact] + public async Task PostTraces_WhenPayloadIsTruncated_ReturnsBadRequest() + { + using var content = new ByteArrayContent([0x0a, 0x04, 0x08]); + content.Headers.ContentType = new("application/x-protobuf"); + + var response = await _httpClient.PostAsync("/elsa/otlp/v1/traces", content); + + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + private static byte[] CreateTracePayload() + { + return Message(1, + Join( + Message(1, Resource()), + Message(2, + Join( + Message(2, + Join( + Bytes(1, TraceId), + Bytes(2, SpanId), + String(5, "Workflow/Approve"), + Varint(6, 1), + Varint(7, UnixNanos(Timestamp)), + Varint(8, UnixNanos(Timestamp.AddMilliseconds(25))), + Message(9, KeyValue("workflow.instance.id", "wf-1")), + Message(9, KeyValue("workflow.definition.id", "order-workflow")), + Message(15, Varint(3, 1)))), + Message(2, + Join( + Bytes(1, TraceId), + Bytes(2, ChildSpanId), + Bytes(4, SpanId), + String(5, "Activity/ApproveTask"), + Varint(6, 1), + Varint(7, UnixNanos(Timestamp.AddMilliseconds(5))), + Varint(8, UnixNanos(Timestamp.AddMilliseconds(20))), + Message(9, KeyValue("workflow.instance.id", "wf-1")), + Message(9, KeyValue("activity.id", "approve-task")), + Message(9, KeyValue("activity.node.id", "node-approve")), + Message(15, Varint(3, 1)))))))); + } + + private static byte[] Resource() + { + return Join( + Message(1, KeyValue("service.name", "elsa-server")), + Message(1, KeyValue("service.instance.id", "node-1")), + Message(1, KeyValue("telemetry.sdk.language", "dotnet"))); + } + + private static byte[] KeyValue(string key, string value) => Join(String(1, key), Message(2, String(1, value))); + + private static byte[] Message(int fieldNumber, byte[] value) => Join(Varint((ulong)((fieldNumber << 3) | 2)), Varint((ulong)value.Length), value); + + private static byte[] String(int fieldNumber, string value) => Message(fieldNumber, Encoding.UTF8.GetBytes(value)); + + private static byte[] Bytes(int fieldNumber, byte[] value) => Message(fieldNumber, value); + + private static byte[] Varint(int fieldNumber, ulong value) => Join(Varint((ulong)(fieldNumber << 3)), Varint(value)); + + private static byte[] Varint(ulong value) + { + var bytes = new List(); + while (value >= 0x80) + { + bytes.Add((byte)(value | 0x80)); + value >>= 7; + } + bytes.Add((byte)value); + return bytes.ToArray(); + } + + private static ulong UnixNanos(DateTimeOffset timestamp) => (ulong)(timestamp - DateTimeOffset.UnixEpoch).Ticks * 100; + + private static byte[] Join(params byte[][] segments) + { + var result = new byte[segments.Sum(x => x.Length)]; + var offset = 0; + foreach (var segment in segments) + { + segment.CopyTo(result, offset); + offset += segment.Length; + } + + return result; + } +} diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpIngestionSecurityTests.cs b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpIngestionSecurityTests.cs new file mode 100644 index 000000000..bee271fc8 --- /dev/null +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OtlpIngestionSecurityTests.cs @@ -0,0 +1,101 @@ +using System.Net; +using Elsa.Diagnostics.OpenTelemetry.Extensions; +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Services; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using OptionsFactory = Microsoft.Extensions.Options.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.IntegrationTests; + +public class OtlpIngestionSecurityTests +{ + [Fact] + public async Task PostTraces_WhenLoopbackAndNoApiKey_AllowsDevelopmentIngestion() + { + await using var app = await CreateAppAsync(); + using var client = app.GetTestClient(); + + var response = await client.PostAsync("/elsa/otlp/v1/traces", CreateEmptyProtobufContent()); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task PostTraces_WhenNonLoopbackAndNoApiKey_RejectsIngestion() + { + await using var app = await CreateAppAsync(); + using var client = app.GetTestClient(); + using var request = new HttpRequestMessage(HttpMethod.Post, "/elsa/otlp/v1/traces") + { + Content = CreateEmptyProtobufContent() + }; + request.Headers.Add("x-test-remote-ip", "10.0.0.5"); + + var response = await client.SendAsync(request); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task PostTraces_WhenApiKeyMatches_AllowsNonLoopbackIngestion() + { + await using var app = await CreateAppAsync(options => options.ApiKey = "secret"); + using var client = app.GetTestClient(); + using var request = new HttpRequestMessage(HttpMethod.Post, "/elsa/otlp/v1/traces") + { + Content = CreateEmptyProtobufContent() + }; + request.Headers.Add("x-test-remote-ip", "10.0.0.5"); + request.Headers.Add("x-otlp-api-key", "secret"); + + var response = await client.SendAsync(request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task CollectorConfiguration_WhenApiKeyIsConfigured_DoesNotExposeSecret() + { + var provider = new CollectorConfigurationProvider(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions { ApiKey = "secret" })); + + var configuration = await provider.GetAsync(); + + Assert.Equal("", configuration.RequiredHeaders["x-otlp-api-key"]); + Assert.DoesNotContain("secret", configuration.RequiredHeaders.Values); + } + + private static async Task CreateAppAsync(Action? configure = null) + { + var builder = WebApplication.CreateSlimBuilder(); + builder.WebHost.UseTestServer(); + builder.Services.AddOpenTelemetryDiagnosticsServices(options => + { + options.AllowUnauthenticatedLoopback = true; + options.HttpEndpointPath = "/elsa/otlp/v1"; + configure?.Invoke(options); + }); + + var app = builder.Build(); + app.Use(async (context, next) => + { + context.Connection.RemoteIpAddress = context.Request.Headers.TryGetValue("x-test-remote-ip", out var value) && IPAddress.TryParse(value.ToString(), out var remoteIpAddress) + ? remoteIpAddress + : IPAddress.Loopback; + + await next(); + }); + app.MapOpenTelemetryHttpProtobufCollector(); + await app.StartAsync(); + return app; + } + + private static ByteArrayContent CreateEmptyProtobufContent() + { + var content = new ByteArrayContent([]); + content.Headers.ContentType = new("application/x-protobuf"); + return content; + } +} diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Usings.cs b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Usings.cs new file mode 100644 index 000000000..c802f4480 --- /dev/null +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/test/integration/Elsa.JavaScript.IntegrationTests/JavaScriptFeatureTests.cs b/test/integration/Elsa.JavaScript.IntegrationTests/JavaScriptFeatureTests.cs deleted file mode 100644 index a6fcd4dfb..000000000 --- a/test/integration/Elsa.JavaScript.IntegrationTests/JavaScriptFeatureTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Reflection; -using Elsa.Expressions.JavaScript.ShellFeatures; -using Elsa.Expressions.Options; -using Elsa.Expressions.Services; -using Jint.Runtime; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Elsa.JavaScript.IntegrationTests; - -public class JavaScriptFeatureTests -{ - [Fact] - public void ConfigureServices_RegistersUniqueWrapperExceptionAlias() - { - var services = new ServiceCollection(); - var feature = new JavaScriptFeature(); - var wrapperExceptionType = typeof(JavaScriptException).GetNestedType("JavaScriptErrorWrapperException", BindingFlags.Public | BindingFlags.NonPublic); - - feature.ConfigureServices(services); - - using var serviceProvider = services.BuildServiceProvider(); - var expressionOptions = serviceProvider.GetRequiredService>(); - var registry = new WellKnownTypeRegistry(expressionOptions); - - Assert.NotNull(wrapperExceptionType); - Assert.True(registry.TryGetType("Jint.JavaScriptErrorWrapperException", out var type)); - Assert.Equal(wrapperExceptionType, type); - Assert.False(registry.TryGetType(wrapperExceptionType.Name, out _)); - } -} diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs index 7684f1da3..e8e6343a9 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs @@ -1,6 +1,5 @@ using System.Text.Json; using System.Text.Json.Nodes; -using Elsa.Expressions.Options; using Elsa.Testing.Shared; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; @@ -10,9 +9,7 @@ namespace Elsa.Workflows.IntegrationTests.Serialization.JsonSerialization; public class SerializationTests(ITestOutputHelper testOutputHelper) { - private readonly IServiceProvider _services = new TestApplicationBuilder(testOutputHelper) - .ConfigureServices(services => services.Configure(options => options.RegisterTypeAlias(typeof(TestObject), nameof(TestObject)))) - .Build(); + private readonly IServiceProvider _services = new TestApplicationBuilder(testOutputHelper).Build(); [Theory(DisplayName = "write")] [InlineData(typeof(JsonObject), "JsonObjectIsland")] @@ -185,4 +182,4 @@ public class SerializationTests(ITestOutputHelper testOutputHelper) public class TestObject { public string? Data { get; set; } -} +} \ No newline at end of file diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs index 29155c1b7..fe1f0cd8d 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs @@ -2,8 +2,8 @@ using System.Dynamic; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; -using Elsa.Expressions.Services; using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.ReferenceHandlers; namespace Elsa.Workflows.IntegrationTests.Serialization.Polymorphism; @@ -14,7 +14,7 @@ public class Tests public void Test1() { var model = CreateModel(); - var expectedJson = File.ReadAllText("Serialization/Polymorphism/data.json").TrimEnd(); + var expectedJson = File.ReadAllText("Serialization/Polymorphism/data.json").Trim(); var actualJson = JsonSerializer.Serialize(model, GetSerializerOptions()); Assert.Equal(expectedJson, actualJson); } @@ -74,10 +74,6 @@ public class Tests private JsonSerializerOptions GetSerializerOptions() { var referenceHandler = new CrossScopedReferenceHandler(); - var wellKnownTypeRegistry = new WellKnownTypeRegistry(); - wellKnownTypeRegistry.RegisterType(typeof(Model), nameof(Model)); - wellKnownTypeRegistry.RegisterType(typeof(CustomDictionary), nameof(CustomDictionary)); - var options = new JsonSerializerOptions { ReferenceHandler = referenceHandler, @@ -88,7 +84,7 @@ public class Tests options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(JsonMetadataServices.TimeSpanConverter); - options.Converters.Add(new PolymorphicObjectConverterFactory(wellKnownTypeRegistry)); + options.Converters.Add(new PolymorphicObjectConverterFactory(new WorkflowJsonOptions())); return options; } diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json index 35109c75a..623a5cacc 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json @@ -1 +1 @@ -{"$id":"1","text":"Hello World","number":123,"flag":true,"items":{"$id":"2","$values":[{"$id":"3","text":"Hello","number":1,"flag":true,"items":{"$id":"4","$values":[{"$id":"5","number":0,"flag":false,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$id":"6","$values":[{"$id":"7","text":"Hello","number":1,"flag":true,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$id":"8","content-type":["application/json"],"_type":"CustomDictionary"}}},{"$id":"9","text":"World","number":2,"flag":false}],"_type":"List\u003CModel\u003E"},"CustomDictionary":{"$ref":"8"}}}]}},{"$id":"10","text":"World","number":2,"flag":false}]},"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$ref":"8"}},"payload":{"$id":"11","text":"Payload","number":0,"flag":false,"_type":"Model"},"hashSet":{"$id":"12","$values":[{"$id":"13","text":"I\u0027m a model in a set!","number":0,"flag":false}],"_type":"HashSet\u003CModel\u003E"},"properties":{"$id":"14","Hello":{"$id":"15","text":"Hello","number":1,"flag":true},"World":{"$id":"16","text":"World","number":2,"flag":false}}} +{"$id":"1","text":"Hello World","number":123,"flag":true,"items":{"$id":"2","$values":[{"$id":"3","text":"Hello","number":1,"flag":true,"items":{"$id":"4","$values":[{"$id":"5","number":0,"flag":false,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$id":"6","$values":[{"$id":"7","text":"Hello","number":1,"flag":true,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$id":"8","content-type":["application/json"],"_type":"Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.CustomDictionary, Elsa.Workflows.IntegrationTests"}}},{"$id":"9","text":"World","number":2,"flag":false}],"_type":"System.Collections.Generic.List\u00601[[Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.Model, Elsa.Workflows.IntegrationTests]], System.Private.CoreLib"},"CustomDictionary":{"$ref":"8"}}}]}},{"$id":"10","text":"World","number":2,"flag":false}]},"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$ref":"8"}},"payload":{"$id":"11","text":"Payload","number":0,"flag":false,"_type":"Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.Model, Elsa.Workflows.IntegrationTests"},"hashSet":{"$id":"12","$values":[{"$id":"13","text":"I\u0027m a model in a set!","number":0,"flag":false}],"_type":"System.Collections.Generic.HashSet\u00601[[Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.Model, Elsa.Workflows.IntegrationTests]], System.Private.CoreLib"},"properties":{"$id":"14","Hello":{"$id":"15","text":"Hello","number":1,"flag":true},"World":{"$id":"16","text":"World","number":2,"flag":false}}} \ No newline at end of file diff --git a/test/unit/Elsa.Common.UnitTests/Entities/OrderDefinitionTests.cs b/test/unit/Elsa.Common.UnitTests/Entities/OrderDefinitionTests.cs deleted file mode 100644 index dbecd8972..000000000 --- a/test/unit/Elsa.Common.UnitTests/Entities/OrderDefinitionTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json; -using Elsa.Common.Entities; - -namespace Elsa.Common.UnitTests.Entities; - -public class OrderDefinitionTests -{ - [Fact] - public void Serialize_DoesNotIncludeKeySelectorText() - { - var order = new OrderDefinition(x => x.Name, OrderDirection.Ascending); - - var json = JsonSerializer.Serialize(order); - - Assert.DoesNotContain(nameof(OrderDefinition.KeySelectorText), json); - } - - private sealed class TestEntity - { - public string Name { get; set; } = null!; - } -} diff --git a/test/unit/Elsa.Common.UnitTests/ShellHandlers/MediatorBackgroundTaskTests.cs b/test/unit/Elsa.Common.UnitTests/ShellHandlers/MediatorBackgroundTaskTests.cs new file mode 100644 index 000000000..1a69f350b --- /dev/null +++ b/test/unit/Elsa.Common.UnitTests/ShellHandlers/MediatorBackgroundTaskTests.cs @@ -0,0 +1,101 @@ +using Elsa.Common; +using Elsa.Common.ShellHandlers; +using Elsa.Mediator; +using Elsa.Mediator.Contracts; +using Elsa.Mediator.Models; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Common.UnitTests.ShellHandlers; + +public class MediatorBackgroundTaskTests +{ + [Fact] + public async Task StartAsync_StartsMediatorCommandProcessor() + { + // Arrange + await using var serviceProvider = CreateServiceProvider(); + var backgroundTask = GetMediatorBackgroundTask(serviceProvider); + var commandSender = serviceProvider.GetRequiredService(); + var sink = serviceProvider.GetRequiredService(); + + // Act + await backgroundTask.StartAsync(CancellationToken.None); + + try + { + await commandSender.SendAsync(new TestCommand("hello"), CommandStrategy.Background, CancellationToken.None); + + // Assert + var completedTask = await Task.WhenAny(sink.Handled.Task, Task.Delay(TimeSpan.FromSeconds(5))); + Assert.Same(sink.Handled.Task, completedTask); + Assert.Equal("hello", await sink.Handled.Task); + } + finally + { + await backgroundTask.StopAsync(CancellationToken.None); + } + } + + [Fact] + public async Task StopAsync_KeepsProcessorRunning_UntilAllBackgroundTaskReferencesStop() + { + // Arrange + await using var serviceProvider = CreateServiceProvider(); + await using var scope1 = serviceProvider.CreateAsyncScope(); + await using var scope2 = serviceProvider.CreateAsyncScope(); + var backgroundTask1 = GetMediatorBackgroundTask(scope1.ServiceProvider); + var backgroundTask2 = GetMediatorBackgroundTask(scope2.ServiceProvider); + var commandSender = serviceProvider.GetRequiredService(); + var sink = serviceProvider.GetRequiredService(); + + // Act + await backgroundTask1.StartAsync(CancellationToken.None); + await backgroundTask2.StartAsync(CancellationToken.None); + await backgroundTask1.StopAsync(CancellationToken.None); + + try + { + await commandSender.SendAsync(new TestCommand("hello"), CommandStrategy.Background, CancellationToken.None); + + // Assert + var completedTask = await Task.WhenAny(sink.Handled.Task, Task.Delay(TimeSpan.FromSeconds(5))); + Assert.Same(sink.Handled.Task, completedTask); + Assert.Equal("hello", await sink.Handled.Task); + } + finally + { + await backgroundTask2.StopAsync(CancellationToken.None); + } + } + + private static ServiceProvider CreateServiceProvider() + { + var services = new ServiceCollection(); + services.AddLogging(); + new ShellFeatures.MediatorFeature().ConfigureServices(services); + services.AddSingleton(); + services.AddCommandHandler(); + return services.BuildServiceProvider(); + } + + private static MediatorBackgroundTask GetMediatorBackgroundTask(IServiceProvider serviceProvider) + { + return serviceProvider.GetServices().OfType().Single(); + } + + private sealed record TestCommand(string Message) : ICommand; + + private sealed class CommandSink + { + public TaskCompletionSource Handled { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously); + } + + private sealed class TestCommandHandler(CommandSink sink) : ICommandHandler + { + public Task HandleAsync(TestCommand command, CancellationToken cancellationToken) + { + sink.Handled.TrySetResult(command.Message); + return Task.FromResult(Unit.Instance); + } + } +} diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleHostStateCollection.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleHostStateCollection.cs index 01db75930..23d0034e3 100644 --- a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleHostStateCollection.cs +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleHostStateCollection.cs @@ -1,11 +1,9 @@ -using ConsoleLogStreaming.Core; - namespace Elsa.Diagnostics.ConsoleLogs.UnitTests; /// /// xUnit collection used by every test class that mutates the process-wide console stream hook -/// or . Members of this collection run sequentially, preventing parallel -/// tests from racing on the same static state. +/// or console capture. Members of this collection run sequentially, preventing parallel tests from racing +/// on the same static state. /// [CollectionDefinition(Name, DisableParallelization = true)] public sealed class ConsoleHostStateCollection diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogContextAccessorTests.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogContextAccessorTests.cs index e85ba4dff..e756b6ece 100644 --- a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogContextAccessorTests.cs +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogContextAccessorTests.cs @@ -1,5 +1,4 @@ using ConsoleLogStreaming.Core; -using ConsoleLogStreaming.Core.Capture; using ConsoleLogStreaming.Core.DependencyInjection; using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Services; @@ -13,22 +12,10 @@ using Microsoft.Extensions.DependencyInjection; namespace Elsa.Diagnostics.ConsoleLogs.UnitTests; [Collection(ConsoleHostStateCollection.Name)] -public class ConsoleLogContextAccessorTests : IAsyncLifetime +public class ConsoleLogContextAccessorTests { private readonly ConsoleLogContextAccessor _accessor = ConsoleLogContextAccessor.Instance; - public Task InitializeAsync() - { - ConsoleStreamHook.Uninstall(); - return Task.CompletedTask; - } - - public Task DisposeAsync() - { - ConsoleStreamHook.Uninstall(); - return Task.CompletedTask; - } - [Fact] public void PushMetadata_RestoresNestedCaseInsensitiveMetadata() { @@ -90,49 +77,6 @@ public class ConsoleLogContextAccessorTests : IAsyncLifetime Assert.Equal("workflow-b", line.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]); } - [Fact] - public void ConsoleLineBuffer_PreservesWorkflowMetadataForMultilineOutput() - { - var buffer = new ConsoleLineBuffer(Microsoft.Extensions.Options.Options.Create(new ConsoleLogStreaming.Core.Options.ConsoleLogOptions())); - IReadOnlyCollection lines; - - using (_accessor.PushWorkflowInstanceId("workflow-multiline")) - lines = buffer.Append("first line\nsecond line\n", DateTimeOffset.UtcNow, _accessor.GetMetadata()); - - Assert.Collection( - lines, - line => Assert.Equal("workflow-multiline", line.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]), - line => Assert.Equal("workflow-multiline", line.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId])); - } - - [Fact] - public async Task ConsoleCapture_AttachesWorkflowMetadataToNonLoggerConsoleWrites() - { - await using var serviceProvider = new ServiceCollection() - .AddSingleton(_accessor) - .AddConsoleLogStreaming(options => options.SourceId = "test-source") - .BuildServiceProvider(); - - var capture = serviceProvider.GetRequiredService(); - await capture.StartAsync(); - - using (_accessor.PushWorkflowInstanceId("workflow-console")) - Console.WriteLine("plain console output"); - - await capture.StopAsync(); - - var result = await serviceProvider.GetRequiredService().GetRecentAsync(new ConsoleLogStreaming.Core.Models.ConsoleLogFilter - { - Metadata = new Dictionary - { - [ConsoleLogMetadataKeys.WorkflowInstanceId] = "workflow-console" - } - }); - - var line = Assert.Single(result.Items, x => x.Text == "plain console output"); - Assert.Equal("workflow-console", line.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]); - } - [Fact] public async Task WorkflowExecutionMiddleware_PushesWorkflowInstanceMetadata() { diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogsRegistrationTests.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogsRegistrationTests.cs index b3a0ecced..c82975ab1 100644 --- a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogsRegistrationTests.cs +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ConsoleLogsRegistrationTests.cs @@ -1,9 +1,10 @@ using ConsoleLogStreaming.Core; using ConsoleLogStreaming.Core.Capture; -using ConsoleLogStreaming.Core.Hosting; -using ConsoleLogStreaming.Core.Providers; +using ConsoleLogStreaming.Core.Models; +using CShells.Lifecycle; using Elsa.Diagnostics.ConsoleLogs.Contracts; using Elsa.Diagnostics.ConsoleLogs.Extensions; +using Elsa.Diagnostics.ConsoleLogs.RealTime; using Elsa.Diagnostics.ConsoleLogs.Services; using Elsa.Workflows; using Microsoft.Extensions.DependencyInjection; @@ -28,93 +29,83 @@ public class ConsoleLogsRegistrationTests : IAsyncLifetime } [Fact] - public async Task AddConsoleLogsServices_ResolvesHostOwnedSingletons() + public async Task AddConsoleLogsServices_RegistersConsoleLogPipeline() { var services = new ServiceCollection(); + services.AddLogging(); services.AddConsoleLogsServices(); await using var serviceProvider = services.BuildServiceProvider(); - Assert.IsType(serviceProvider.GetRequiredService()); - var contextAccessor = serviceProvider.GetRequiredService(); - Assert.Same(ConsoleLogStreamingHost.SourceRegistry, serviceProvider.GetRequiredService()); - Assert.Same(ConsoleLogStreamingHost.RedactionPipeline, serviceProvider.GetRequiredService()); - Assert.Same(contextAccessor, serviceProvider.GetRequiredService()); - Assert.Same(contextAccessor, serviceProvider.GetRequiredService()); + Assert.NotNull(serviceProvider.GetRequiredService()); + Assert.NotNull(serviceProvider.GetRequiredService()); + Assert.NotNull(serviceProvider.GetRequiredService()); + Assert.NotNull(serviceProvider.GetRequiredService()); + Assert.Same(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService()); + Assert.Same(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService()); + Assert.Contains(serviceProvider.GetServices(), x => x.GetType() == typeof(ConsoleLogCaptureShellInitializer)); + Assert.Contains(serviceProvider.GetServices(), x => x.GetType() == typeof(ConsoleLogCaptureShellDrainHandler)); AssertConsoleLogPipelineContributors(serviceProvider); - Assert.Contains(serviceProvider.GetServices(), x => x.GetType() == typeof(ConsoleLogStreamingHostedService)); - Assert.Same(ConsoleLogStreamingHost.Capture, serviceProvider.GetRequiredService()); - - var services2 = new ServiceCollection(); - services2.AddConsoleLogsServices(); - await using var serviceProvider2 = services2.BuildServiceProvider(); - - Assert.Same(serviceProvider.GetRequiredService(), serviceProvider2.GetRequiredService()); - Assert.Same(serviceProvider.GetRequiredService(), serviceProvider2.GetRequiredService()); - Assert.Same(serviceProvider.GetRequiredService(), serviceProvider2.GetRequiredService()); - Assert.Same(contextAccessor, ConsoleLogStreamingHost.MetadataAccessor); } [Fact] - public async Task AddConsoleLogsServices_RegistersHostOwnedDependencies() + public async Task AddConsoleLogsServices_ShellInitializerStartsCapture() { var services = new ServiceCollection(); + services.AddLogging(); services.AddConsoleLogsServices(); await using var serviceProvider = services.BuildServiceProvider(); + var initializer = serviceProvider.GetServices().OfType().Single(); - foreach (var hostedService in serviceProvider.GetServices()) - await hostedService.StartAsync(CancellationToken.None); + await initializer.InitializeAsync(CancellationToken.None); - var contextAccessor = serviceProvider.GetRequiredService(); - Assert.Same(ConsoleLogStreamingHost.Provider, serviceProvider.GetRequiredService()); - Assert.Same(ConsoleLogStreamingHost.SourceRegistry, serviceProvider.GetRequiredService()); - Assert.Same(ConsoleLogStreamingHost.RedactionPipeline, serviceProvider.GetRequiredService()); - Assert.Same(ConsoleLogStreamingHost.Formatter, serviceProvider.GetRequiredService()); - Assert.Same(contextAccessor, serviceProvider.GetRequiredService()); - Assert.Same(contextAccessor, serviceProvider.GetRequiredService()); - AssertConsoleLogPipelineContributors(serviceProvider); + try + { + var line = $"console-shell-capture-{Guid.NewGuid():N}"; + Console.WriteLine(line); - foreach (var hostedService in serviceProvider.GetServices()) - await hostedService.StopAsync(CancellationToken.None); + var provider = serviceProvider.GetRequiredService(); + + await AssertEventuallyAsync(async () => + { + var result = await provider.GetRecentAsync(new() + { + Query = line, + Limit = 10 + }); + + Assert.Contains(result.Items, x => x.Text.Contains(line, StringComparison.Ordinal)); + }); + } + finally + { + var drainHandler = serviceProvider.GetServices().OfType().Single(); + await drainHandler.DrainAsync(new NoopDrainExtensionHandle(), CancellationToken.None); + } } [Fact] - public async Task ShutdownAsync_ResetsReferenceLeases() - { - ConsoleLogStreamingHost.AddReference(); - ConsoleLogStreamingHost.EnsureInitialized(); - - await ConsoleLogStreamingHost.ShutdownAsync(); - - ConsoleLogStreamingHost.AddReference(); - ConsoleLogStreamingHost.EnsureInitialized(); - await ConsoleLogStreamingHost.ReleaseReferenceAsync(); - - var provider = new CustomProvider(); - Assert.True(ConsoleLogStreamingHost.ConfigureProvider(_ => provider)); - Assert.Same(provider, ConsoleLogStreamingHost.Provider); - } - - [Fact] - public async Task AddConsoleLogsHost_RegistersHostedFlushService() + public async Task AddConsoleLogsHost_RegistersHostedServicesAndCaptureDependencies() { var services = new ServiceCollection(); + services.AddLogging(); services.AddConsoleLogsHost(); await using var serviceProvider = services.BuildServiceProvider(); - - var contextAccessor = serviceProvider.GetRequiredService(); - Assert.Contains(serviceProvider.GetServices(), x => x.GetType() == typeof(ConsoleLogStreamingHostedService)); - Assert.Same(contextAccessor, serviceProvider.GetRequiredService()); - Assert.Same(contextAccessor, serviceProvider.GetRequiredService()); + Assert.NotNull(serviceProvider.GetRequiredService()); + Assert.NotNull(serviceProvider.GetRequiredService()); + Assert.Same(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService()); + Assert.Same(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService()); + Assert.Contains(serviceProvider.GetServices(), x => x.GetType().Name == "ConsoleLogCaptureHostedService"); AssertConsoleLogPipelineContributors(serviceProvider); } [Fact] - public void AddConsoleLogsHost_AppliesConfigurationWhenCalledBeforeFirstAccess() + public void AddConsoleLogsHost_AppliesConfiguration() { var services = new ServiceCollection(); + services.AddLogging(); services.AddConsoleLogsHost(options => options.RecentCapacity = 17); using var serviceProvider = services.BuildServiceProvider(); @@ -123,16 +114,172 @@ public class ConsoleLogsRegistrationTests : IAsyncLifetime } [Fact] - public void AddConsoleLogsHost_DoesNotInitializeHostDuringRegistration() + public async Task DecoratedProvider_AttachesAmbientElsaMetadata() { - var services = new ServiceCollection(); - services.AddConsoleLogsHost(); + await using var serviceProvider = new ServiceCollection() + .AddLogging() + .AddConsoleLogsServices(options => options.SourceId = "test-source") + .BuildServiceProvider(); + var contextAccessor = serviceProvider.GetRequiredService(); + var provider = serviceProvider.GetRequiredService(); - Assert.True(ConsoleLogStreamingHost.Configure(options => options.RecentCapacity = 23)); + using (contextAccessor.PushWorkflowInstanceId("workflow-console")) + await provider.PublishAsync(new ConsoleLogLine { Text = "message", Source = new ConsoleLogSource { Id = "test-source" } }); - using var serviceProvider = services.BuildServiceProvider(); + var result = await provider.GetRecentAsync(new ConsoleLogFilter + { + Metadata = new Dictionary + { + [ConsoleLogMetadataKeys.WorkflowInstanceId] = "workflow-console" + } + }); - Assert.Equal(23, serviceProvider.GetRequiredService>().Value.RecentCapacity); + var line = Assert.Single(result.Items); + Assert.Equal("workflow-console", line.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]); + } + + [Fact] + public async Task ConsoleCapture_AttachesAmbientElsaMetadataAtWriteTime() + { + await using var serviceProvider = new ServiceCollection() + .AddLogging() + .AddConsoleLogsServices(options => options.SourceId = "test-source") + .BuildServiceProvider(); + var contextAccessor = serviceProvider.GetRequiredService(); + var initializer = serviceProvider.GetServices().OfType().Single(); + + await initializer.InitializeAsync(CancellationToken.None); + + try + { + var line = $"console-workflow-capture-{Guid.NewGuid():N}"; + using (contextAccessor.PushWorkflowInstanceId("workflow-captured")) + Console.WriteLine(line); + + var provider = serviceProvider.GetRequiredService(); + + await AssertEventuallyAsync(async () => + { + var result = await provider.GetRecentAsync(new() + { + Metadata = new Dictionary + { + [ConsoleLogMetadataKeys.WorkflowInstanceId] = "workflow-captured" + }, + Query = line, + Limit = 10 + }); + + var capturedLine = Assert.Single(result.Items); + Assert.Equal("workflow-captured", capturedLine.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]); + }); + } + finally + { + var drainHandler = serviceProvider.GetServices().OfType().Single(); + await drainHandler.DrainAsync(new NoopDrainExtensionHandle(), CancellationToken.None); + } + } + + [Fact] + public async Task AddConsoleLogsServices_DecoratesExistingProvider() + { + var innerProvider = new RecordingConsoleLogProvider(); + await using var serviceProvider = new ServiceCollection() + .AddLogging() + .AddSingleton(innerProvider) + .AddConsoleLogsServices() + .BuildServiceProvider(); + var contextAccessor = serviceProvider.GetRequiredService(); + var provider = serviceProvider.GetRequiredService(); + + using (contextAccessor.PushWorkflowInstanceId("workflow-console")) + await provider.PublishAsync(new ConsoleLogLine { Text = "message", Source = new ConsoleLogSource { Id = "test-source" } }); + + Assert.NotNull(innerProvider.PublishedLine); + Assert.Equal("workflow-console", innerProvider.PublishedLine.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]); + } + + [Fact] + public async Task DecoratedProvider_FiltersRecentRowsByMetadataWhenInnerProviderDoesNot() + { + var innerProvider = new MetadataIgnoringConsoleLogProvider(); + await using var serviceProvider = new ServiceCollection() + .AddLogging() + .AddSingleton(innerProvider) + .AddConsoleLogsServices() + .BuildServiceProvider(); + var provider = serviceProvider.GetRequiredService(); + + await provider.PublishAsync(CreateLine("workflow-a", "a")); + await provider.PublishAsync(CreateLine("workflow-b", "b")); + + var result = await provider.GetRecentAsync(new() + { + Metadata = new Dictionary + { + [ConsoleLogMetadataKeys.WorkflowInstanceId] = "workflow-b" + } + }); + + var line = Assert.Single(result.Items); + Assert.Equal("b", line.Text); + } + + [Fact] + public async Task DecoratedProvider_FiltersRecentRowsByBufferedMetadataWhenInnerProviderDropsMetadata() + { + var innerProvider = new MetadataDroppingConsoleLogProvider(); + await using var serviceProvider = new ServiceCollection() + .AddLogging() + .AddSingleton(innerProvider) + .AddConsoleLogsServices() + .BuildServiceProvider(); + var contextAccessor = serviceProvider.GetRequiredService(); + var provider = serviceProvider.GetRequiredService(); + + using (contextAccessor.PushWorkflowInstanceId("workflow-buffered")) + await provider.PublishAsync(new ConsoleLogLine { Text = "buffered", Source = new ConsoleLogSource { Id = "test-source" } }); + + Assert.Empty(Assert.Single(innerProvider.PublishedLines).Metadata); + + var result = await provider.GetRecentAsync(new() + { + Metadata = new Dictionary + { + [ConsoleLogMetadataKeys.WorkflowInstanceId] = "workflow-buffered" + } + }); + + var line = Assert.Single(result.Items); + Assert.Equal("buffered", line.Text); + Assert.Equal("workflow-buffered", line.Metadata[ConsoleLogMetadataKeys.WorkflowInstanceId]); + } + + [Fact] + public async Task DecoratedProvider_FiltersLiveRowsByMetadataWhenInnerProviderDoesNot() + { + var innerProvider = new MetadataIgnoringConsoleLogProvider(); + innerProvider.LiveItems.Add(CreateLine("workflow-a", "a")); + innerProvider.LiveItems.Add(CreateLine("workflow-b", "b")); + + await using var serviceProvider = new ServiceCollection() + .AddLogging() + .AddSingleton(innerProvider) + .AddConsoleLogsServices() + .BuildServiceProvider(); + var provider = serviceProvider.GetRequiredService(); + + var lines = await provider.SubscribeAsync(new() + { + Metadata = new Dictionary + { + [ConsoleLogMetadataKeys.WorkflowInstanceId] = "workflow-b" + } + }).Where(x => x.Line != null).Select(x => x.Line!).ToListAsync(); + + var line = Assert.Single(lines); + Assert.Equal("b", line.Text); } private static void AssertConsoleLogPipelineContributors(IServiceProvider serviceProvider) @@ -141,22 +288,131 @@ public class ConsoleLogsRegistrationTests : IAsyncLifetime Assert.Contains(serviceProvider.GetServices(), x => x.GetType() == typeof(ConsoleLogActivityExecutionPipelineContributor)); } - private sealed class CustomProvider : IConsoleLogProvider + private static async Task AssertEventuallyAsync(Func assertion) { - public ValueTask PublishAsync(ConsoleLogStreaming.Core.Models.ConsoleLogLine line, CancellationToken cancellationToken = default) => ValueTask.CompletedTask; + var deadline = DateTimeOffset.UtcNow.AddSeconds(3); + Exception? lastException = null; - public ValueTask GetRecentAsync(ConsoleLogStreaming.Core.Models.ConsoleLogFilter filter, CancellationToken cancellationToken = default) => - ValueTask.FromResult(new ConsoleLogStreaming.Core.Models.RecentConsoleLogsResult()); - - public async IAsyncEnumerable SubscribeAsync( - ConsoleLogStreaming.Core.Models.ConsoleLogFilter filter, - [EnumeratorCancellation] CancellationToken cancellationToken = default) + while (DateTimeOffset.UtcNow < deadline) { - await Task.CompletedTask; - yield break; + try + { + await assertion(); + return; + } + catch (Xunit.Sdk.XunitException e) + { + lastException = e; + await Task.Delay(25); + } } - public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) => - ValueTask.FromResult>([]); + if (lastException != null) + throw lastException; + } + + private static ConsoleLogLine CreateLine(string workflowInstanceId, string text) => new() + { + Text = text, + Source = new ConsoleLogSource { Id = "test-source" }, + Metadata = new Dictionary + { + [ConsoleLogMetadataKeys.WorkflowInstanceId] = workflowInstanceId + } + }; + + private sealed class RecordingConsoleLogProvider : IConsoleLogProvider + { + public ConsoleLogLine? PublishedLine { get; private set; } + + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + PublishedLine = line; + return ValueTask.CompletedTask; + } + + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(new RecentConsoleLogsResult()); + } + + public IAsyncEnumerable SubscribeAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return AsyncEnumerable.Empty(); + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return ValueTask.FromResult>([]); + } + } + + private sealed class MetadataIgnoringConsoleLogProvider : IConsoleLogProvider + { + public List RecentItems { get; } = []; + public List LiveItems { get; } = []; + + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + RecentItems.Add(line); + return ValueTask.CompletedTask; + } + + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(new RecentConsoleLogsResult { Items = RecentItems }); + } + + public async IAsyncEnumerable SubscribeAsync( + ConsoleLogFilter filter, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + foreach (var line in LiveItems) + { + cancellationToken.ThrowIfCancellationRequested(); + yield return ConsoleLogStreamingItem.FromLine(line); + await Task.Yield(); + } + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return ValueTask.FromResult>([]); + } + } + + private sealed class MetadataDroppingConsoleLogProvider : IConsoleLogProvider + { + public List PublishedLines { get; } = []; + + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + PublishedLines.Add(line with { Metadata = new Dictionary() }); + return ValueTask.CompletedTask; + } + + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(new RecentConsoleLogsResult { Items = PublishedLines }); + } + + public IAsyncEnumerable SubscribeAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return AsyncEnumerable.Empty(); + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return ValueTask.FromResult>([]); + } + } + + private sealed class NoopDrainExtensionHandle : IDrainExtensionHandle + { + public bool TryExtend(TimeSpan requestedExtension, out TimeSpan grantedExtension) + { + grantedExtension = TimeSpan.Zero; + return false; + } } } diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Elsa.Diagnostics.ConsoleLogs.UnitTests.csproj b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Elsa.Diagnostics.ConsoleLogs.UnitTests.csproj index 17fe4f464..b21be7aa8 100644 --- a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Elsa.Diagnostics.ConsoleLogs.UnitTests.csproj +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Elsa.Diagnostics.ConsoleLogs.UnitTests.csproj @@ -6,6 +6,7 @@ + diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs new file mode 100644 index 000000000..2558ca593 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs @@ -0,0 +1,156 @@ +using ConsoleLogStreaming.Core; +using ConsoleLogStreaming.Core.Models; +using Elsa.Diagnostics.ConsoleLogs.RealTime; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Elsa.Diagnostics.ConsoleLogs.UnitTests; + +public class ElsaConsoleLogSubscriptionManagerTests +{ + [Fact] + public async Task SubscribeAsync_DoesNotSendSourceChangedForRepeatedSource() + { + var source = new ConsoleLogSource + { + Id = "source-1", + DisplayName = "Source 1", + ServiceName = "service", + MachineName = "machine", + Health = ConsoleLogSourceHealth.Connected + }; + var provider = new StreamingConsoleLogProvider( + ConsoleLogStreamingItem.FromLine(CreateLine(source, "first")), + ConsoleLogStreamingItem.FromLine(CreateLine(source, "second"))); + var client = new RecordingConsoleLogsClient(); + var hubContext = new TestHubContext(client); + using var manager = new ElsaConsoleLogSubscriptionManager(provider, hubContext, NullLogger.Instance); + + await manager.SubscribeAsync("connection-1", new(), CancellationToken.None); + + await AssertEventuallyAsync(() => + { + Assert.Equal(2, client.Lines.Count); + Assert.Single(client.Sources); + }); + } + + private static ConsoleLogLine CreateLine(ConsoleLogSource source, string text) => new() + { + Text = text, + Source = source + }; + + private static async Task AssertEventuallyAsync(Action assertion) + { + Xunit.Sdk.XunitException? lastException = null; + + for (var i = 0; i < 40; i++) + { + try + { + assertion(); + return; + } + catch (Xunit.Sdk.XunitException e) + { + lastException = e; + await Task.Delay(25); + } + } + + if (lastException != null) + throw lastException; + } + + private sealed class StreamingConsoleLogProvider(params ConsoleLogStreamingItem[] items) : IConsoleLogProvider + { + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + return ValueTask.CompletedTask; + } + + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(new RecentConsoleLogsResult()); + } + + public async IAsyncEnumerable SubscribeAsync(ConsoleLogFilter filter, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + foreach (var item in items) + { + cancellationToken.ThrowIfCancellationRequested(); + yield return item; + await Task.Yield(); + } + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return ValueTask.FromResult>([]); + } + } + + private sealed class RecordingConsoleLogsClient : IElsaConsoleLogsClient + { + public List Lines { get; } = []; + public List Sources { get; } = []; + + public Task ReceiveConsoleLogLineAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + Lines.Add(line); + return Task.CompletedTask; + } + + public Task ReceiveDroppedLinesAsync(ConsoleLogDroppedSummary summary, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + + public Task ReceiveSourceChangedAsync(ConsoleLogSource source, CancellationToken cancellationToken = default) + { + Sources.Add(source); + return Task.CompletedTask; + } + } + + private sealed class TestHubContext(IElsaConsoleLogsClient client) : IHubContext + { + public IHubClients Clients { get; } = new TestHubClients(client); + public IGroupManager Groups { get; } = new TestGroupManager(); + } + + private sealed class TestHubClients(IElsaConsoleLogsClient client) : IHubClients + { + public IElsaConsoleLogsClient All => client; + + public IElsaConsoleLogsClient AllExcept(IReadOnlyList excludedConnectionIds) => client; + + public IElsaConsoleLogsClient Client(string connectionId) => client; + + public IElsaConsoleLogsClient Clients(IReadOnlyList connectionIds) => client; + + public IElsaConsoleLogsClient Group(string groupName) => client; + + public IElsaConsoleLogsClient GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => client; + + public IElsaConsoleLogsClient Groups(IReadOnlyList groupNames) => client; + + public IElsaConsoleLogsClient User(string userId) => client; + + public IElsaConsoleLogsClient Users(IReadOnlyList userIds) => client; + } + + private sealed class TestGroupManager : IGroupManager + { + public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + + public Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + } +} diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/RecentConsoleLogsEndpointTests.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/RecentConsoleLogsEndpointTests.cs new file mode 100644 index 000000000..064c9f793 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/RecentConsoleLogsEndpointTests.cs @@ -0,0 +1,16 @@ +using System.Text; +using System.Text.Json; +using Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Recent; + +namespace Elsa.Diagnostics.ConsoleLogs.UnitTests; + +public class RecentConsoleLogsEndpointTests +{ + [Fact] + public async Task DeserializeJsonBodyAsync_WhenJsonIsMalformed_ThrowsJsonException() + { + await using var body = new MemoryStream(Encoding.UTF8.GetBytes("{")); + + await Assert.ThrowsAsync(async () => await Endpoint.DeserializeJsonBodyAsync(body, CancellationToken.None)); + } +} diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Usings.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Usings.cs index fd1941521..8457b59a5 100644 --- a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Usings.cs +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Usings.cs @@ -1,4 +1,4 @@ global using System.Runtime.CompilerServices; -global using ConsoleLogStreaming.Contracts; +global using ConsoleLogStreaming.Core.Models; global using Microsoft.Extensions.Options; global using Xunit; diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj new file mode 100644 index 000000000..4c9e11f6b --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj @@ -0,0 +1,12 @@ + + + + [Elsa.Diagnostics.OpenTelemetry]* + 0 + + + + + + + diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/InMemory/RingBufferTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/InMemory/RingBufferTests.cs new file mode 100644 index 000000000..3ec14fc7a --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/InMemory/RingBufferTests.cs @@ -0,0 +1,20 @@ +using Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.InMemory; + +public class RingBufferTests +{ + [Fact] + public void Add_WhenCapacityIsExceeded_DropsOldestItems() + { + var buffer = new RingBuffer(3); + + buffer.Add(1); + buffer.Add(2); + buffer.Add(3); + buffer.Add(4); + + Assert.Equal([2, 3, 4], buffer.Snapshot()); + Assert.Equal(1, buffer.DroppedCount); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpHttpProtobufParserTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpHttpProtobufParserTests.cs new file mode 100644 index 000000000..1d796473f --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpHttpProtobufParserTests.cs @@ -0,0 +1,142 @@ +using System.Buffers.Binary; +using System.Text; +using Elsa.Diagnostics.OpenTelemetry.Ingestion.HttpProtobuf; +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Ingestion; + +public class OtlpHttpProtobufParserTests +{ + private static readonly byte[] TraceId = Convert.FromHexString("00112233445566778899aabbccddeeff"); + private static readonly byte[] SpanId = Convert.FromHexString("0011223344556677"); + private static readonly DateTimeOffset Timestamp = new(2026, 5, 26, 10, 0, 0, TimeSpan.Zero); + + [Fact(DisplayName = "OTLP trace payload is normalized to trace, span, resource, and workflow metadata")] + public void ParseTraces() + { + var payload = Message(1, + Join(Message(1, Resource()), + Message(2, Message(2, + Join(Bytes(1, TraceId), + Bytes(2, SpanId), + String(5, "Workflow/Approve"), + Varint(6, 1), + Varint(7, UnixNanos(Timestamp)), + Varint(8, UnixNanos(Timestamp.AddMilliseconds(25))), + Message(9, KeyValue("workflow.instance.id", "wf-1")), + Message(15, Varint(3, 2))))))); + + var batch = OtlpHttpProtobufParser.ParseTraces(payload); + var span = Assert.Single(batch.Spans); + var trace = Assert.Single(batch.Traces); + + Assert.Equal("elsa-server:node-1", span.ResourceId); + Assert.Equal("00112233445566778899aabbccddeeff", trace.TraceId); + Assert.Equal("0011223344556677", trace.RootSpanId); + Assert.Equal("wf-1", Assert.Single(trace.WorkflowInstanceIds)); + Assert.Equal(SpanStatus.Error, trace.Status); + } + + [Fact(DisplayName = "OTLP metric payload is normalized to metric instruments and points")] + public void ParseMetrics() + { + var point = + Join(Varint(3, UnixNanos(Timestamp)), + Fixed64(4, 42.5), + Message(7, KeyValue("workflow.definition.id", "orders"))); + var metric = + Join(String(1, "workflow.duration"), + String(2, "Workflow duration"), + String(3, "ms"), + Message(5, Message(1, point))); + var payload = Message(1, Join(Message(1, Resource()), Message(2, Message(2, metric)))); + + var batch = OtlpHttpProtobufParser.ParseMetrics(payload); + var instrument = Assert.Single(batch.Instruments); + var metricPoint = Assert.Single(batch.MetricPoints); + + Assert.Equal("workflow.duration", instrument.Name); + Assert.Equal("workflow.duration", metricPoint.InstrumentName); + Assert.Equal(MetricKind.Gauge, instrument.Kind); + Assert.Equal(42.5, metricPoint.Value); + Assert.Equal("orders", metricPoint.Attributes["workflow.definition.id"]); + } + + [Fact(DisplayName = "OTLP log payload is normalized to correlated OTLP log records")] + public void ParseLogs() + { + var log = + Join(Varint(1, UnixNanos(Timestamp)), + Varint(2, 17), + String(3, "Error"), + Message(5, AnyString("boom")), + Bytes(9, TraceId), + Bytes(10, SpanId), + Message(6, KeyValue("workflow.instance.id", "wf-1"))); + var payload = Message(1, Join(Message(1, Resource()), Message(2, Message(2, log)))); + + var batch = OtlpHttpProtobufParser.ParseLogs(payload); + var record = Assert.Single(batch.Logs); + + Assert.Equal("elsa-server:node-1", record.ResourceId); + Assert.Equal("Error", record.SeverityText); + Assert.Equal("boom", record.Body); + Assert.Equal("00112233445566778899aabbccddeeff", record.TraceId); + Assert.Equal("0011223344556677", record.SpanId); + } + + private static byte[] Resource() + { + return Join( + Message(1, KeyValue("service.name", "elsa-server")), + Message(1, KeyValue("service.instance.id", "node-1")), + Message(1, KeyValue("telemetry.sdk.language", "dotnet"))); + } + + private static byte[] KeyValue(string key, string value) => Join(String(1, key), Message(2, AnyString(value))); + + private static byte[] AnyString(string value) => String(1, value); + + private static byte[] Message(int fieldNumber, byte[] value) => Join(Varint((ulong)((fieldNumber << 3) | 2)), Varint((ulong)value.Length), value); + + private static byte[] String(int fieldNumber, string value) => Message(fieldNumber, Encoding.UTF8.GetBytes(value)); + + private static byte[] Bytes(int fieldNumber, byte[] value) => Message(fieldNumber, value); + + private static byte[] Varint(int fieldNumber, ulong value) => Join(Varint((ulong)(fieldNumber << 3)), Varint(value)); + + private static byte[] Fixed64(int fieldNumber, double value) + { + var bytes = new byte[9]; + bytes[0] = (byte)((fieldNumber << 3) | 1); + BinaryPrimitives.WriteUInt64LittleEndian(bytes.AsSpan(1), (ulong)BitConverter.DoubleToInt64Bits(value)); + return bytes; + } + + private static byte[] Varint(ulong value) + { + var bytes = new List(); + while (value >= 0x80) + { + bytes.Add((byte)(value | 0x80)); + value >>= 7; + } + bytes.Add((byte)value); + return bytes.ToArray(); + } + + private static ulong UnixNanos(DateTimeOffset timestamp) => (ulong)(timestamp - DateTimeOffset.UnixEpoch).Ticks * 100; + + private static byte[] Join(params byte[][] segments) + { + var result = new byte[segments.Sum(x => x.Length)]; + var offset = 0; + foreach (var segment in segments) + { + segment.CopyTo(result, offset); + offset += segment.Length; + } + + return result; + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpIngestionSecurityTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpIngestionSecurityTests.cs new file mode 100644 index 000000000..4ebee00f4 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Ingestion/OtlpIngestionSecurityTests.cs @@ -0,0 +1,68 @@ +using System.Net; +using Elsa.Diagnostics.OpenTelemetry.Ingestion; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Microsoft.AspNetCore.Http; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Ingestion; + +public class OtlpIngestionSecurityTests +{ + [Fact(DisplayName = "Loopback ingestion is allowed without API key in development mode")] + public void AllowsLoopbackWithoutApiKey() + { + var context = CreateContext(IPAddress.Loopback); + + var authorized = OtlpIngestionSecurity.IsAuthorized(context, new OpenTelemetryDiagnosticsOptions()); + + Assert.True(authorized); + } + + [Fact(DisplayName = "Non-loopback ingestion is rejected without API key")] + public void RejectsNonLoopbackWithoutApiKey() + { + var context = CreateContext(IPAddress.Parse("10.0.0.5")); + + var authorized = OtlpIngestionSecurity.IsAuthorized(context, new OpenTelemetryDiagnosticsOptions()); + + Assert.False(authorized); + } + + [Fact(DisplayName = "Missing remote address is rejected without API key")] + public void RejectsMissingRemoteAddressWithoutApiKey() + { + var context = CreateContext(null); + + var authorized = OtlpIngestionSecurity.IsAuthorized(context, new OpenTelemetryDiagnosticsOptions()); + + Assert.False(authorized); + } + + [Fact(DisplayName = "Configured API key header authorizes ingestion")] + public void AllowsConfiguredApiKey() + { + var context = CreateContext(IPAddress.Parse("10.0.0.5")); + context.Request.Headers["x-otlp-api-key"] = "secret"; + + var authorized = OtlpIngestionSecurity.IsAuthorized(context, new OpenTelemetryDiagnosticsOptions { ApiKey = "secret" }); + + Assert.True(authorized); + } + + [Fact(DisplayName = "Incorrect API key header rejects ingestion")] + public void RejectsIncorrectConfiguredApiKey() + { + var context = CreateContext(IPAddress.Parse("10.0.0.5")); + context.Request.Headers["x-otlp-api-key"] = "not-secret"; + + var authorized = OtlpIngestionSecurity.IsAuthorized(context, new OpenTelemetryDiagnosticsOptions { ApiKey = "secret" }); + + Assert.False(authorized); + } + + private static DefaultHttpContext CreateContext(IPAddress? remoteAddress) + { + var context = new DefaultHttpContext(); + context.Connection.RemoteIpAddress = remoteAddress; + return context; + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/InMemoryOpenTelemetryStoreTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/InMemoryOpenTelemetryStoreTests.cs new file mode 100644 index 000000000..52087d27a --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/InMemoryOpenTelemetryStoreTests.cs @@ -0,0 +1,110 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Providers; + +public class InMemoryOpenTelemetryStoreTests +{ + [Fact] + public async Task WriteAsync_WhenTraceCapacityIsExceeded_DropsOldestTraceAndReportsCount() + { + var context = new OpenTelemetryStoreTestContext(new OpenTelemetryDiagnosticsOptions + { + TraceCapacity = 2, + SpanCapacity = 10, + MetricPointCapacity = 10, + LogRecordCapacity = 10 + }); + var resource = context.Resource("resource-a", "api"); + + await context.WriteAsync(new OpenTelemetryBatch([resource], [context.Trace("trace-1", resource.Id, context.Now.AddSeconds(1))], [], [], [], [])); + await context.WriteAsync(new OpenTelemetryBatch([], [context.Trace("trace-2", resource.Id, context.Now.AddSeconds(2))], [], [], [], [])); + await context.WriteAsync(new OpenTelemetryBatch([], [context.Trace("trace-3", resource.Id, context.Now.AddSeconds(3))], [], [], [], [])); + + var result = await context.Store.QueryTracesAsync(new OpenTelemetryTraceFilter { Take = 10 }); + var diagnostics = await context.Store.GetDiagnosticsAsync(); + + Assert.Equal(["trace-2", "trace-3"], result.Items.Select(x => x.TraceId)); + Assert.Equal(1, result.DroppedCount); + Assert.Equal(1, diagnostics.DroppedTraceCount); + Assert.Equal(2, diagnostics.TraceCount); + } + + [Fact] + public async Task QueryResourcesAsync_WhenTakeExceedsMaxQuerySize_ClampsResult() + { + var context = new OpenTelemetryStoreTestContext(new OpenTelemetryDiagnosticsOptions { MaxQuerySize = 1 }); + + await context.WriteAsync(new OpenTelemetryBatch([context.Resource("resource-a", "api"), context.Resource("resource-b", "worker")], [], [], [], [], [])); + + var result = await context.Store.QueryResourcesAsync(new OpenTelemetryResourceFilter { Take = 10 }); + + Assert.Single(result.Items); + } + + [Fact] + public async Task QueryTracesAsync_WhenTraceIdAppearsInMultipleBatches_ReturnsLatestTrace() + { + var context = new OpenTelemetryStoreTestContext(new OpenTelemetryDiagnosticsOptions { TraceCapacity = 10 }); + var resource = context.Resource("resource-a", "api"); + + await context.WriteAsync(new OpenTelemetryBatch([resource], [context.Trace("trace-1", resource.Id, context.Now.AddSeconds(1))], [], [], [], [])); + await context.WriteAsync(new OpenTelemetryBatch([], [context.Trace("trace-1", resource.Id, context.Now.AddSeconds(2))], [], [], [], [])); + + var result = await context.Store.QueryTracesAsync(new OpenTelemetryTraceFilter { Take = 10 }); + + var trace = Assert.Single(result.Items); + Assert.Equal(context.Now.AddSeconds(2), trace.StartTime); + } + + [Fact] + public async Task WriteAsync_WhenResourceCapacityIsExceeded_DropsOldestResource() + { + var context = new OpenTelemetryStoreTestContext(new OpenTelemetryDiagnosticsOptions { ResourceCapacity = 2 }); + + await context.WriteAsync(new OpenTelemetryBatch( + [ + context.Resource("resource-a", "api", context.Now.AddSeconds(1)), + context.Resource("resource-b", "worker", context.Now.AddSeconds(2)), + context.Resource("resource-c", "jobs", context.Now.AddSeconds(3)) + ], + [], [], [], [], [])); + + var result = await context.Store.QueryResourcesAsync(new OpenTelemetryResourceFilter { Take = 10 }); + + Assert.Equal(["resource-c", "resource-b"], result.Items.Select(x => x.Id)); + Assert.Equal(1, result.DroppedCount); + } + + [Fact] + public async Task Constructor_WhenCapacitiesAreMisconfigured_ClampsToMinimumCapacity() + { + var context = new OpenTelemetryStoreTestContext(new OpenTelemetryDiagnosticsOptions + { + TraceCapacity = 0, + SpanCapacity = 0, + MetricPointCapacity = 0, + LogRecordCapacity = 0 + }); + var resource = context.Resource("resource-a", "api"); + + await context.WriteAsync(new OpenTelemetryBatch( + [resource], + [context.Trace("trace-1", resource.Id)], + [context.Span("span-1", "trace-1", "span-1", resource.Id)], + [context.Instrument("instrument-1", resource.Id, "metric")], + [context.Point("point-1", "instrument-1", resource.Id)], + [context.Log("log-1", resource.Id, "trace-1")])); + + var diagnostics = await context.Store.GetDiagnosticsAsync(); + + Assert.Equal(1, diagnostics.TraceCount); + Assert.Equal(1, diagnostics.SpanCount); + Assert.Equal(1, diagnostics.MetricPointCount); + Assert.Equal(1, diagnostics.LogRecordCount); + Assert.Equal(1, diagnostics.TraceCapacity); + Assert.Equal(1, diagnostics.SpanCapacity); + Assert.Equal(1, diagnostics.MetricPointCapacity); + Assert.Equal(1, diagnostics.LogRecordCapacity); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryMetricQueryTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryMetricQueryTests.cs new file mode 100644 index 000000000..2787c6978 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryMetricQueryTests.cs @@ -0,0 +1,45 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Providers; + +public class OpenTelemetryMetricQueryTests +{ + [Fact] + public async Task QueryMetricsAsync_WhenFilteringByInstrumentName_ReturnsMatchingInstrumentPoints() + { + var context = new OpenTelemetryStoreTestContext(); + var resource = context.Resource("resource-api", "api"); + var duration = context.Instrument("instrument-duration", resource.Id, "workflow.duration"); + var count = context.Instrument("instrument-count", resource.Id, "workflow.count"); + await context.WriteAsync(new OpenTelemetryBatch([resource], [], [], [duration, count], [context.Point("point-1", duration.Id, resource.Id), context.Point("point-2", count.Id, resource.Id)], [])); + + var result = await context.Store.QueryMetricsAsync(new OpenTelemetryMetricFilter { InstrumentName = "duration" }); + + Assert.Equal(duration.Id, Assert.Single(result.Instruments).Id); + Assert.Equal("point-1", Assert.Single(result.Points).Id); + } + + [Fact] + public async Task QueryMetricsAsync_WhenFilteringByInstrumentName_AppliesInstrumentFilterBeforeTake() + { + var context = new OpenTelemetryStoreTestContext(); + var resource = context.Resource("resource-api", "api"); + var duration = context.Instrument("instrument-duration", resource.Id, "workflow.duration"); + var count = context.Instrument("instrument-count", resource.Id, "workflow.count"); + await context.WriteAsync(new OpenTelemetryBatch( + [resource], + [], + [], + [duration, count], + [ + context.Point("point-1", duration.Id, resource.Id, context.Now), + context.Point("point-2", count.Id, resource.Id, context.Now.AddSeconds(1)) + ], + [])); + + var result = await context.Store.QueryMetricsAsync(new OpenTelemetryMetricFilter { InstrumentName = "duration", Take = 1 }); + + Assert.Equal(duration.Id, Assert.Single(result.Instruments).Id); + Assert.Equal("point-1", Assert.Single(result.Points).Id); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryStoreTestContext.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryStoreTestContext.cs new file mode 100644 index 000000000..998bf2595 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryStoreTestContext.cs @@ -0,0 +1,59 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Providers.InMemory; +using Elsa.Diagnostics.OpenTelemetry.Services; +using OptionsFactory = Microsoft.Extensions.Options.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Providers; + +public class OpenTelemetryStoreTestContext +{ + public OpenTelemetryStoreTestContext(OpenTelemetryDiagnosticsOptions? options = null) + { + Options = options ?? new OpenTelemetryDiagnosticsOptions(); + SourceRegistry = new OpenTelemetrySourceRegistry(OptionsFactory.Create(Options)); + Store = new InMemoryOpenTelemetryStore(OptionsFactory.Create(Options), SourceRegistry); + } + + public OpenTelemetryDiagnosticsOptions Options { get; } + public OpenTelemetrySourceRegistry SourceRegistry { get; } + public InMemoryOpenTelemetryStore Store { get; } + public DateTimeOffset Now { get; } = new(2026, 5, 26, 10, 0, 0, TimeSpan.Zero); + + public async Task WriteAsync(OpenTelemetryBatch batch) + { + await Store.WriteAsync(batch); + } + + public TelemetryResource Resource(string id, string serviceName, DateTimeOffset? lastSeen = null, TelemetryResourceStatus status = TelemetryResourceStatus.Active) + { + return new(id, serviceName, $"{id}-instance", "dotnet", new Dictionary(), lastSeen ?? Now, status); + } + + public TelemetryTrace Trace(string traceId, string resourceId, DateTimeOffset? startTime = null, SpanStatus status = SpanStatus.Ok, params string[] workflowInstanceIds) + { + var start = startTime ?? Now; + return new(traceId, $"{traceId}-root", $"trace-{traceId}", start, start.AddMilliseconds(25), TimeSpan.FromMilliseconds(25), status, [resourceId], workflowInstanceIds, 2); + } + + public TelemetrySpan Span(string id, string traceId, string spanId, string resourceId, DateTimeOffset? startTime = null) + { + var start = startTime ?? Now; + return new(id, traceId, spanId, null, resourceId, $"span-{spanId}", "internal", start, start.AddMilliseconds(10), SpanStatus.Ok, null, new Dictionary(), [], []); + } + + public MetricInstrument Instrument(string id, string resourceId, string name) + { + return new(id, resourceId, name, "ms", null, MetricKind.Gauge, new Dictionary()); + } + + public MetricPoint Point(string id, string instrumentId, string resourceId, DateTimeOffset? timestamp = null) + { + return new(id, instrumentId, instrumentId, resourceId, timestamp ?? Now, 42, null, null, new Dictionary(), null, null); + } + + public OtlpLogRecord Log(string id, string resourceId, string traceId, string severity = "Information", string body = "message") + { + return new(id, resourceId, Now, severity, null, body, traceId, $"{traceId}-span", new Dictionary()); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryTraceQueryTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryTraceQueryTests.cs new file mode 100644 index 000000000..ac2154d66 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OpenTelemetryTraceQueryTests.cs @@ -0,0 +1,38 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Providers; + +public class OpenTelemetryTraceQueryTests +{ + [Fact] + public async Task QueryTracesAsync_WhenFilteringByServiceName_ReturnsMatchingResourceTraces() + { + var context = new OpenTelemetryStoreTestContext(); + var api = context.Resource("resource-api", "api"); + var worker = context.Resource("resource-worker", "worker"); + await context.WriteAsync(new OpenTelemetryBatch([api, worker], [context.Trace("trace-api", api.Id), context.Trace("trace-worker", worker.Id)], [], [], [], [])); + + var result = await context.Store.QueryTracesAsync(new OpenTelemetryTraceFilter { ServiceName = "api" }); + + Assert.Equal("trace-api", Assert.Single(result.Items).TraceId); + } + + [Fact] + public async Task GetTraceAsync_ReturnsOrderedSpansResourcesAndTraceLogs() + { + var context = new OpenTelemetryStoreTestContext(); + var resource = context.Resource("resource-api", "api"); + var trace = context.Trace("trace-1", resource.Id); + var laterSpan = context.Span("span-record-2", trace.TraceId, "span-2", resource.Id, context.Now.AddSeconds(2)); + var earlierSpan = context.Span("span-record-1", trace.TraceId, "span-1", resource.Id, context.Now.AddSeconds(1)); + var log = context.Log("log-1", resource.Id, trace.TraceId); + await context.WriteAsync(new OpenTelemetryBatch([resource], [trace], [laterSpan, earlierSpan], [], [], [log])); + + var detail = await context.Store.GetTraceAsync(trace.TraceId); + + Assert.NotNull(detail); + Assert.Equal(["span-1", "span-2"], detail.Spans.Select(x => x.SpanId)); + Assert.Equal(resource.Id, Assert.Single(detail.Resources).Id); + Assert.Equal(log.Id, Assert.Single(detail.Logs).Id); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OtlpLogQueryTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OtlpLogQueryTests.cs new file mode 100644 index 000000000..1328b85ab --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Providers/OtlpLogQueryTests.cs @@ -0,0 +1,28 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Providers; + +public class OtlpLogQueryTests +{ + [Fact] + public async Task QueryLogsAsync_WhenFilteringByTraceAndSeverity_ReturnsMatchingLogs() + { + var context = new OpenTelemetryStoreTestContext(); + var resource = context.Resource("resource-api", "api"); + await context.WriteAsync(new OpenTelemetryBatch( + [resource], + [], + [], + [], + [], + [ + context.Log("log-1", resource.Id, "trace-1", "Information"), + context.Log("log-2", resource.Id, "trace-1", "Error"), + context.Log("log-3", resource.Id, "trace-2", "Error") + ])); + + var result = await context.Store.QueryLogsAsync(new OpenTelemetryLogFilter { TraceId = "trace-1", Severity = "Error" }); + + Assert.Equal("log-2", Assert.Single(result.Items).Id); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/CollectorConfigurationTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/CollectorConfigurationTests.cs new file mode 100644 index 000000000..2d171a761 --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/CollectorConfigurationTests.cs @@ -0,0 +1,41 @@ +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Services; +using OptionsFactory = Microsoft.Extensions.Options.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Services; + +public class CollectorConfigurationTests +{ + [Fact] + public async Task GetAsync_WhenGrpcIsDisabled_ReturnsDisabledGrpcMetadataWithoutSecretValue() + { + var provider = new CollectorConfigurationProvider(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions + { + ApiKey = "secret-value", + EnableGrpc = false + })); + + var configuration = await provider.GetAsync(); + + Assert.True(configuration.Http.Enabled); + Assert.False(configuration.Grpc.Enabled); + Assert.Null(configuration.Grpc.Endpoint); + Assert.Equal("", configuration.RequiredHeaders["x-otlp-api-key"]); + } + + [Fact] + public async Task GetAsync_WhenGrpcIsEnabled_ReturnsConfiguredGrpcEndpoint() + { + var provider = new CollectorConfigurationProvider(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions + { + EnableGrpc = true, + GrpcEndpointPath = "https://localhost:4317" + })); + + var configuration = await provider.GetAsync(); + + Assert.True(configuration.Grpc.Enabled); + Assert.Equal("https://localhost:4317", configuration.Grpc.Endpoint); + Assert.Null(configuration.Grpc.DisabledReason); + } +} diff --git a/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/OpenTelemetryRedactorTests.cs b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/OpenTelemetryRedactorTests.cs new file mode 100644 index 000000000..b100324dd --- /dev/null +++ b/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Services/OpenTelemetryRedactorTests.cs @@ -0,0 +1,39 @@ +using Elsa.Diagnostics.OpenTelemetry.Models; +using Elsa.Diagnostics.OpenTelemetry.Options; +using Elsa.Diagnostics.OpenTelemetry.Services; +using OptionsFactory = Microsoft.Extensions.Options.Options; + +namespace Elsa.Diagnostics.OpenTelemetry.UnitTests.Services; + +public class OpenTelemetryRedactorTests +{ + [Fact] + public void Redact_WhenSensitiveAttributeNameExists_RedactsValue() + { + var redactor = new OpenTelemetryRedactor(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions())); + var log = new OtlpLogRecord("1", "resource", DateTimeOffset.UtcNow, "Information", null, "hello", null, null, new Dictionary { ["password"] = "secret" }); + var batch = new OpenTelemetryBatch([], [], [], [], [], [log]); + + var result = redactor.Redact(batch); + + Assert.Equal("[Redacted]", result.Logs.Single().Attributes["password"]); + } + + [Fact] + public void Redact_WhenAttributeKeysDifferOnlyByCase_UsesLastValue() + { + var redactor = new OpenTelemetryRedactor(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions())); + var log = new OtlpLogRecord("1", "resource", DateTimeOffset.UtcNow, "Information", null, "hello", null, null, new Dictionary + { + ["Password"] = "first", + ["password"] = "second" + }); + var batch = new OpenTelemetryBatch([], [], [], [], [], [log]); + + var result = redactor.Redact(batch); + + var attributes = result.Logs.Single().Attributes; + Assert.Single(attributes); + Assert.Equal("[Redacted]", attributes["Password"]); + } +} diff --git a/test/unit/Elsa.Http.UnitTests/ShellFeatures/HttpFeatureTests.cs b/test/unit/Elsa.Http.UnitTests/ShellFeatures/HttpFeatureTests.cs deleted file mode 100644 index 2774848a7..000000000 --- a/test/unit/Elsa.Http.UnitTests/ShellFeatures/HttpFeatureTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Elsa.Expressions.Options; -using Elsa.Expressions.Services; -using Elsa.Http.Bookmarks; -using Elsa.Http.ShellFeatures; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Elsa.Http.UnitTests.ShellFeatures; - -public class HttpFeatureTests -{ - [Fact] - public void ConfigureServices_RegistersHttpTypeAliases() - { - var services = new ServiceCollection(); - var feature = new HttpFeature(); - - feature.ConfigureServices(services); - - using var serviceProvider = services.BuildServiceProvider(); - var expressionOptions = serviceProvider.GetRequiredService>(); - var registry = new WellKnownTypeRegistry(expressionOptions); - - Assert.True(registry.TryGetType(nameof(HttpEndpointBookmarkPayload), out var type)); - Assert.Equal(typeof(HttpEndpointBookmarkPayload), type); - Assert.True(registry.TryGetType(nameof(HttpRequestException), out var exceptionType)); - Assert.Equal(typeof(HttpRequestException), exceptionType); - } -} diff --git a/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs b/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs new file mode 100644 index 000000000..b831000e5 --- /dev/null +++ b/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs @@ -0,0 +1,108 @@ +using Elsa.Mediator.Channels; +using Elsa.Mediator.CommandStrategies; +using Elsa.Mediator.Contexts; +using Elsa.Mediator.Contracts; +using Elsa.Mediator.Middleware.Command; +using Elsa.Mediator.Models; +using Elsa.Mediator.Options; +using Elsa.Mediator.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Elsa.Mediator.UnitTests; + +public class BackgroundCommandProcessorTests +{ + [Fact] + public async Task ExecuteAsync_UsesQueuedContextStrategyAndCancellationToken() + { + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddScoped(); + await using var serviceProvider = services.BuildServiceProvider(); + var channel = new CommandsChannel(); + var processor = new BackgroundCommandProcessor( + Microsoft.Extensions.Options.Options.Create(new MediatorOptions { CommandWorkerCount = 1 }), + channel, + serviceProvider.GetRequiredService(), + NullLogger.Instance); + using var processorCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + using var commandCancellationTokenSource = new CancellationTokenSource(); + var runTask = processor.ExecuteAsync(processorCancellationTokenSource.Token); + var strategy = new TestCommandStrategy(); + var context = new CommandContext(new TestCommand(), strategy, typeof(Unit), new Dictionary(), serviceProvider, commandCancellationTokenSource.Token); + + await commandCancellationTokenSource.CancelAsync(); + await channel.Writer.WriteAsync(context, processorCancellationTokenSource.Token); + + var recorder = serviceProvider.GetRequiredService(); + var recordedCall = await recorder.WaitForCallAsync(processorCancellationTokenSource.Token); + await processorCancellationTokenSource.CancelAsync(); + await runTask; + + Assert.Same(strategy, recordedCall.Strategy); + Assert.True(recordedCall.CancellationToken.IsCancellationRequested); + } + + [Fact] + public async Task BackgroundStrategy_QueuesExecutableContext() + { + var services = new ServiceCollection(); + services.AddSingleton(); + await using var serviceProvider = services.BuildServiceProvider(); + var channel = serviceProvider.GetRequiredService(); + var commandContext = new CommandContext(new TestCommand(), CommandStrategy.Background, typeof(Unit), new Dictionary(), serviceProvider, CancellationToken.None); + var strategyContext = new CommandStrategyContext(commandContext, new TestCommandHandler(), serviceProvider); + + await CommandStrategy.Background.ExecuteAsync(strategyContext); + + var queuedContext = await channel.Reader.ReadAsync(); + + Assert.Same(CommandStrategy.Default, queuedContext.CommandStrategy); + Assert.Same(commandContext.Command, queuedContext.Command); + Assert.Same(commandContext.Headers, queuedContext.Headers); + } + + private sealed class RecordingCommandSender(CommandSenderRecorder recorder) : ICommandSender + { + public Task SendAsync(ICommand command, CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task SendAsync(ICommand command, IDictionary headers, CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task SendAsync(ICommand command, ICommandStrategy? strategy, CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task SendAsync(ICommand command, ICommandStrategy? strategy, IDictionary headers, CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task SendAsync(ICommand command, CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task SendAsync(ICommand command, ICommandStrategy? strategy, CancellationToken cancellationToken = default) => throw new NotSupportedException(); + + public Task SendAsync(ICommand command, ICommandStrategy? strategy, IDictionary headers, CancellationToken cancellationToken = default) + { + recorder.Record(new(strategy, cancellationToken)); + return Task.CompletedTask; + } + } + + private sealed class CommandSenderRecorder + { + private readonly TaskCompletionSource _completed = new(TaskCreationOptions.RunContinuationsAsynchronously); + + public void Record(RecordedCommandCall call) => _completed.TrySetResult(call); + + public Task WaitForCallAsync(CancellationToken cancellationToken) => _completed.Task.WaitAsync(cancellationToken); + } + + private sealed record RecordedCommandCall(ICommandStrategy? Strategy, CancellationToken CancellationToken); + + private sealed record TestCommand : ICommand; + + private sealed class TestCommandHandler : ICommandHandler + { + public Task HandleAsync(TestCommand command, CancellationToken cancellationToken) => Task.FromResult(Unit.Instance); + } + + private sealed class TestCommandStrategy : DefaultStrategy + { + } +} diff --git a/test/unit/Elsa.Mediator.UnitTests/BackgroundNotificationProcessorTests.cs b/test/unit/Elsa.Mediator.UnitTests/BackgroundNotificationProcessorTests.cs new file mode 100644 index 000000000..d1fe97828 --- /dev/null +++ b/test/unit/Elsa.Mediator.UnitTests/BackgroundNotificationProcessorTests.cs @@ -0,0 +1,145 @@ +using System.Collections.Concurrent; +using Elsa.Mediator.Channels; +using Elsa.Mediator.Contexts; +using Elsa.Mediator.Contracts; +using Elsa.Mediator.Middleware.Notification; +using Elsa.Mediator.Options; +using Elsa.Mediator.PublishingStrategies; +using Elsa.Mediator.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Elsa.Mediator.UnitTests; + +public class BackgroundNotificationProcessorTests +{ + [Fact] + public async Task ExecuteAsync_CreatesIndependentScopePerWorker() + { + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); + await using var serviceProvider = services.BuildServiceProvider(); + var channel = new NotificationsChannel(); + var processor = new BackgroundNotificationProcessor( + Microsoft.Extensions.Options.Options.Create(new MediatorOptions { NotificationWorkerCount = 2 }), + channel, + serviceProvider.GetRequiredService(), + NullLogger.Instance); + using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + var runTask = processor.ExecuteAsync(cancellationTokenSource.Token); + var notificationStrategy = NotificationStrategy.Sequential; + + await channel.Writer.WriteAsync(new NotificationContext(new TestNotification(), notificationStrategy, serviceProvider), cancellationTokenSource.Token); + await channel.Writer.WriteAsync(new NotificationContext(new TestNotification(), notificationStrategy, serviceProvider), cancellationTokenSource.Token); + + var recorder = serviceProvider.GetRequiredService(); + await recorder.WaitForCallsAsync(2, cancellationTokenSource.Token); + await cancellationTokenSource.CancelAsync(); + await runTask; + + Assert.Equal(2, recorder.ScopeIds.Distinct().Count()); + } + + [Fact] + public async Task ExecuteAsync_UsesQueuedContextStrategy() + { + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); + await using var serviceProvider = services.BuildServiceProvider(); + var channel = new NotificationsChannel(); + var processor = new BackgroundNotificationProcessor( + Microsoft.Extensions.Options.Options.Create(new MediatorOptions { NotificationWorkerCount = 1 }), + channel, + serviceProvider.GetRequiredService(), + NullLogger.Instance); + using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + var runTask = processor.ExecuteAsync(cancellationTokenSource.Token); + var strategy = new TestNotificationStrategy(); + + await channel.Writer.WriteAsync(new NotificationContext(new TestNotification(), strategy, serviceProvider), cancellationTokenSource.Token); + + var recorder = serviceProvider.GetRequiredService(); + var recordedCall = await recorder.WaitForCallAsync(cancellationTokenSource.Token); + await cancellationTokenSource.CancelAsync(); + await runTask; + + Assert.Same(strategy, recordedCall.Strategy); + } + + [Fact] + public async Task BackgroundStrategy_QueuesExecutableContext() + { + var services = new ServiceCollection(); + services.AddSingleton(); + await using var serviceProvider = services.BuildServiceProvider(); + var channel = serviceProvider.GetRequiredService(); + var notificationContext = new NotificationContext(new TestNotification(), NotificationStrategy.Background, serviceProvider); + var strategyContext = new NotificationStrategyContext(notificationContext, [], NullLogger.Instance, serviceProvider); + + await NotificationStrategy.Background.PublishAsync(strategyContext); + + var queuedContext = await channel.Reader.ReadAsync(); + + Assert.Same(NotificationStrategy.Sequential, queuedContext.NotificationStrategy); + Assert.Same(notificationContext.Notification, queuedContext.Notification); + } + + private sealed class RecordingNotificationSender(WorkerScopeMarker scopeMarker, NotificationSenderRecorder recorder) : INotificationSender + { + public Task SendAsync(INotification notification, CancellationToken cancellationToken = default) + { + recorder.Record(scopeMarker.Id); + return Task.CompletedTask; + } + + public Task SendAsync(INotification notification, IEventPublishingStrategy? strategy, CancellationToken cancellationToken = default) + { + recorder.Record(scopeMarker.Id, strategy); + return Task.CompletedTask; + } + } + + private sealed class NotificationSenderRecorder + { + private int _callCount; + private readonly TaskCompletionSource _completed = new(TaskCreationOptions.RunContinuationsAsynchronously); + public ConcurrentBag ScopeIds { get; } = []; + private readonly TaskCompletionSource _firstCall = new(TaskCreationOptions.RunContinuationsAsynchronously); + + public void Record(Guid scopeId, IEventPublishingStrategy? strategy = null) + { + ScopeIds.Add(scopeId); + _firstCall.TrySetResult(new(strategy)); + + if (Interlocked.Increment(ref _callCount) == 2) + _completed.TrySetResult(); + } + + public async Task WaitForCallsAsync(int expectedCallCount, CancellationToken cancellationToken) + { + if (Volatile.Read(ref _callCount) >= expectedCallCount) + return; + + await _completed.Task.WaitAsync(cancellationToken); + } + + public Task WaitForCallAsync(CancellationToken cancellationToken) => _firstCall.Task.WaitAsync(cancellationToken); + } + + private sealed class WorkerScopeMarker + { + public Guid Id { get; } = Guid.NewGuid(); + } + + private sealed record TestNotification : INotification; + + private sealed record RecordedNotificationCall(IEventPublishingStrategy? Strategy); + + private sealed class TestNotificationStrategy : SequentialProcessingStrategy + { + } +} diff --git a/test/unit/Elsa.Workflows.Api.UnitTests/ActivityExecutions/ActivityExecutionsEndpointTests.cs b/test/unit/Elsa.Workflows.Api.UnitTests/ActivityExecutions/ActivityExecutionsEndpointTests.cs new file mode 100644 index 000000000..39294d194 --- /dev/null +++ b/test/unit/Elsa.Workflows.Api.UnitTests/ActivityExecutions/ActivityExecutionsEndpointTests.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using Elsa.Workflows.Runtime.Entities; +using FastEndpoints; +using WorkflowsApiFeature = Elsa.Workflows.Api.Features.WorkflowsApiFeature; + +namespace Elsa.Workflows.Api.UnitTests.ActivityExecutions; + +public class ActivityExecutionsEndpointTests +{ + [Fact] + public void GetEndpoint_ExposesPathAndQueryRoutes() + { + var endpointType = typeof(WorkflowsApiFeature).Assembly.GetType("Elsa.Workflows.Api.Endpoints.ActivityExecutions.Get.Endpoint", throwOnError: true)!; + var endpoint = Activator.CreateInstance(endpointType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, [null], null)!; + var definition = new EndpointDefinition(endpointType, typeof(EmptyRequest), typeof(ActivityExecutionRecord)); + + endpointType + .GetProperty("Definition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)! + .SetValue(endpoint, definition); + + endpointType.GetMethod("Configure")!.Invoke(endpoint, null); + + Assert.Contains("/activity-executions/{id}", definition.Routes); + Assert.Contains("/activity-executions/{*id}", definition.Routes); + Assert.Contains("/activity-executions/by-id", definition.Routes); + } +} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs index 54ce2cd71..c90ab0a78 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs @@ -1,6 +1,5 @@ using System.Text.Json; using Elsa.Common.Serialization; -using Elsa.Expressions.Services; using Elsa.Workflows.Activities; using Elsa.Workflows.Helpers; using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; @@ -9,6 +8,7 @@ using Elsa.Workflows.Models; using Elsa.Workflows.Serialization.Configurators; using Elsa.Workflows.Serialization.Converters; using Elsa.Workflows.Serialization.Helpers; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; using NSubstitute; @@ -162,7 +162,7 @@ public sealed class ActivityJsonConverterTests Converters = { sut, - new TypeJsonConverter(WellKnownTypeRegistry.CreateDefault()), + new TypeJsonConverter(new WorkflowJsonOptions()), new PolymorphicObjectConverterFactory() }, TypeInfoResolver = new ModifiableJsonTypeInfoResolver(new CustomConstructorConfigurator().GetModifiers()) @@ -352,4 +352,4 @@ public sealed class ActivityJsonConverterTests } private static ILogger CreateLogger() => LoggerFactory.Create(_ => { }).CreateLogger(); -} \ No newline at end of file +} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ExcludeFromHashConverterTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ExcludeFromHashConverterTests.cs deleted file mode 100644 index 493432cd4..000000000 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ExcludeFromHashConverterTests.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using Elsa.Workflows.Attributes; -using Elsa.Workflows.Serialization.Converters; - -namespace Elsa.Workflows.Core.UnitTests.Serialization.Converters; - -public class ExcludeFromHashConverterTests -{ - private readonly JsonSerializerOptions _options = new() - { - Converters = { new ExcludeFromHashConverterFactory() } - }; - - [Fact] - public void Write_IncludesConditionallyIgnoredProperty_WhenValueIsNotNull() - { - var json = JsonSerializer.Serialize(new ConditionalIgnoreModel { Name = "Alice" }, _options); - - Assert.Contains("\"Name\":\"Alice\"", json); - } - - [Fact] - public void Write_ExcludesConditionallyIgnoredProperty_WhenValueIsNull() - { - var json = JsonSerializer.Serialize(new ConditionalIgnoreModel(), _options); - - Assert.DoesNotContain("\"Name\"", json); - } - - [Fact] - public void Write_ExcludesAlwaysIgnoredProperty() - { - var json = JsonSerializer.Serialize(new AlwaysIgnoreModel { Secret = "hidden" }, _options); - - Assert.DoesNotContain("\"Secret\"", json); - } - - [Fact] - public void Write_SkipsIndexerProperties() - { - var json = JsonSerializer.Serialize(new IndexerModel(), _options); - - Assert.DoesNotContain("\"Item\"", json); - } - - [Fact] - public void Write_DoesNotEvaluateExcludedProperty() - { - var json = JsonSerializer.Serialize(new ExcludedThrowingModel(), _options); - - Assert.DoesNotContain("\"Secret\"", json); - } - - [Fact] - public void Write_DoesNotEvaluateAlwaysIgnoredProperty() - { - var json = JsonSerializer.Serialize(new AlwaysIgnoredThrowingModel(), _options); - - Assert.DoesNotContain("\"Secret\"", json); - } - - [Fact] - public void Write_IncludesNullableValueTypeWithDefaultUnderlyingValue_WhenIgnoringDefaults() - { - var json = JsonSerializer.Serialize(new DefaultIgnoreNullableModel { Count = 0 }, _options); - - Assert.Contains("\"Count\":0", json); - } - - [Fact] - public void Write_IncludesProperty_WhenJsonIgnoreConditionIsUnknown() - { - var json = JsonSerializer.Serialize(new UnknownIgnoreConditionModel { Name = "Alice" }, _options); - - Assert.Contains("\"Name\":\"Alice\"", json); - } - - [Fact] - public void Write_ExcludesStaticProperties() - { - var json = JsonSerializer.Serialize(new StaticPropertyModel { Name = "Alice" }, _options); - - Assert.Contains("\"Name\":\"Alice\"", json); - Assert.DoesNotContain("\"Secret\"", json); - } - - [Fact] - public void Write_PreservesDeclarationOrder() - { - var json = JsonSerializer.Serialize(new OrderedModel { B = "second", A = "first" }, _options); - - Assert.True(json.IndexOf("\"B\"", StringComparison.Ordinal) < json.IndexOf("\"A\"", StringComparison.Ordinal)); - } - - [Fact] - public void Write_OrdersInheritedProperties_ByDeclaringTypeThenDeclarationOrder() - { - var json = JsonSerializer.Serialize(new DerivedOrderedModel - { - BaseB = "base second", - BaseA = "base first", - DerivedB = "derived second", - DerivedA = "derived first" - }, _options); - - Assert.True(json.IndexOf("\"DerivedB\"", StringComparison.Ordinal) < json.IndexOf("\"DerivedA\"", StringComparison.Ordinal)); - Assert.True(json.IndexOf("\"DerivedA\"", StringComparison.Ordinal) < json.IndexOf("\"BaseB\"", StringComparison.Ordinal)); - Assert.True(json.IndexOf("\"BaseB\"", StringComparison.Ordinal) < json.IndexOf("\"BaseA\"", StringComparison.Ordinal)); - } - - private sealed class ConditionalIgnoreModel - { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Name { get; set; } - } - - private sealed class AlwaysIgnoreModel - { - [JsonIgnore] - public string? Secret { get; set; } - } - - private sealed class IndexerModel - { - public string this[int index] => index.ToString(); - } - - private sealed class ExcludedThrowingModel - { - [ExcludeFromHash] - public string Secret => throw new InvalidOperationException(); - } - - private sealed class AlwaysIgnoredThrowingModel - { - [JsonIgnore] - public string Secret => throw new InvalidOperationException(); - } - - private sealed class DefaultIgnoreNullableModel - { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] - public int? Count { get; set; } - } - - private sealed class UnknownIgnoreConditionModel - { - [JsonIgnore(Condition = (JsonIgnoreCondition)999)] - public string? Name { get; set; } - } - - private sealed class StaticPropertyModel - { - public static string Secret => throw new InvalidOperationException(); - - public string? Name { get; set; } - } - - private sealed class OrderedModel - { - public string? B { get; set; } - - public string? A { get; set; } - } - - private class BaseOrderedModel - { - public string? BaseB { get; set; } - - public string? BaseA { get; set; } - } - - private sealed class DerivedOrderedModel : BaseOrderedModel - { - public string? DerivedB { get; set; } - - public string? DerivedA { get; set; } - } -} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs index fd1a5d414..71f2b1396 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs @@ -1,200 +1,104 @@ using System.Text.Json; -using System.Text.Json.Nodes; -using Elsa.Expressions.Options; -using Elsa.Expressions.Services; +using Elsa.Expressions.Models; using Elsa.Extensions; +using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Exceptions; -using Elsa.Workflows.Memory; +using Elsa.Workflows.IncidentStrategies; +using Elsa.Workflows.Models; using Elsa.Workflows.Serialization.Converters; using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.State; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Newtonsoft.Json.Linq; namespace Elsa.Workflows.Core.UnitTests.Serialization.Converters; -public sealed class WorkflowJsonTypeResolverTests +public class WorkflowJsonTypeResolverTests { private static readonly string UnsafeAssemblyQualifiedTypeAlias = typeof(System.Text.StringBuilder).AssemblyQualifiedName!; - private readonly WellKnownTypeRegistry _wellKnownTypeRegistry = new(Microsoft.Extensions.Options.Options.Create(new ExpressionOptions())); + private static readonly string TrustedAssemblyQualifiedTypeAlias = typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(); private readonly JsonSerializerOptions _options; + private readonly JsonSerializerOptions _strictOptions; public WorkflowJsonTypeResolverTests() { - _wellKnownTypeRegistry.RegisterType(typeof(ExceptionState), nameof(ExceptionState)); - _wellKnownTypeRegistry.RegisterType(typeof(FaultException), nameof(FaultException)); - _wellKnownTypeRegistry.RegisterType(typeof(RegisteredPayload), "RegisteredPayload"); - _options = CreateOptions(_wellKnownTypeRegistry); + _options = CreateOptions(); + _strictOptions = CreateOptions(false); } - [Theory] - [InlineData("String", typeof(string))] - [InlineData("String[]", typeof(string[]))] - [InlineData("String[][]", typeof(string[][]))] - [InlineData("List", typeof(List))] - [InlineData("List", typeof(List))] - [InlineData("List>", typeof(List>))] - [InlineData("ExceptionState", typeof(ExceptionState))] - [InlineData("FaultException", typeof(FaultException))] - [InlineData("ObjectDictionary", typeof(IDictionary))] - public void When_DeserializeRegisteredTypeAlias_Then_ReturnsExpectedType(string typeAlias, Type expectedType) + [Fact] + public void TypeJsonConverter_ResolvesClrAssemblyQualifiedType() { + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(UnsafeAssemblyQualifiedTypeAlias), _options); + + Assert.Equal(typeof(System.Text.StringBuilder), result); + } + + [Fact] + public void TypeJsonConverter_RejectsUnregisteredClrAssemblyQualifiedType_WhenLegacyClrTypeNamesDisabled() + { + Assert.Throws(() => JsonSerializer.Deserialize(JsonSerializer.Serialize(UnsafeAssemblyQualifiedTypeAlias), _strictOptions)); + } + + [Fact] + public void TypeJsonConverter_ResolvesTrustedClrAssemblyQualifiedType() + { + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(TrustedAssemblyQualifiedTypeAlias), _options); + + Assert.Equal(typeof(UnregisteredPayload), result); + } + + [Fact] + public void TypeJsonConverter_ResolvesIncidentStrategyClrType() + { + var typeAlias = typeof(ContinueWithIncidentsStrategy).GetSimpleAssemblyQualifiedName(); + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _options); - Assert.Equal(expectedType, result); + Assert.Equal(typeof(ContinueWithIncidentsStrategy), result); } [Fact] - public void When_DeserializeRegisteredLegacyAssemblyQualifiedTypeAlias_Then_ReturnsExpectedType() + public void TypeJsonConverter_ResolvesFaultExceptionClrType() { - var typeAlias = typeof(RegisteredPayload).GetSimpleAssemblyQualifiedName(); + var typeAlias = typeof(FaultException).GetSimpleAssemblyQualifiedName(); - var result = JsonSerializer.Deserialize(JsonString(typeAlias), _options); + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _options); - Assert.Equal(typeof(RegisteredPayload), result); + Assert.Equal(typeof(FaultException), result); } [Fact] - public void When_DeserializeRegisteredLegacyGenericCollectionTypeAlias_Then_ReturnsExpectedType() + public void PolymorphicObjectConverter_ResolvesClrAssemblyQualifiedType() { - var typeAlias = typeof(List).GetSimpleAssemblyQualifiedName(); - - var result = JsonSerializer.Deserialize(JsonString(typeAlias), _options); - - Assert.Equal(typeof(List), result); - } - - [Theory] - [InlineData(typeof(string), "String")] - [InlineData(typeof(string[]), "String[]")] - [InlineData(typeof(string[][]), "String[][]")] - [InlineData(typeof(List), "List")] - [InlineData(typeof(List), "List")] - [InlineData(typeof(List>), "List>")] - [InlineData(typeof(ExceptionState), "ExceptionState")] - [InlineData(typeof(FaultException), "FaultException")] - public void When_SerializeSupportedType_Then_EmitsAliasThatCanBeDeserialized(Type type, string expectedAlias) - { - var json = JsonSerializer.Serialize(type, _options); - var alias = JsonSerializer.Deserialize(json); - var result = JsonSerializer.Deserialize(json, _options); - - Assert.Equal(expectedAlias, alias); - Assert.Equal(type, result); - } - - [Theory] - [InlineData(typeof(IEnumerable), "List", typeof(List))] - [InlineData(typeof(ICollection), "List", typeof(List))] - [InlineData(typeof(IList), "List", typeof(List))] - [InlineData(typeof(IReadOnlyCollection), "List", typeof(List))] - [InlineData(typeof(IReadOnlyList), "List", typeof(List))] - [InlineData(typeof(ISet), "HashSet", typeof(HashSet))] - public void When_SerializeInterfaceCollectionType_Then_EmitsInstantiableAlias(Type type, string expectedAlias, Type expectedRoundTripType) - { - var json = JsonSerializer.Serialize(type, _options); - var alias = JsonSerializer.Deserialize(json); - var result = JsonSerializer.Deserialize(json, _options); - - Assert.Equal(expectedAlias, alias); - Assert.Equal(expectedRoundTripType, result); - } - - [Theory] - [MemberData(nameof(JsonIslandValues))] - public void When_SerializeSpecialJsonIslandType_Then_CanBeDeserialized(object value, Type expectedType) - { - _wellKnownTypeRegistry.RegisterType(typeof(JObject), nameof(JObject)); - _wellKnownTypeRegistry.RegisterType(typeof(JArray), nameof(JArray)); - - var json = JsonSerializer.Serialize(value, _options); - var result = JsonSerializer.Deserialize(json, _options); - - Assert.IsType(expectedType, result); - } - - [Theory] - [InlineData(typeof(System.Text.StringBuilder))] - [InlineData(typeof(System.Text.StringBuilder[]))] - [InlineData(typeof(List))] - public void When_SerializeUnsupportedType_Then_EmitsSafeUnregisteredTypeAlias(Type type) - { - var json = JsonSerializer.Serialize(type, _options); - var alias = JsonSerializer.Deserialize(json); - var result = JsonSerializer.Deserialize(json, _options); - - Assert.StartsWith("UnregisteredClrType:", alias); - Assert.Equal(typeof(Exception), result); - } - - [Fact] - public void When_SerializeExceptionStateWithUnregisteredExceptionType_Then_DoesNotThrow() - { - var exceptionState = ExceptionState.FromException(new NullReferenceException("Test")); - - var json = JsonSerializer.Serialize(exceptionState, _options); - var result = JsonSerializer.Deserialize(json, _options)!; - - Assert.Contains("UnregisteredClrType:", json); - Assert.Equal(typeof(Exception), result.Type); - Assert.Equal("Test", result.Message); - } - - [Fact] - public void When_ConfigureWorkflowsFeature_Then_RegistersCoreAliases() - { - var services = new ServiceCollection(); - var module = services.CreateModule(); - module.UseWorkflows(); - module.Apply(); - using var serviceProvider = services.BuildServiceProvider(); - var expressionOptions = serviceProvider.GetRequiredService>(); - var registry = new WellKnownTypeRegistry(expressionOptions); - - var aliasRegistered = registry.TryGetAlias(typeof(NullReferenceException), out var alias); - var typeRegistered = registry.TryGetType(nameof(NullReferenceException), out var type); - - Assert.True(aliasRegistered); - Assert.Equal(nameof(NullReferenceException), alias); - Assert.True(typeRegistered); - Assert.Equal(typeof(NullReferenceException), type); - Assert.True(registry.TryGetAlias(typeof(MemoryStorageDriver), out var memoryStorageDriverAlias)); - Assert.Equal(nameof(MemoryStorageDriver), memoryStorageDriverAlias); - Assert.True(registry.TryGetType(nameof(MemoryStorageDriver), out var memoryStorageDriverType)); - Assert.Equal(typeof(MemoryStorageDriver), memoryStorageDriverType); - Assert.True(registry.TryGetType(typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName(), out var legacyMemoryStorageDriverType)); - Assert.Equal(typeof(MemoryStorageDriver), legacyMemoryStorageDriverType); - } - - [Fact] - public void When_SerializePolymorphicObjectWithUnregisteredType_Then_OmitsTypeMetadata() - { - var json = JsonSerializer.Serialize(new UnregisteredPayload { Name = "Alice" }, _options); + var json = $$""" + { + "name": "Alice", + "_type": {{JsonSerializer.Serialize(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName())}} + } + """; var result = JsonSerializer.Deserialize(json, _options); - Assert.DoesNotContain("\"_type\"", json); - var payload = Assert.IsAssignableFrom>(result); - Assert.Equal("Alice", payload["name"]); + var payload = Assert.IsType(result); + Assert.Equal("Alice", payload.Name); } [Fact] - public void When_DeserializeUnknownAssemblyQualifiedTypeAlias_Then_ThrowsJsonException() + public void PolymorphicObjectConverter_RejectsUnregisteredClrAssemblyQualifiedType_WhenLegacyClrTypeNamesDisabled() { - Assert.Throws(() => JsonSerializer.Deserialize(JsonString(UnsafeAssemblyQualifiedTypeAlias), _options)); + var json = $$""" + { + "name": "Alice", + "_type": {{JsonSerializer.Serialize(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName())}} + } + """; + + Assert.Throws(() => JsonSerializer.Deserialize(json, _strictOptions)); } [Fact] - public void When_DeserializeUnknownGenericElementTypeAlias_Then_ThrowsJsonException() - { - var typeAlias = $"List<{UnsafeAssemblyQualifiedTypeAlias}>"; - - Assert.Throws(() => JsonSerializer.Deserialize(JsonString(typeAlias), _options)); - } - - [Fact] - public void When_DeserializePolymorphicObjectWithRegisteredTypeAlias_Then_ReturnsTypedObject() + public void PolymorphicObjectConverter_ResolvesRegisteredTypeAlias() { var json = """ { @@ -209,142 +113,148 @@ public sealed class WorkflowJsonTypeResolverTests Assert.Equal("Alice", payload.Name); } - [Theory] - [InlineData("IEnumerable", typeof(List))] - [InlineData("ICollection", typeof(List))] - [InlineData("IList", typeof(List))] - [InlineData("IReadOnlyCollection", typeof(List))] - [InlineData("IReadOnlyList", typeof(List))] - [InlineData("ISet", typeof(HashSet))] - public void When_DeserializePolymorphicCollectionInterface_Then_ReturnsConcreteCollection(string typeAlias, Type expectedType) + [Fact] + public void PolymorphicObjectConverter_WritesClrTypeMetadataForUnregisteredTypes() { - var json = $$""" - { - "_items": ["Alice"], - "_type": "{{typeAlias}}" - } - """; - + var json = JsonSerializer.Serialize(new UnregisteredPayload { Name = "Alice" }, _options); var result = JsonSerializer.Deserialize(json, _options); - Assert.IsType(expectedType, result); - } - - [Fact] - public void When_DeserializePolymorphicObjectWithNonInstantiableType_Then_ThrowsJsonException() - { - _wellKnownTypeRegistry.RegisterType(typeof(AbstractPayload), "AbstractPayload"); - var json = """ - { - "_type": "AbstractPayload" - } - """; - - Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); - } - - [Fact] - public void When_DeserializePolymorphicObjectWithUnknownAssemblyQualifiedType_Then_ThrowsJsonException() - { - var json = $$""" - { - "capacity": 16, - "_type": {{JsonString(UnsafeAssemblyQualifiedTypeAlias)}} - } - """; - - Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); - } - - [Fact] - public void When_DeserializePolymorphicObjectWithoutTypeJsonConverterAndUnknownAssemblyQualifiedType_Then_ThrowsJsonException() - { - var options = CreatePolymorphicOnlyOptions(_wellKnownTypeRegistry); - var json = $$""" - { - "capacity": 16, - "_type": {{JsonString(UnsafeAssemblyQualifiedTypeAlias)}} - } - """; - - Assert.Throws(() => JsonSerializer.Deserialize(json, options)); - } - - [Fact] - public void When_DeserializeDictionaryObjectPayloadWithRegisteredTypeAlias_Then_ReturnsTypedObjectValue() - { - var json = """ - { - "payload": { - "name": "Alice", - "_type": "RegisteredPayload" - } - } - """; - - var result = JsonSerializer.Deserialize>(json, _options)!; - - var payload = Assert.IsType(result["payload"]); + Assert.Contains("\"_type\"", json); + var payload = Assert.IsType(result); Assert.Equal("Alice", payload.Name); } [Fact] - public void When_DeserializeDictionaryObjectPayloadWithUnknownAssemblyQualifiedType_Then_ThrowsJsonException() + public void PolymorphicObjectConverter_RejectsUnregisteredClrTypeMetadata_WhenLegacyClrTypeNamesDisabled() { - var json = $$""" - { - "payload": { - "capacity": 16, - "_type": {{JsonString(UnsafeAssemblyQualifiedTypeAlias)}} - } - } - """; - - Assert.Throws(() => JsonSerializer.Deserialize>(json, _options)); + Assert.Throws(() => JsonSerializer.Serialize(new UnregisteredPayload { Name = "Alice" }, _strictOptions)); } [Fact] - public void When_RegistryChangesAfterLegacyResolutionAttempt_Then_LegacyResolutionUsesCurrentRegistry() + public void TypeJsonConverter_WritesUnregisteredTypesAsClrTypeNames() { - var typeAlias = typeof(LateRegisteredPayload).GetSimpleAssemblyQualifiedName(); - Assert.False(WorkflowJsonTypeResolver.TryResolveType(_wellKnownTypeRegistry, typeAlias, out _)); + var json = JsonSerializer.Serialize(typeof(UnregisteredPayload), _options); + var alias = JsonSerializer.Deserialize(json); + var result = JsonSerializer.Deserialize(json, _options); - _wellKnownTypeRegistry.RegisterType(typeof(LateRegisteredPayload), "LateRegisteredPayload"); - - Assert.True(WorkflowJsonTypeResolver.TryResolveType(_wellKnownTypeRegistry, typeAlias, out var result)); - Assert.Equal(typeof(LateRegisteredPayload), result); + Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), alias); + Assert.Equal(typeof(UnregisteredPayload), result); } - private static JsonSerializerOptions CreateOptions(WellKnownTypeRegistry wellKnownTypeRegistry) => new() + [Fact] + public void TypeJsonConverter_RejectsUnregisteredClrTypeMetadata_WhenLegacyClrTypeNamesDisabled() + { + Assert.Throws(() => JsonSerializer.Serialize(typeof(UnregisteredPayload), _strictOptions)); + } + + [Fact] + public void OutputJsonConverter_WritesUnregisteredTypesAsClrTypeNames() + { + var options = CreateOptions(); + options.Converters.Add(new OutputJsonConverter(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions()))); + var output = new Output(new MemoryBlockReference("result")); + + var json = JsonSerializer.Serialize(output, options); + + using var doc = JsonDocument.Parse(json); + Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), doc.RootElement.GetProperty("typeName").GetString()); + } + + [Fact] + public void OutputJsonConverter_RejectsUnregisteredClrTypeMetadata_WhenLegacyClrTypeNamesDisabled() + { + var workflowJsonOptions = new WorkflowJsonOptions + { + AllowLegacyClrTypeNames = false + }; + var options = CreateOptions(); + options.Converters.Add(new OutputJsonConverter(Microsoft.Extensions.Options.Options.Create(workflowJsonOptions))); + var output = new Output(new MemoryBlockReference("result")); + + Assert.Throws(() => JsonSerializer.Serialize(output, options)); + } + + [Fact] + public void TypeJsonConverter_ResolvesRegisteredLegacyAssemblyQualifiedName() + { + var typeAlias = typeof(RegisteredPayload).GetSimpleAssemblyQualifiedName(); + + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _strictOptions); + + Assert.Equal(typeof(RegisteredPayload), result); + } + + [Fact] + public void TypeJsonConverter_ResolvesRegisteredAliasesCaseInsensitively() + { + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize("registeredpayload"), _strictOptions); + + Assert.Equal(typeof(RegisteredPayload), result); + } + + [Fact] + public void TypeJsonConverter_WritesPreferredAlias_WhenTypeHasMultipleAliases() + { + var json = JsonSerializer.Serialize(typeof(FlowJoinMode), _strictOptions); + + Assert.Equal("\"FlowJoinMode\"", json); + } + + [Fact] + public void TypeJsonConverter_RoundTripsNullableValueTypeAliases_WhenLegacyClrTypeNamesDisabled() + { + var json = JsonSerializer.Serialize(typeof(int?), _strictOptions); + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize("int32?"), _strictOptions); + + Assert.Equal("\"Int32?\"", json); + Assert.Equal(typeof(int?), result); + } + + [Fact] + public void ShellWorkflowsFeature_RegistersWorkflowJsonTypeAliases() + { + var services = new ServiceCollection(); + new Elsa.Workflows.ShellFeatures.WorkflowsFeature().ConfigureServices(services); + var workflowJsonOptions = services.BuildServiceProvider().GetRequiredService>().Value; + + var faultStrategy = WorkflowJsonTypeResolver.ResolveType(workflowJsonOptions, nameof(FaultStrategy), false); + + Assert.Equal(typeof(FaultStrategy), faultStrategy); + } + + [Fact] + public void ShellFlowchartFeature_RegistersFlowScopeTypeAlias() + { + var services = new ServiceCollection(); + new Elsa.Workflows.ShellFeatures.FlowchartFeature().ConfigureServices(services); + var workflowJsonOptions = services.BuildServiceProvider().GetRequiredService>().Value; + + var flowScope = WorkflowJsonTypeResolver.ResolveType(workflowJsonOptions, "FlowScope", false); + + Assert.Equal(typeof(FlowScope), flowScope); + } + + private JsonSerializerOptions CreateOptions(bool allowLegacyClrTypeNames = true) + { + var workflowJsonOptions = new WorkflowJsonOptions + { + AllowLegacyClrTypeNames = allowLegacyClrTypeNames + }; + workflowJsonOptions.RegisterWorkflowTypeAliases(); + workflowJsonOptions.RegisterTypeAlias(typeof(RegisteredPayload), "RegisteredPayload"); + workflowJsonOptions.RegisterTypeAlias(typeof(FaultStrategy), nameof(FaultStrategy)); + + return new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true, Converters = { - new PolymorphicObjectConverterFactory(wellKnownTypeRegistry), - new TypeJsonConverter(wellKnownTypeRegistry) + new PolymorphicObjectConverterFactory(workflowJsonOptions), + new TypeJsonConverter(workflowJsonOptions) } }; - - private static JsonSerializerOptions CreatePolymorphicOnlyOptions(WellKnownTypeRegistry wellKnownTypeRegistry) => new() - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - PropertyNameCaseInsensitive = true, - Converters = - { - new PolymorphicObjectConverterFactory(wellKnownTypeRegistry) - } - }; - - private static string JsonString(string value) => JsonSerializer.Serialize(value); - - public static TheoryData JsonIslandValues() => new() - { - { new JObject { ["name"] = "Alice" }, typeof(JObject) }, - { new JArray("Alice", "Bob"), typeof(JArray) }, - { new JsonObject { ["name"] = "Alice" }, typeof(JsonObject) }, - { new JsonArray("Alice", "Bob"), typeof(JsonArray) } - }; + } public sealed class RegisteredPayload { @@ -355,14 +265,4 @@ public sealed class WorkflowJsonTypeResolverTests { public string? Name { get; set; } } - - public abstract class AbstractPayload - { - public string? Name { get; set; } - } - - public sealed class LateRegisteredPayload - { - public string? Name { get; set; } - } } diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs index 4cc8b8eb1..62c6042ab 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs @@ -1,7 +1,8 @@ -using Elsa.Expressions.Services; +using System.Text.Json; using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Services; using Microsoft.Extensions.Logging.Abstractions; @@ -9,15 +10,15 @@ namespace Elsa.Workflows.Core.UnitTests.Services; public class VariableMapperTests { - private readonly WellKnownTypeRegistry _registry = new(); + private readonly WorkflowJsonOptions _workflowJsonOptions = new(); private readonly VariableMapper _mapper; public VariableMapperTests() { - _registry.RegisterType(typeof(string), "String"); - _registry.RegisterType(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); - _registry.RegisterType(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); - _mapper = new(_registry, NullLogger.Instance); + _workflowJsonOptions.RegisterTypeAlias(typeof(string), "String"); + _workflowJsonOptions.RegisterTypeAlias(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); + _workflowJsonOptions.RegisterTypeAlias(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); + _mapper = new(NullLogger.Instance, _workflowJsonOptions); } [Fact] @@ -37,7 +38,7 @@ public class VariableMapperTests } [Fact] - public void Map_ResolvesRegisteredMemoryStorageDriverAssemblyQualifiedName() + public void Map_ResolvesRegisteredStorageDriverAssemblyQualifiedName() { var variable = _mapper.Map(new VariableModel("id", "name", "String", "value", typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName())); @@ -55,10 +56,37 @@ public class VariableMapperTests [Fact] public void Map_DoesNotUseRegisteredNonStorageDriverAliasAsStorageDriver() { - _registry.RegisterType(typeof(string), "NotAStorageDriver"); + _workflowJsonOptions.RegisterTypeAlias(typeof(string), "NotAStorageDriver"); var variable = _mapper.Map(new VariableModel("id", "name", "String", "value", "NotAStorageDriver")); Assert.Null(variable.StorageDriverType); } + + [Fact] + public void Map_WritesUnregisteredVariableTypeAsClrTypeName() + { + var variable = new Variable("payload", new()); + + var model = _mapper.Map(variable); + + Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), model.TypeName); + } + + [Fact] + public void Map_RejectsUnregisteredVariableType_WhenLegacyClrTypeNamesDisabled() + { + var workflowJsonOptions = new WorkflowJsonOptions + { + AllowLegacyClrTypeNames = false + }; + var mapper = new VariableMapper(NullLogger.Instance, workflowJsonOptions); + var variable = new Variable("payload", new()); + + Assert.Throws(() => mapper.Map(variable)); + } + + private sealed class UnregisteredPayload + { + } } diff --git a/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs b/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs new file mode 100644 index 000000000..2a6ba1acb --- /dev/null +++ b/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs @@ -0,0 +1,82 @@ +using System.Text.Json; +using Elsa.Extensions; +using Elsa.Workflows.Management.Mappers; +using Elsa.Workflows.Memory; +using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; +using NSubstitute; + +namespace Elsa.Workflows.Management.UnitTests.Mappers; + +public class VariableDefinitionMapperTests +{ + private readonly IServiceScopeFactory _scopeFactory = Substitute.For(); + private readonly WorkflowJsonOptions _workflowJsonOptions = new(); + private readonly VariableDefinitionMapper _mapper; + + public VariableDefinitionMapperTests() + { + _workflowJsonOptions.RegisterTypeAlias(typeof(string), "String"); + _workflowJsonOptions.RegisterTypeAlias(typeof(MemoryStorageDriver), nameof(MemoryStorageDriver)); + _mapper = CreateMapper(_workflowJsonOptions); + } + + [Fact] + public void Map_ResolvesUnregisteredClrTypeName_WhenLegacyClrTypeNamesEnabled() + { + var definition = new VariableDefinition("id", "payload", typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), false, null, null); + + var variable = _mapper.Map(definition); + + Assert.IsType>(variable); + } + + [Fact] + public void Map_DoesNotResolveUnregisteredClrTypeName_WhenLegacyClrTypeNamesDisabled() + { + var workflowJsonOptions = new WorkflowJsonOptions + { + AllowLegacyClrTypeNames = false + }; + var mapper = CreateMapper(workflowJsonOptions); + var definition = new VariableDefinition("id", "payload", typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), false, null, null); + + var variable = mapper.Map(definition); + + Assert.Null(variable); + } + + [Fact] + public void Map_WritesUnregisteredVariableTypeAsClrTypeName() + { + var variable = new Variable("payload", new()); + + var definition = _mapper.Map(variable); + + Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), definition.TypeName); + } + + [Fact] + public void Map_RejectsUnregisteredVariableType_WhenLegacyClrTypeNamesDisabled() + { + var workflowJsonOptions = new WorkflowJsonOptions + { + AllowLegacyClrTypeNames = false + }; + var mapper = CreateMapper(workflowJsonOptions); + var variable = new Variable("payload", new()); + + Assert.Throws(() => mapper.Map(variable)); + } + + private VariableDefinitionMapper CreateMapper(WorkflowJsonOptions workflowJsonOptions) + { + return new(Microsoft.Extensions.Options.Options.Create(workflowJsonOptions), _scopeFactory, NullLogger.Instance); + } + + private sealed class UnregisteredPayload + { + } +} diff --git a/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs b/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs index f9748dc49..5e7eba5d3 100644 --- a/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs +++ b/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs @@ -1,12 +1,12 @@ using System.IO.Compression; using System.Text.Json; -using Elsa.Expressions.Contracts; using Elsa.Workflows.Activities; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Models; +using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using NSubstitute; @@ -60,9 +60,8 @@ public class WorkflowDefinitionExporterRegressionTests private WorkflowDefinitionExporter CreateExporter() { var activitySerializer = Substitute.For(); - var wellKnownTypeRegistry = Substitute.For(); var scopeFactory = Substitute.For(); - var variableDefinitionMapper = new VariableDefinitionMapper(wellKnownTypeRegistry, scopeFactory, NullLogger.Instance); + var variableDefinitionMapper = new VariableDefinitionMapper(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions()), scopeFactory, NullLogger.Instance); var workflowDefinitionMapper = new WorkflowDefinitionMapper(activitySerializer, _workflowDefinitionService, variableDefinitionMapper); var fileNameSanitizer = new DefaultFileNameSanitizer(); @@ -77,4 +76,4 @@ public class WorkflowDefinitionExporterRegressionTests return new(workflow, rootNode, [rootNode]); } -} \ No newline at end of file +} diff --git a/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs b/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs index 6299d3a86..d20a45359 100644 --- a/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs +++ b/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs @@ -1,10 +1,10 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Expressions.Contracts; -using Elsa.Expressions.Services; using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime.Comparers; using Elsa.Workflows.Runtime.Entities; +using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Serialization.Options; namespace Elsa.Workflows.Runtime.UnitTests.Comparers; @@ -27,8 +27,8 @@ public class WorkflowTriggerEqualityComparerTests /// A simple payload class that mimics real trigger payloads like HttpEndpointBookmarkPayload. /// private record TestPayload(string Path, string Method); - private record TypedPayload(Type PayloadType, object Value); - private record NestedPayload(string Name); + + private record TypePayload(Type TargetType); [Fact(DisplayName = "Fresh and round-tripped triggers with identical logical content should be considered equal")] public void FreshAndRoundTrippedTriggers_ShouldBeEqual() @@ -41,7 +41,7 @@ public class WorkflowTriggerEqualityComparerTests var roundTrippedPayload = SimulatePayloadRoundTrip(freshPayload); var loadedTrigger = CreateTrigger("trigger-1", roundTrippedPayload); - var comparer = new WorkflowTriggerEqualityComparer(CreateTypeRegistry()); + var comparer = new WorkflowTriggerEqualityComparer(); // Act var areEqual = comparer.Equals(freshTrigger, loadedTrigger); @@ -72,7 +72,7 @@ public class WorkflowTriggerEqualityComparerTests var newTriggers = new List { freshTrigger }; // Act: this is exactly what TriggerIndexer.IndexTriggersInternalAsync does - var diff = Diff.For(currentTriggers, newTriggers, new WorkflowTriggerEqualityComparer(CreateTypeRegistry())); + var diff = Diff.For(currentTriggers, newTriggers, new WorkflowTriggerEqualityComparer()); // Assert: the diff should find no changes. // Before the fix, it reported Removed=[existingTrigger] and Added=[freshTrigger] @@ -82,6 +82,22 @@ public class WorkflowTriggerEqualityComparerTests Assert.Single(diff.Unchanged); } + [Fact(DisplayName = "Comparer should use configured type aliases when normalizing trigger payloads")] + public void FreshAndRoundTrippedTriggers_WithRegisteredTypeAlias_ShouldBeEqual() + { + var workflowJsonOptions = new WorkflowJsonOptions(); + workflowJsonOptions.RegisterTypeAlias(typeof(CustomAliasTarget), "CustomAlias"); + var payload = new TypePayload(typeof(CustomAliasTarget)); + var roundTrippedPayload = SimulatePayloadRoundTrip(payload, workflowJsonOptions); + var freshTrigger = CreateTrigger("trigger-1", payload); + var loadedTrigger = CreateTrigger("trigger-1", roundTrippedPayload); + var comparer = new WorkflowTriggerEqualityComparer(workflowJsonOptions); + + var areEqual = comparer.Equals(freshTrigger, loadedTrigger); + + Assert.True(areEqual); + } + [Fact(DisplayName = "Documents the underlying System.Text.Json casing behavior that necessitated the fix")] public void PayloadSerializationMismatch_ProducesDifferentJson() { @@ -110,50 +126,6 @@ public class WorkflowTriggerEqualityComparerTests Assert.Equal("{\"Path\":\"/api/test\",\"Method\":\"GET\"}", freshJson); Assert.Equal("{\"path\":\"/api/test\",\"method\":\"GET\"}", roundTrippedJson); } - - [Fact(DisplayName = "Comparer serializes typed payload properties using the registered type aliases")] - public void TypedPayloadProperties_ShouldSerializeWithRegisteredAliases() - { - var payload = new TypedPayload(typeof(NestedPayload), new NestedPayload("orders")); - var comparer = new WorkflowTriggerEqualityComparer(CreateTypeRegistry()); - var trigger = CreateTrigger("trigger-1", payload); - var expectedAliasPayload = JsonSerializer.Deserialize( - """ - { - "payloadType": "NestedPayload", - "value": { - "name": "orders", - "_type": "NestedPayload" - } - } - """, - PayloadSerializerOptions); - var assemblyQualifiedPayload = JsonSerializer.Deserialize( - $$""" - { - "payloadType": "{{typeof(NestedPayload).AssemblyQualifiedName}}", - "value": { - "name": "orders", - "_type": "{{typeof(NestedPayload).AssemblyQualifiedName}}" - } - } - """, - PayloadSerializerOptions); - var missingTypePayload = JsonSerializer.Deserialize( - """ - { - "payloadType": "NestedPayload", - "value": { - "name": "orders" - } - } - """, - PayloadSerializerOptions); - - Assert.True(comparer.Equals(trigger, CreateTrigger("trigger-2", expectedAliasPayload!))); - Assert.False(comparer.Equals(trigger, CreateTrigger("trigger-3", assemblyQualifiedPayload!))); - Assert.False(comparer.Equals(trigger, CreateTrigger("trigger-4", missingTypePayload!))); - } /// /// IPayloadSerializer options: camelCase with case-insensitive deserialization. @@ -190,13 +162,20 @@ public class WorkflowTriggerEqualityComparerTests return deserialized!; } - private static IWellKnownTypeRegistry CreateTypeRegistry() + private static object SimulatePayloadRoundTrip(object payload, WorkflowJsonOptions workflowJsonOptions) { - var registry = WellKnownTypeRegistry.CreateDefault(); - registry.RegisterType(typeof(TestPayload), nameof(TestPayload)); - registry.RegisterType(typeof(TypedPayload), nameof(TypedPayload)); - registry.RegisterType(typeof(NestedPayload), nameof(NestedPayload)); - return registry; + var options = CreatePayloadSerializerOptions(workflowJsonOptions); + var json = JsonSerializer.Serialize(payload, options); + return JsonSerializer.Deserialize(json, options)!; + } + + private static JsonSerializerOptions CreatePayloadSerializerOptions(WorkflowJsonOptions workflowJsonOptions) + { + var options = new JsonSerializerOptions(PayloadSerializerOptions); + options.Converters.Add(new JsonStringEnumConverter()); + options.Converters.Add(new PolymorphicObjectConverterFactory(workflowJsonOptions)); + options.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); + return options; } /// @@ -219,4 +198,6 @@ public class WorkflowTriggerEqualityComparerTests Hash = hash, Payload = payload }; + + private sealed class CustomAliasTarget; } diff --git a/test/unit/Elsa.Workflows.Runtime.UnitTests/Extensions/ServiceCollectionWorkflowExtensionsTests.cs b/test/unit/Elsa.Workflows.Runtime.UnitTests/Extensions/ServiceCollectionWorkflowExtensionsTests.cs new file mode 100644 index 000000000..97084a465 --- /dev/null +++ b/test/unit/Elsa.Workflows.Runtime.UnitTests/Extensions/ServiceCollectionWorkflowExtensionsTests.cs @@ -0,0 +1,29 @@ +using Elsa.Extensions; +using Elsa.Workflows; +using Elsa.Workflows.Runtime.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Elsa.Workflows.Runtime.UnitTests.Extensions; + +public class ServiceCollectionWorkflowExtensionsTests +{ + [Fact] + public void AddWorkflow_PostConfiguresRuntimeOptions() + { + var services = new ServiceCollection(); + var configuredWorkflows = new Dictionary>>(); + + services.Configure(options => options.Workflows = configuredWorkflows); + services.AddWorkflow(); + + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>().Value; + var workflowKey = typeof(ServiceCollectionRegisteredWorkflow).GetSimpleAssemblyQualifiedName(); + + Assert.Same(configuredWorkflows, options.Workflows); + Assert.Contains(workflowKey, options.Workflows.Keys); + } +} + +public class ServiceCollectionRegisteredWorkflow : WorkflowBase; diff --git a/test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs b/test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs deleted file mode 100644 index d68ca615b..000000000 --- a/test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System.Reflection; -using Elsa.Expressions.Options; -using Elsa.Features.Attributes; -using Elsa.Features.Services; -using Elsa.Extensions; -using Elsa.Workflows; -using Elsa.Workflows.Activities; -using Elsa.Workflows.Features; -using Elsa.Workflows.Runtime.Options; -using Elsa.Workflows.Runtime.Providers; -using NSubstitute; -using RuntimeFeature = Elsa.Workflows.Runtime.Features.WorkflowRuntimeFeature; -using ShellRuntimeFeature = Elsa.Workflows.Runtime.ShellFeatures.WorkflowRuntimeFeature; - -namespace Elsa.Workflows.Runtime.UnitTests.Features; - -public class WorkflowRuntimeFeatureTests -{ - private readonly RuntimeFeature _feature = new(Substitute.For()); - private readonly ShellRuntimeFeature _shellFeature = new(); - - [Fact] - public void AddWorkflow_Throws_WhenTypeDoesNotImplementWorkflow() - { - Assert.Throws(() => _feature.AddWorkflow(typeof(NotAWorkflow))); - } - - [Theory] - [MemberData(nameof(NonInstantiableWorkflowTypes))] - public void AddWorkflow_Throws_WhenWorkflowTypeIsNotInstantiable(Type workflowType) - { - Assert.Throws(() => _feature.AddWorkflow(workflowType)); - } - - [Fact] - public void ShellAddWorkflow_Throws_WhenTypeDoesNotImplementWorkflow() - { - Assert.Throws(() => _shellFeature.AddWorkflow(typeof(NotAWorkflow))); - } - - [Theory] - [MemberData(nameof(NonInstantiableWorkflowTypes))] - public void ShellAddWorkflow_Throws_WhenWorkflowTypeIsNotInstantiable(Type workflowType) - { - Assert.Throws(() => _shellFeature.AddWorkflow(workflowType)); - } - - [Fact] - public void AddWorkflow_AllowsClosedGenericWorkflowType() - { - var workflowType = typeof(GenericWorkflow); - - _feature.AddWorkflow(workflowType); - - Assert.Contains(workflowType.GetSimpleAssemblyQualifiedName(), _feature.Workflows.Keys); - Assert.Contains(workflowType.FullName!, _feature.Workflows.Keys); - } - - [Fact] - public void ShellAddWorkflow_AllowsClosedGenericWorkflowType() - { - var workflowType = typeof(GenericWorkflow); - - _shellFeature.AddWorkflow(workflowType); - - Assert.Contains(workflowType.GetSimpleAssemblyQualifiedName(), _shellFeature.Workflows.Keys); - Assert.Contains(workflowType.FullName!, _shellFeature.Workflows.Keys); - } - - [Fact] - public void WorkflowsAdd_RegistersWorkflowTypeAlias() - { - var workflowType = typeof(GenericWorkflow); - var options = new ExpressionOptions(); - - _feature.Workflows.Add(workflowType); - - RegisterWorkflowTypeAliases(_feature, options); - - Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); - } - - [Fact] - public void WorkflowsAdd_DoesNotThrow_WhenLegacyKeyAlreadyExists() - { - var workflowType = typeof(GenericWorkflow); - _feature.Workflows.Add(workflowType.FullName!, _ => new ValueTask(new GenericWorkflow())); - - _feature.Workflows.Add(workflowType); - - Assert.Contains(workflowType.GetSimpleAssemblyQualifiedName(), _feature.Workflows.Keys); - Assert.Contains(workflowType.FullName!, _feature.Workflows.Keys); - Assert.Same(_feature.Workflows[workflowType.FullName!], _feature.Workflows[workflowType.GetSimpleAssemblyQualifiedName()]); - } - - [Fact] - public async Task ClrWorkflowsProvider_MaterializesWorkflowOnce_WhenCanonicalAndLegacyKeysExist() - { - CountingWorkflow.CreatedCount = 0; - var builder = Substitute.For(); - var builderFactory = Substitute.For(); - var provider = new ClrWorkflowsProvider( - Microsoft.Extensions.Options.Options.Create(new RuntimeOptions { Workflows = _feature.Workflows }), - builderFactory, - Substitute.For()); - builderFactory.CreateBuilder().Returns(builder); - builder.BuildWorkflowAsync(Arg.Any()).Returns(new Workflow()); - - _feature.Workflows.Add(typeof(CountingWorkflow)); - var workflows = await provider.GetWorkflowsAsync(); - - Assert.Single(workflows); - Assert.Equal(1, CountingWorkflow.CreatedCount); - } - - [Fact] - public void ShellWorkflowsAdd_RegistersWorkflowTypeAlias() - { - var workflowType = typeof(GenericWorkflow); - var options = new ExpressionOptions(); - - _shellFeature.Workflows.Add(workflowType); - - RegisterWorkflowTypeAliases(_shellFeature, options); - - Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); - } - - [Fact] - public void WorkflowsAdd_Throws_WhenTypeDoesNotImplementWorkflow() - { - Assert.Throws(() => _feature.Workflows.Add(typeof(NotAWorkflow))); - } - - [Fact] - public void RuntimeFeature_DependsOnWorkflowsFeature() - { - var dependencyTypes = typeof(RuntimeFeature) - .GetCustomAttributes() - .Select(x => x.Type); - - Assert.Contains(typeof(WorkflowsFeature), dependencyTypes); - } - - [Fact] - public void RegisterWorkflowTypeAliases_RegistersOnlyTrackedWorkflowTypes() - { - var workflowType = typeof(GenericWorkflow); - var options = new ExpressionOptions(); - _feature.AddWorkflow(workflowType); - _feature.Workflows[typeof(NotAWorkflow).AssemblyQualifiedName!] = _ => new ValueTask(new GenericWorkflow()); - - RegisterWorkflowTypeAliases(_feature, options); - - Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); - Assert.DoesNotContain(typeof(NotAWorkflow).AssemblyQualifiedName!, options.AliasTypeDictionary.Keys); - } - - [Fact] - public void ShellRegisterWorkflowTypeAliases_RegistersOnlyTrackedWorkflowTypes() - { - var workflowType = typeof(GenericWorkflow); - var options = new ExpressionOptions(); - _shellFeature.AddWorkflow(workflowType); - _shellFeature.Workflows[typeof(NotAWorkflow).AssemblyQualifiedName!] = _ => new ValueTask(new GenericWorkflow()); - - RegisterWorkflowTypeAliases(_shellFeature, options); - - Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); - Assert.DoesNotContain(typeof(NotAWorkflow).AssemblyQualifiedName!, options.AliasTypeDictionary.Keys); - } - - public static TheoryData NonInstantiableWorkflowTypes() => new() - { - typeof(IWorkflow), - typeof(WorkflowBase), - typeof(GenericWorkflow<>) - }; - - private sealed class NotAWorkflow - { - } - - private sealed class GenericWorkflow : IWorkflow - { - public ValueTask BuildAsync(IWorkflowBuilder builder, CancellationToken cancellationToken = default) - { - return ValueTask.CompletedTask; - } - } - - public sealed class CountingWorkflow : IWorkflow - { - public static int CreatedCount { get; set; } - - public CountingWorkflow() - { - CreatedCount++; - } - - public ValueTask BuildAsync(IWorkflowBuilder builder, CancellationToken cancellationToken = default) - { - return ValueTask.CompletedTask; - } - } - - private static void RegisterWorkflowTypeAliases(object feature, ExpressionOptions options) - { - feature.GetType() - .GetMethod("RegisterWorkflowTypeAliases", BindingFlags.Instance | BindingFlags.NonPublic)! - .Invoke(feature, new object[] { options }); - } -} From 5c408dff543286b3a4caccf673282af238804f28 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 31 May 2026 08:23:22 +0200 Subject: [PATCH 3/6] Resolve OpenTelemetry package warnings (#7546) --- Directory.Packages.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b66561041..22622fee5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -155,13 +155,13 @@ - + - - - - - + + + + + From 9124c2847ccf5d1191a6727d24b3462d597e8f35 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 31 May 2026 08:30:40 +0200 Subject: [PATCH 4/6] Bump OpenTelemetry and Remotion dependencies (#7547) --- .../video/elsa-readme-video/package-lock.json | 639 +++++----- design/video/elsa-readme-video/package.json | 4 +- .../exports/elsa-workflows-readme-poster.png | Bin 735255 -> 735339 bytes .../ClientLib/dist/lodash.js | 4 +- .../ClientLib/dist/lodashFp.js | 10 +- .../ClientLib/dist/moment.js | 278 ++--- .../ClientLib/package-lock.json | 1101 +++++++++-------- 7 files changed, 1020 insertions(+), 1016 deletions(-) diff --git a/design/video/elsa-readme-video/package-lock.json b/design/video/elsa-readme-video/package-lock.json index 00808f410..4810e9cf9 100644 --- a/design/video/elsa-readme-video/package-lock.json +++ b/design/video/elsa-readme-video/package-lock.json @@ -8,10 +8,10 @@ "name": "elsa-readme-video", "version": "0.1.0", "dependencies": { - "@remotion/cli": "4.0.462", + "@remotion/cli": "4.0.469", "react": "19.2.6", "react-dom": "19.2.6", - "remotion": "4.0.462" + "remotion": "4.0.469" }, "devDependencies": { "@types/react": "19.2.14", @@ -20,18 +20,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -660,23 +660,21 @@ } }, "node_modules/@remotion/bundler": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/bundler/-/bundler-4.0.462.tgz", - "integrity": "sha512-GlKjrFkrkl/UgiSTCzMPxRtTnOswOUozo5kk0TmK27tDlF9Mkm6Vyy/Dk5UptPIxDeTi8RIvGWrRRhgVUgzzeQ==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/bundler/-/bundler-4.0.469.tgz", + "integrity": "sha512-vHJD/Ey3aTmjlFJ2m9stA+BK3uoacjNB7dT0hSSFQjuN0X4suNmSgA3lRhxPBcUFrrziy4HRXaiJp5H2y3Yc2Q==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@remotion/media-parser": "4.0.462", - "@remotion/studio": "4.0.462", - "@remotion/studio-shared": "4.0.462", - "@remotion/timeline-utils": "4.0.462", + "@remotion/media-parser": "4.0.469", + "@remotion/studio": "4.0.469", + "@remotion/studio-shared": "4.0.469", + "@remotion/timeline-utils": "4.0.469", "@rspack/core": "1.7.6", "@rspack/plugin-react-refresh": "1.6.1", + "css-loader": "7.1.4", "esbuild": "0.28.0", - "loader-utils": "2.0.4", - "postcss": "8.5.10", - "postcss-value-parser": "4.2.0", "react-refresh": "0.18.0", - "remotion": "4.0.462", + "remotion": "4.0.469", "style-loader": "4.0.0", "webpack": "5.105.0" }, @@ -686,22 +684,22 @@ } }, "node_modules/@remotion/cli": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/cli/-/cli-4.0.462.tgz", - "integrity": "sha512-ZFeXBM2bl1Eku8OroJyCOK+kflMTbJ7HBhUaH8qN3WSyX0dOngBKkNa9DRFbiDJVDGgE0ziG7uiSuU/oB1HPqQ==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/cli/-/cli-4.0.469.tgz", + "integrity": "sha512-dv3hpY0CsjzkwPVXQJcJQHikXLHzupFyJg835rp5zBuqF+i/HmhZM8VZdh4LZDEut3OHJD3vkEgAk35R18Q8iQ==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@remotion/bundler": "4.0.462", - "@remotion/media-utils": "4.0.462", - "@remotion/player": "4.0.462", - "@remotion/renderer": "4.0.462", - "@remotion/studio": "4.0.462", - "@remotion/studio-server": "4.0.462", - "@remotion/studio-shared": "4.0.462", + "@remotion/bundler": "4.0.469", + "@remotion/media-utils": "4.0.469", + "@remotion/player": "4.0.469", + "@remotion/renderer": "4.0.469", + "@remotion/studio": "4.0.469", + "@remotion/studio-server": "4.0.469", + "@remotion/studio-shared": "4.0.469", "dotenv": "17.3.1", "minimist": "1.2.6", "prompts": "2.4.2", - "remotion": "4.0.462" + "remotion": "4.0.469" }, "bin": { "remotion": "remotion-cli.js", @@ -714,9 +712,9 @@ } }, "node_modules/@remotion/compositor-darwin-arm64": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-darwin-arm64/-/compositor-darwin-arm64-4.0.462.tgz", - "integrity": "sha512-soKDNA0jSppazP9jxbz4OFQRTVS9mIj5w+5EtmcH23gCdnZejjCEO8839YE7nhHi5C7wgqU/sdkwRs3FyfP+tg==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-darwin-arm64/-/compositor-darwin-arm64-4.0.469.tgz", + "integrity": "sha512-Ke/PljsHgvHIJD7rGlgTGkvmY044abjTUo2QI3Qq368NGzzEHe2USVyqycacKTilHCtcZG1n8CMbofpkXHurcg==", "cpu": [ "arm64" ], @@ -726,9 +724,9 @@ ] }, "node_modules/@remotion/compositor-darwin-x64": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-darwin-x64/-/compositor-darwin-x64-4.0.462.tgz", - "integrity": "sha512-xAkk7095Ud/Ugs3SP7GERnTwm2sljuZ4K89Gb5Y8tvdObqH70u1TMobzNWPcBOJcYOl7hgfc4dqV9pvMTHo+hw==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-darwin-x64/-/compositor-darwin-x64-4.0.469.tgz", + "integrity": "sha512-e6usJHMZQN1qUrjLfaVXAHk212W+FMDzDQWJAnxzXDnb+diPpFvzmW8tGdZWTOjU5mBttEJQmS507zHvs2q4uQ==", "cpu": [ "x64" ], @@ -738,9 +736,9 @@ ] }, "node_modules/@remotion/compositor-linux-arm64-gnu": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-arm64-gnu/-/compositor-linux-arm64-gnu-4.0.462.tgz", - "integrity": "sha512-8Qy3lGKQsX/Kuxlji9AENnlpzRSDuG/K5DIe7o73YBitxey539sp1D3Ww0VCrE0uyH4Gj85KiPrT8YEESMcpCA==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-arm64-gnu/-/compositor-linux-arm64-gnu-4.0.469.tgz", + "integrity": "sha512-/N7Bhq024Fw10n6kvx53D8EO3UQOOL6gmq8PJ3o7XORDSANzyYtTogyqHFMJ7LxZ5MLRP1vbdu2kqimBYJA3qw==", "cpu": [ "arm64" ], @@ -753,9 +751,9 @@ ] }, "node_modules/@remotion/compositor-linux-arm64-musl": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-arm64-musl/-/compositor-linux-arm64-musl-4.0.462.tgz", - "integrity": "sha512-dZjq3H8GngDdZs3/cqOdrPKOhW1UhQb99emYNx+G4Mv4kIpqX3sOEGYZNokCDZxR8hiAehI8BqblHk1NGDa0mQ==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-arm64-musl/-/compositor-linux-arm64-musl-4.0.469.tgz", + "integrity": "sha512-kVlqB1SSJ/ihVncgwEh9uKqMhjdtS+6NTuUTpZbVlEx34s8SN7Y7MV0cHHQnx4KiksbFvVABGVjL9a6yiqIuEw==", "cpu": [ "arm64" ], @@ -768,9 +766,9 @@ ] }, "node_modules/@remotion/compositor-linux-x64-gnu": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-x64-gnu/-/compositor-linux-x64-gnu-4.0.462.tgz", - "integrity": "sha512-nfqqBOc81+CnkmoOFhQF0EzqiGK1N5FwrcwrxexJxoQkxpNk4kMRp2CKyaOd6cHEx1hQKKCl/pPiScEez8ZwfA==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-x64-gnu/-/compositor-linux-x64-gnu-4.0.469.tgz", + "integrity": "sha512-lP+Hzujpk3IB41thQEAf3vnK3bhfqjPrxytKqQ4gWxV830mhQ7g3Htgu9oWGYfshdbfWeMjlRF8rEClzcU/xBw==", "cpu": [ "x64" ], @@ -783,9 +781,9 @@ ] }, "node_modules/@remotion/compositor-linux-x64-musl": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-x64-musl/-/compositor-linux-x64-musl-4.0.462.tgz", - "integrity": "sha512-AFNmG/Ll2lP3Hh9E7qjWkTIKaNfxZwQJeke2bWmcOV+tlWJa/mFccNVHnoDP5NpjpYwAHvemCUxmPIV1l2/7lw==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-x64-musl/-/compositor-linux-x64-musl-4.0.469.tgz", + "integrity": "sha512-5NV/W1rmZIQFn4ivYCNyg/YooUxKkd+EX/d+rdt/sidPzQUpySRm81F+pnnuqnVldlHmr6LGl9sNe5DSH9dJtw==", "cpu": [ "x64" ], @@ -798,9 +796,9 @@ ] }, "node_modules/@remotion/compositor-win32-x64-msvc": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/compositor-win32-x64-msvc/-/compositor-win32-x64-msvc-4.0.462.tgz", - "integrity": "sha512-lXjrweVS3cEpfR33TH7so93GKUtx77zfK0iKBkrTcwZw7IIYYIBG8Y7H2M2MTIW3xQDPtuJPhOuVTiUFcocmcw==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/compositor-win32-x64-msvc/-/compositor-win32-x64-msvc-4.0.469.tgz", + "integrity": "sha512-0lEP9HvbCgQa7HxMl804DrE49kmctidNgSNHavVT7O7B4E03uxAt4kaRRy1P7SLeGMJ/1wKIYLfWtvV4sd7HKA==", "cpu": [ "x64" ], @@ -810,25 +808,25 @@ ] }, "node_modules/@remotion/licensing": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/licensing/-/licensing-4.0.462.tgz", - "integrity": "sha512-NbTiGVmqp7NJsLbjJP84jB5oLO92a6TJiq2KckpdpZlekLPbITpKp984rXMZjZgE/B0LkeYkIHRNO75AikFQLQ==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/licensing/-/licensing-4.0.469.tgz", + "integrity": "sha512-ZSM0no+STTcEQAYGyyarXKkpQet18kXgJR59oTmRa0iqS+nN78OMBE4Uj7totpfmhXYV98T4gWgkGHqjDjqcBg==", "license": "MIT" }, "node_modules/@remotion/media-parser": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/media-parser/-/media-parser-4.0.462.tgz", - "integrity": "sha512-wSXZcVhNppSxsw+kDF6Y00YqnTQvw88OU3sM6P2JR6IKzsKq2bSMgm4amqVs1K1hP7m3CAdx4NqG/5H9a9/kzw==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/media-parser/-/media-parser-4.0.469.tgz", + "integrity": "sha512-mBHh2e7YK3CFiDvfXVoFxgxZrg7PtlDnYKCQHmkoqleBP3rpJlYaXeCgHt+mDwSUd0HFxGFdKYlDdXEn0Kh4kQ==", "license": "Remotion License https://remotion.dev/license" }, "node_modules/@remotion/media-utils": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/media-utils/-/media-utils-4.0.462.tgz", - "integrity": "sha512-naC7SVMO979E6kRzXxL3H1IoaNdTucE+7NbYDbt6ixrlsFtenpiRaVH0RlJPmYXmcwss3dvmmabVwrQ7RrMB5Q==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/media-utils/-/media-utils-4.0.469.tgz", + "integrity": "sha512-L1Qk0PR0BQRhuCgBBnPSKi0zVTe2U2vx8Z2GmNgTqaJvNnzyMJ4WyWyMWYegNs68nFKoUJ5yskkI6oPUwrhCmg==", "license": "MIT", "dependencies": { "mediabunny": "1.45.0", - "remotion": "4.0.462" + "remotion": "4.0.469" }, "peerDependencies": { "react": ">=16.8.0", @@ -836,12 +834,12 @@ } }, "node_modules/@remotion/player": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/player/-/player-4.0.462.tgz", - "integrity": "sha512-w/zBCWwLXsoNwsokaPwKxpdv+CBw52FuR3pQZegZvcnKwx1d8bq2P4xBjhCs+o5XP7kiRS0FQIIFYiCmXZXYgw==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/player/-/player-4.0.469.tgz", + "integrity": "sha512-cAnin3JPrJx0mBFT7bcZ9N8xOwXygMIWeM4qHgDONfIwgqouir8gQFPIxRtyAzNubMl8xvLjbPSBbDeusNDAGw==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "remotion": "4.0.462" + "remotion": "4.0.469" }, "peerDependencies": { "react": ">=16.8.0", @@ -849,27 +847,26 @@ } }, "node_modules/@remotion/renderer": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/renderer/-/renderer-4.0.462.tgz", - "integrity": "sha512-qwOsGvtGb3CIpYMrVeO+wTwJN+C3uigT9gKyM0tl24IrPbq8UWqkX1mDJv5pYcWUbCj1mEdeakh7ue9+zgdEgA==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/renderer/-/renderer-4.0.469.tgz", + "integrity": "sha512-9529YcfPbZCQCVhq/eGQaqsuQzAeXClWzq9Eq3vC1UpJrAwsA3DfpDZiwu8IOXVhKqR4uouYJZQagcAahhH9bg==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@remotion/licensing": "4.0.462", - "@remotion/streaming": "4.0.462", + "@remotion/licensing": "4.0.469", + "@remotion/streaming": "4.0.469", "execa": "5.1.1", - "extract-zip": "2.0.1", - "remotion": "4.0.462", + "remotion": "4.0.469", "source-map": "0.8.0-beta.0", - "ws": "8.17.1" + "ws": "8.20.1" }, "optionalDependencies": { - "@remotion/compositor-darwin-arm64": "4.0.462", - "@remotion/compositor-darwin-x64": "4.0.462", - "@remotion/compositor-linux-arm64-gnu": "4.0.462", - "@remotion/compositor-linux-arm64-musl": "4.0.462", - "@remotion/compositor-linux-x64-gnu": "4.0.462", - "@remotion/compositor-linux-x64-musl": "4.0.462", - "@remotion/compositor-win32-x64-msvc": "4.0.462" + "@remotion/compositor-darwin-arm64": "4.0.469", + "@remotion/compositor-darwin-x64": "4.0.469", + "@remotion/compositor-linux-arm64-gnu": "4.0.469", + "@remotion/compositor-linux-arm64-musl": "4.0.469", + "@remotion/compositor-linux-x64-gnu": "4.0.469", + "@remotion/compositor-linux-x64-musl": "4.0.469", + "@remotion/compositor-win32-x64-msvc": "4.0.469" }, "peerDependencies": { "react": ">=16.8.0", @@ -877,29 +874,29 @@ } }, "node_modules/@remotion/streaming": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/streaming/-/streaming-4.0.462.tgz", - "integrity": "sha512-o3+GgxZURUr1wwlTSKg3JRIF/r3ctSMUrMFB3rjxlcXKNW4Z/Izkho2lWmZlONYtZHJVshg6hfS3OxjTK2zwdA==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/streaming/-/streaming-4.0.469.tgz", + "integrity": "sha512-ACYjvcoCxIhVLICgm6zNyxKtXOsRnQ+GocWyY8SdHS2LNpLj/ihRj2xXAdJcuqQI/FaITHIvMiK9kwGAv3J6iw==", "license": "MIT" }, "node_modules/@remotion/studio": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/studio/-/studio-4.0.462.tgz", - "integrity": "sha512-Rl+VhBesr1cCDuFogE2p+oAIF/IVM0fQYZDWWSLHFwF37gb6jLIfEgrrFqgarPwNTAEZwY2qqr2c7J3uooeH1Q==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/studio/-/studio-4.0.469.tgz", + "integrity": "sha512-YMwNokK3XDfhCjZs0J6zj4kcOXlb96YugMMfOY3xBHyVmbKOnSyhNHyZ07E9Kr48p2lorzzS6n6kpFrpOt2FLQ==", "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.31", - "@remotion/media-utils": "4.0.462", - "@remotion/player": "4.0.462", - "@remotion/renderer": "4.0.462", - "@remotion/studio-shared": "4.0.462", - "@remotion/timeline-utils": "4.0.462", - "@remotion/web-renderer": "4.0.462", - "@remotion/zod-types": "4.0.462", + "@remotion/media-utils": "4.0.469", + "@remotion/player": "4.0.469", + "@remotion/renderer": "4.0.469", + "@remotion/studio-shared": "4.0.469", + "@remotion/timeline-utils": "4.0.469", + "@remotion/web-renderer": "4.0.469", + "@remotion/zod-types": "4.0.469", "mediabunny": "1.45.0", "memfs": "3.4.3", "open": "8.4.2", - "remotion": "4.0.462", + "remotion": "4.0.469", "semver": "7.5.3", "zod": "4.3.6" }, @@ -909,54 +906,54 @@ } }, "node_modules/@remotion/studio-server": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/studio-server/-/studio-server-4.0.462.tgz", - "integrity": "sha512-RI4KwdLju6yKO1IDDAtLVy0gelYf+rfLqhpRpRoutFj3X9euajbX2o7Fghfc3Qn6UfAz3VA78U8z4ZO75BAeQg==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/studio-server/-/studio-server-4.0.469.tgz", + "integrity": "sha512-QnkXtHS6exjHXEQbIK8qXN/8c6jAO6FKrK7917+8E/+0Bl8I18K63yX/CxtONcRuj7qOPfq/s0fIpBO2awczbw==", "license": "MIT", "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", - "@remotion/bundler": "4.0.462", - "@remotion/renderer": "4.0.462", - "@remotion/studio-shared": "4.0.462", + "@remotion/bundler": "4.0.469", + "@remotion/renderer": "4.0.469", + "@remotion/studio-shared": "4.0.469", "memfs": "3.4.3", "open": "8.4.2", "prettier": "3.8.1", "recast": "0.23.11", - "remotion": "4.0.462", + "remotion": "4.0.469", "semver": "7.5.3" } }, "node_modules/@remotion/studio-shared": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/studio-shared/-/studio-shared-4.0.462.tgz", - "integrity": "sha512-j8Q5+E4IWqpKWwSanxGI7+WG1rblpyf9Fb65cUoXmGrC28gq+dMqvPo+od2gSd77hfKZ80Po1u45cdP83B9tNA==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/studio-shared/-/studio-shared-4.0.469.tgz", + "integrity": "sha512-JN4jdfaLNYLo/aV5jPt13A7dheRm3MuF27Y9ON0Gs/VZva9G+nHyz89zUqMYWLaXU3gG5Sq9HkFa/lGMWC+2Ow==", "license": "MIT", "dependencies": { - "remotion": "4.0.462" + "remotion": "4.0.469" } }, "node_modules/@remotion/timeline-utils": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/timeline-utils/-/timeline-utils-4.0.462.tgz", - "integrity": "sha512-xC6ErhwO9Jz6oP+0vfJHJVxEl7ZVTbyJOEbz4BzT1h0Wq4f6d9hH7d8VvmrvZ2IQwb1VaqrkR7URvaW+VfJ14A==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/timeline-utils/-/timeline-utils-4.0.469.tgz", + "integrity": "sha512-Jrl0IUdgljfh64SgOxkFvgMX4UY1nYxDp8Hddrk2R8edIcVUJrMoe2+xLlgFoKwyhyZNE4kHNXnrVlUoSI4d5g==", "license": "MIT", "dependencies": { "mediabunny": "1.45.0" } }, "node_modules/@remotion/web-renderer": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/web-renderer/-/web-renderer-4.0.462.tgz", - "integrity": "sha512-Wj2IIACwNaRWGxc79LKs1vzbIEzhvs63u1rnJwvh+EDuHbhMZBCU7wJGVuSKZifNsKb9k999HiSS43d+j1OhpQ==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/web-renderer/-/web-renderer-4.0.469.tgz", + "integrity": "sha512-6Bgx3zLy4AgQiT2ERQCqiBUatNfQhZ4amod6kIy3Xmc8nUw7m2KtzUXZfy7V+Ln3/yo3cRcBa1ehFSRiNbUfCg==", "license": "UNLICENSED", "dependencies": { "@mediabunny/aac-encoder": "1.45.0", "@mediabunny/flac-encoder": "1.45.0", "@mediabunny/mp3-encoder": "1.45.0", - "@remotion/licensing": "4.0.462", + "@remotion/licensing": "4.0.469", "mediabunny": "1.45.0", - "remotion": "4.0.462" + "remotion": "4.0.469" }, "peerDependencies": { "react": ">=18.0.0", @@ -964,12 +961,12 @@ } }, "node_modules/@remotion/zod-types": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/@remotion/zod-types/-/zod-types-4.0.462.tgz", - "integrity": "sha512-q+wgcvD4AVFg17hPvpklZUU1oUt/A/tK1dTNi1o7NyXZmqic3Ko0iZpW01lEe5AsOW7so4XSWgv89Gs+r/R4dQ==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/@remotion/zod-types/-/zod-types-4.0.469.tgz", + "integrity": "sha512-AfWk/Y4vRepXAsQI41lHwjZyxm0KtNjx04EfTdfvKZq5lcTAEvLcpRlVQhGBazuCY4XXbhsNTSANeOpNAJF2yw==", "license": "MIT", "dependencies": { - "remotion": "4.0.462" + "remotion": "4.0.469" }, "peerDependencies": { "zod": "4.3.6" @@ -1240,9 +1237,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.8.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.8.0.tgz", - "integrity": "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==", + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "license": "MIT", "dependencies": { "undici-types": ">=7.24.0 <7.24.7" @@ -1268,16 +1265,6 @@ "@types/react": "^19.2.0" } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -1518,9 +1505,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.29", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", - "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "version": "2.10.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", + "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -1529,15 +1516,6 @@ "node": ">=6.0.0" } }, - "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==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/browserslist": { "version": "4.28.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", @@ -1571,15 +1549,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -1587,9 +1556,9 @@ "license": "MIT" }, "node_modules/caniuse-lite": { - "version": "1.0.30001792", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", - "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", "funding": [ { "type": "opencollective", @@ -1635,6 +1604,65 @@ "node": ">= 8" } }, + "node_modules/css-loader": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.4.tgz", + "integrity": "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.40", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.6.3" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -1642,23 +1670,6 @@ "dev": true, "license": "MIT" }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -1681,33 +1692,15 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.357", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.357.tgz", - "integrity": "sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g==", + "version": "1.5.364", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz", + "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==", "license": "ISC" }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { - "version": "5.21.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz", - "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -1870,41 +1863,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1927,15 +1885,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -2000,6 +1949,18 @@ "node": ">=10.17.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==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -2071,18 +2032,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -2105,20 +2054,6 @@ "url": "https://opencollective.com/webpack" } }, - "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==", - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -2209,12 +2144,6 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "license": "MIT" }, - "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==", - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", @@ -2240,10 +2169,13 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", - "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", - "license": "MIT" + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/npm-run-path": { "version": "4.0.1", @@ -2257,15 +2189,6 @@ "node": ">=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==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -2307,12 +2230,6 @@ "node": ">=8" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "license": "MIT" - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2320,9 +2237,9 @@ "license": "ISC" }, "node_modules/postcss": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", - "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { "type": "opencollective", @@ -2339,7 +2256,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2347,6 +2264,78 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "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==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "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", @@ -2381,16 +2370,6 @@ "node": ">= 6" } }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2456,9 +2435,9 @@ } }, "node_modules/remotion": { - "version": "4.0.462", - "resolved": "https://registry.npmjs.org/remotion/-/remotion-4.0.462.tgz", - "integrity": "sha512-0bcwIiN7H0IcHtcDlfWHE2ho46RF0VmnVN1fAc26uMkonmAMMhqB+1aogfTE8eiYESEzFokh0lRc0t6pI8wzNA==", + "version": "4.0.469", + "resolved": "https://registry.npmjs.org/remotion/-/remotion-4.0.469.tgz", + "integrity": "sha512-wD8LK3bFfcv44gnj8KLS1R1iGI+n0XGtPvdIiIaGfE+CTX3p2FJYKw2Vc5OfyfdVSACLn3r654XW9VteA9cTIQ==", "license": "SEE LICENSE IN LICENSE.md", "peerDependencies": { "react": ">=16.8.0", @@ -2648,9 +2627,9 @@ } }, "node_modules/terser": { - "version": "5.47.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", - "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -2666,9 +2645,9 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", @@ -2805,6 +2784,12 @@ "browserslist": ">= 4.21.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==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", @@ -2873,9 +2858,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", - "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "license": "MIT", "engines": { "node": ">=10.13.0" @@ -2907,16 +2892,10 @@ "node": ">= 8" } }, - "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==", - "license": "ISC" - }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -2940,16 +2919,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/zod": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", diff --git a/design/video/elsa-readme-video/package.json b/design/video/elsa-readme-video/package.json index e7db66a7e..4962c9d07 100644 --- a/design/video/elsa-readme-video/package.json +++ b/design/video/elsa-readme-video/package.json @@ -9,10 +9,10 @@ "still": "remotion still ElsaReadme ../exports/elsa-workflows-readme-poster.png --frame=36" }, "dependencies": { - "@remotion/cli": "4.0.462", + "@remotion/cli": "4.0.469", "react": "19.2.6", "react-dom": "19.2.6", - "remotion": "4.0.462" + "remotion": "4.0.469" }, "devDependencies": { "@types/react": "19.2.14", diff --git a/design/video/exports/elsa-workflows-readme-poster.png b/design/video/exports/elsa-workflows-readme-poster.png index 07bf7948411cdf2ab9a335251b782528b16f9880..62a5eaa31d856c578ee7b33922247387fa0c7c16 100644 GIT binary patch delta 370325 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
    %6R^@cPERB( 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
    Rs1I6 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≶ntANNXA%S_#SE@ldIrK^Bcpf13>^@GI~AWlr6~jNH8>1IaR#= zfR^N?hkI2;4GF1Wi|cgS;ixzc^&)FD=gcTTcA(GjS6yX&pg4r$as`mHaZ(l8fYfCUI&QgvMjI!dOR}4#T^*S-?A%02ov7M{qzb>n@^xknvzANcy4nDgHo^k zL+0?|qi#vY2Qf<eKz9b9F3z!Zz}RB>Sf!}7FzhNCjhG^=oR3bKcmRJmZA z9yCXrAW9f;)r?l2v4AgVyuhH~Z1xQ)(XPfukj4w=u0XdE+BW(EKws7{`~bOhE{EiL zHrwuDh}iI|>;Fo0uX#LlKk>_#vU@!Y;^I;df?i{3|0^1UE-Ao#3e>Grz$Lu(T$l>? z-!8{Z-20}Q3=I>?2$|0;1WA?VL80BaXP`Y!}K$w7Zx4@_&DcvAQH;hgZ z$qgi=LlK{Sf6w##@A+f@?e*I3`@Zh$I_G>o=Y7xuyV|pPh8mJO7Tn37VExpdKi{dD zZDET3pI)YB!M(;)GjY#zpUgeZn*sO)B}B%n!IpTe&~&CjYfM54%CVB6X&>%`Q7q?ZULTrD_4@kv6s zj`WHXiZ#hEDK@J|KPz_+rkDkMUdLcFA7Yt-Vvm>+sV!x>aWmSEG^x5}+XCMO0m)462f(lQCxP!S3{npBirwZunA zhDH>nI{L=hzvWxtW9T7e5GWq#iYt#qe;CX8t>w5mnu8sg%5LBa6RMz|-hT1=V6JSV z9$8Wq>WcLJgl z)rB!l3^jh}gi7cfX2Z_t<29zU@Nz+6_+A!zVXvhWb4cU-dJI=VeP&~ ztU2qQkj4pEI8ic*JGaNc~eq?Ye5ue1f29ENs6Y|b3> z(??3u{DeK~4~aY5X)H~sXnB}R9K=Hx^Kok>txdnt3Ho!Oc#|kS1?0t%{tMByv?TlE zg1w6Jo8;6WR$0?fMlP*tl(d83>>-YZ-6fVWM)+hAvToEBeFPiA%KPx8t zi-_Su7d8MGHvAYsR71?bdBjOwxN=6?3U>Ltb{%ZeyjzT?g*&h0syRAam7pI}-*P&P z|4~tQAksK!+)=nw%*L+=mSK1rM`G;KL`Zt7{ibBF!p@KH=O}%jS^;k`s+|AQ&w}ws z6Kpbu{%h}LV>}p;yE6!INYdZT$^V%H@T1t0hd(!Q$qy*C)c>;k_x|ulCt{5HjZdT& zkCIMe1Lc*9w7;(0*52xPNAs-Zl_x88v0#cJ2F-X!V7rrYm2%w56Eu>r65BEF%1~c{S*6X#tQ2o` zEApqz$Hmd`)bz}sANM~6$g>+rINh&p>QfzHf22A}OxNP3cp>J82utflX7lxx8}OZxRpKcyS_8T5txY*Vo(kL++|M6CW|nr*R~KT>o=PH=GoFQd>m= z3ddJV#Da=3U4)veOBv_Wpel)Y@@aAl46kD&lXcPL!K*6&PXE`t*zX-MLlvxA8&AUk7RN=tC3r|*hjPpV&U5F{B?epBX^C)6 zFoT&YrkSb#S#|dhG1b(O2H$KM%hp;q)}~1iI)E^T0)}avUlcEygC5MRmgpbde!&y~ z4fK*5*Q$rNFend1c>_#ERsoC8HVNs6@MY#|!5_`R_;;#)fR9+yoDPA@w)(9;20SJ0 z&w7;uZ=U1PpU~80TwUN$;-o3B^3=NQR@=T`K4T&|l8C#bT-iO|%xB^fD7;wP>{{m` zt=mN5&u$u;2EG?tJqn9odl7D3-4ir0Kxw zGEgoN>Q;~2c9me2bP+!*)ZDdQFHQ!Vi!Bm3XS_F4D(qJK!k%#QET!nj?$>!=ASZot zxslRNGZG5ulV;xhXs#^V>usO)b499>ro0@VNs@B4`MLCPZsgZZ5=Y!KVfP62vx++J zSk-`U%MV=30Me`k12G2**Cz*!mA+5E4O;5dlC8=-COwDMR&xxXR%PE5GkZ)sQx%9Q!>bL=UXpYk}g;BBOaOI;Y z^v96xT5fjL_puY29OVt?3-!Y}vn*FN7Sx$KhE~c!qC%8jraqn56#-UsMOb=%QChW2 z&>51rs;7k5E!)ay(IE7b^}pHChnNoX*RztH-8lKs?t3RGT{odd4r8%h*g>^aYuh9jnx>ntv*fP zu*ID-EhffMeVVGAS#O5q_-_Lkk|Z^=J{u1v{@yg~dJQg=o-e5`mhP71|0W&4;v?k9 zug9E8{MX4NIn<$S9^;x8^-@3jn*;yxLWTKC3Ats=cn=#puKevrc`da{ zT=G(?FAvTpqcY~?=#82-6>@pvD)%h5%zmVMRmv)=g@+u?!q>d~NiE>nX^sN4vsKvt zCfVG+lm2I(yf7~LC0cCW4^8y)grP8By?hx7D^t4HBE%r(vlZJ`K_6%pZ4*$tJ*vLf6E~SKcQ7A1D?ar!Q zAd10HQ?u7|3aS;pp)xSwvP++wM#3_8?$P_Hw~m{XiSc__5kQnASz92kJZUmotk^h& zDS~*;b|?l%D5Ew&B?ViQAfumN9kY%_b%y5bKoibU_NHn75csXurT@= zb-M6Ay6~y-w5T#oR}CcmY+KN_Y0^y_2UOOI1^nsmL(qLOxb0EOyThdlMvH+2RQZvt z+%P_*{&ogppk=1b>r<4GvotM`Fih!@#r`g*g1P0()JJi>b#*SCLq|>TL$=)J^x@1x>xyCRuBU_c^r1 zzDiLj%u6@4kU4(HKs!!$R}-PEKOKygkb%CtlV1=jNt=vXyO9y+B5){K1467^%3D;+pHC5m=&$W9nb$PtmwFRO zX|HzPhM5=Fk!yyRWcEHaAaZcQVb=WYe$DU_BE->3>C+q4H%}7{+Z$)^M-RRSD@r_%YBk>9MS4UpLIod%)HqW0%(_O z4~v@TN=u}vkq^Yk=d(cLr-}X0;u$k_2R#guH2Eb&IQ_y2>Bpvb)9XrBm%P>=>pYh! z8KgAQEntgIQHGjZPcK2eu5$C1fAKO+x%v{;Io0CC(!yP0F(fe<#-i~;dE)Mj9rj); zwz27f)gVj@xu-;*N;EuYOmGv65EtWZ+O*i&=FiZ58=+p=w?CBLPXa1(t2ZlhO9>!S zcBz14vg^R-olZmOj0Eb!fDG*1RJNf!JP58A2`dn!Kgd*?$ReOxKa$?DHpyk9hL-wU z9eaE!#$kKc35H!(S|p@(;vpS2vYQ#;Y@EHG3~aO2DTYtO)}AO%Ap9IsGiv7Ibp@Hm z_cMwlOSY3@E8w_s&a2s`-~D)jw!=1AfPME9c3L*goE6V`0Xim?0{n5GHARQ zkdN6G#GZBSj-uqq@Ivj`#X67k++oi$_X^ju=6fRuV2^!I+iSk4;0DXO6hGUweC+;H zGb-mB_((!~TD&1I1}!O&lI}UB>4Tm7WvXOE{hS47FYJme`0m&n=Qg%geWOHCC}TU9 z{DQnoT`J|Ior}1H&$5ilIYsCdP5W?*KG1vTmjy$I*d=Sgvf~F#W5{}Ajv8XOA&5(h zMYZH>9}JT#N9Bq4&qGt%{;4E#(-JgGc5u1YyOACV(+D%F7OA`U`MnRo;lx_QRhO?0 zEK6G~898XjmGzL-h)%tZ?a(G4h=~v<;dLOE!Go*S*`4f&cjAK2}>pi8TXhm9>AEZzj?!^}l);nv3 zZ9~I(98ErLZ*CfLKu9hL4w|=fV8y;60&$Xn;y~S)$#_U)4F+~@1fWFmqZ{BL2R%%z zYxd?onk^?AZ0zIjUjQlAMUwgUCGIXtNcsFd7cez`lj{y})3B z05#zu>spj(`DA)Qv3B!IvFN5p{LPx2EFB4H?q}r!cb|l?Ycfv8HuoD3|5*KWBQ`Kf zD|dcyVFBHI^4f?`A=VSFI!pYeD-N+3^>ugf%u#CG0x7?b4@~Zb52ro{zgmBG8&PAA z;I@Ac08A)G5e=45eky>GyAwC~GUZ#jcFoS_KKJV+a1l&&#kDNf`Vn{Q&@C;OqhQn4 z9CZ*IrMp^WSAXG8^h@`s^7DcI!{hoj`NKsGF(Y0+nlX@U0+0V&p6O4CJD@SWXdj7B zI(C04{V(qi%8+4cahI8iFa8{c~$iYCd02xckeOJUY!l5&{QR6#E>~8M*F|% zzHaT{3k`oOVgiVz*EF2zloHcQZ9CcS?Zjz6qz-HkFU=4s$$PGU;h%xfibhnW)+9w^ zHSvDtTnk6bgAX>6;CKbp`m#vnSNovSTcdY`OGl-_YW69Y+3zFf(#$@)X#)fpfkr1I zt5^R_z_7Wmg95|kO&T4A<=M#(O*BU!1m~!xd8Dw#4!|fm=$5r?@NugmJ7t9$-#yuG zCMf5TWf^t*b18el$#Dl23E64xSvu@&3q3A!)vyv@kJ%WXf6ujusNIcOs980^f*lVr z44Q1Slr<9H0*jc;#9Y8OuL!`NCpSWl68TZCldu%c?JPL~BK)?#ZGia+5XzIpo`Y-r zHBiPgT#B@so!Z;~X=J6{E(=tx-9?rtx^K4*EjMxtNRHxO1XhPX&6w*z*izI8)F^^Q ze@Z8b1(-4u3^%yKTRsE5S^6!16X0T%9S9~21da~Y z5elfMad30WsIg%9Yj(Vi5tCJnY~7fj@N5w!wfr(tF5fq7=_}DLAl5Ykx7!cS$iyS1 z>RV3WU%j{x%syaT zfZ^Tj07e(D@W%lE&k?q0&H*DuV*VW{w#L?YzI?*g5A>BDze#X!niHIGh5Gf(s|qwKxP0hSi2>~ zKZn4?;%5QxpDBlhugvKNnmc@Xj@4j0sci#4Oknt>sd(;=?cKt7_rHFPUf0nwTwT-}1c~oAIg4W9Q>n#gOTHC@OYSRCH2fT5R z5a&?5#XuZu&I$DyB}PFkweR?}HgE|;7%4O|+?1pGzECv7A}rgsI3MRspgzihl2*4u znkX|%!}^w1B-~MC=kG(l4U3%?VJZ(}9T=A%4kW1(PXWAyW-a?@s_nbWZ>6C)>*zsf zrGb=48XZn}`-7W>XBnXq>L7Q~w|${BV}XOgH8fxhiHuGL%I76wU9GjOjm*RNSBaWK zHD*sL*|uRR-@ddH7`)ygQFqLGdoX0w>F~8m{gZyF(T$gkn-_40n`nON?$RY=Ug-{I z+oWwSlA`HopAMlhoHBAXE43!R^G4xFbZY%b8XrU6WnV zCF_J(DJhF`5=cpWlAKU-6xJGwz|Oml4(m{HwUNM$@#;0Rc#$)|LlO~8MlYn>i|kwc zbh-P+ zQVR1`qZ#Rw{oH@6|5zp+4-AJj2=bL%cHqRh3U@dd>kuM4TMuHIq6u5JvH2N6%UTtX ziplF@Ao?W+;K-D#qq?=*pdLD-obND9gPF6!W|7&`LaWPhnoBWm{K>030V( ziaU(Jbo-`etH+fKh{d^zAJ|Y-I=(vKw~ydxOnuDU-@5DT$Xq~;di4$05pi-PV|kv? z<)CiOG+uV1k`R4?rJDOYmR}dsQDi7HTB6an6izYPiBr0n+WEo$x2AKV8HR}D2~%A1 z@}W3xc@YQM2TDUXbEOM%M6PlSKxl8DlbS6BzLCyTvACd@c3$aPmFZ~Nt1H{yE{denz?sF*6+fY@#`vwuM+3|7162~ z6Z-B&p7;uKj&EYInK|-8D-{~UNiF#%brmPOcQ2Ehnl#QqEP+?Dyi_}{4X&mX<;}3A7U;{n1k+(wc+TK*olVhr&Vx25S_+6`z}hH z&v{op1rn+B<7PE$9via;(3pPLpO?~sb09{?7X88vDTgKjTVp>#s@1^vxFyTB(^>{w z|715?Ez^%3USH~;03-xqzrCc(ceZ3ch=$*HBcwyVUqI;{w0iK`Y>|D4W3c`E^URXs zbv8>9pYX$3;TJjCv#PZ6RL@p2XQ1P<49$w7@9l7pc}-62tbEHQNX2&6b+U4)PXJh} zz48yEV>7y^scnsHIi7&-QWjJHA|}JHXXcr)sA_;mAm7;BX986Ct zC*o9+!5v)9^oLN`cUju2J|^>7lpP6Pbd2ywe}3z!CDotLCFyc%H@`VN_e_{jdqX*w z*Btr?=LsCtHD?3N{l$is>ol`XyMb4U;BSrAOhP%ZRSAbhQIz8AqBvWAWEtU5+Au4r zjO1O^x4C+u9KwpO!pHK2WJ8ScNc-H``J$JMHXD1;#9-$4y*jl@3(9=M#@Q{ zn2nAmo9D)O<+ICl-bj8laNeiKs+qFQdiVBQVE-)rOF1zytd^5VN_g7c$cy~@1yO^g z-OxTwO2Ho0yw8o^Lcyui!78b7jN&^EZ!#+1c!!(Hu32d6>Cm_ETA;dSm%rPoUA{d! zbHkwfegHC4V8wq=7mT5=YP)`}W-QTC?bSmo?ZBNrv5!En2u^$*64=A0$}i)@exW+h z^mfCoB%n`bR0nky;*MATDb`O3qnx+?R8+O}cUQ1vdJ#89*W=|M#b!Me1o$eab#EPs z&0epw2J5~7`R*a)&h;CoRSumVsK#0kVB1H-lO}j2ur<;$lo4zf%o_nddfvV>qoUiZpfF^sf{k)F&%wj*nm2g&~_3KvO9lB}C_4aR7>b~1=ISl!v575W= z7pKw%BHUHjX%2RD$`1~M?4;4CItR#5%$CQD&VontN`RB}S{LP}p4LDhpk=zUC$Re- zBS^!p%19a&PC2c7OBdyv%H~{o3Bm+A5o&q$`vP^}8utkuDG&lkY_xa;YP=G%XVVtH zyjja{eaR~kxTo2$Gs8>6%Lr$jzTl$*+sx-%y38EjFz?zKUytiUUWq$)Gxi`I)hLA5A>!B9BojsqUQ>#WISt%SB*HRK z_@i-4_ZqVJ+R}bm;mof#4vXe^yNg?{@6GmM77ah0OAB{11q$NSk{R|=>!{B=i?3rF z0L-4yWD69Zt1iHU`^RRW7byNAfqmwcVbP zVL^+Re`^(vC$O#(NNDj=^}U-^i7l|~-qUonTBTG7cnkwts5IR%SJ>&`cWJOjk2#0I zrXtD;1KN+QX9)~f3UL&z>B+UEoK!_7A>r)u%O4z{$5yyxc~BWRQfave2T1PV)3TAM z5zkg9q$tZ-m`E#VhN~sp-M;@k&A^su-psYi%DBlDo@Q&*9=AF{DNNVKp6j#6*KN0x zOH1IsZEIgt*0=i9c6%FKcN4xLI6XNE+b`9~B<#|zY*#(AbS(}>Zu^AR5MQP}rR${8nepO=o0vCy#IE=7JZ+dRCXrAfw8V5O&U z&;_IKkK%;yzEzz&HNc@<|7{-3%4k$j`LcE`_2zklVVZyh#QB3)HN0cr(%S)c&8WJD zXu1{HH5-78Xz}z0is?EC>uB*$qj{o|W^6FOn($X8Y zEW94*AtnxTmLe&WdF6NE6u)8pu1EbhL6A~!ku^QM2LYQ+CmuUlE8g9tQpA<~?so>Z z^&!uc{G*$8Qydom-XmVwXDS>&^RcKqIwrBVW|ZW$3iu6_e(jIHCXWRduw|0zxRmz` zWc$C84`t~(og??MY6yoYSK?V_g2u8`rhNh^lYYZS?cFZ7t140) zD9rA6(na8WLvh@_ZTKBUb6YvHysBAt!0g{sXOlntxN?G}%Fn2>#o^RuAF#O~e6)sx z+bv7l;gVctW#IC;qJ3)@ONYoxmF74#%{}B%WAq1>54<&EE9}o{F8gOS=-`tlJQiAF zhmqUAzonvW^$qklygOlS>iTt{i#Cm8JLEr0nsZ0Lf=K@L3uA&qg&e9s2jU)*Ak&c}EK{);P6aQNhM!Ic;}7Plg}Lr5W_2 z)m0eSjS$m;{B1NJx@1%+3e-}xr|Vtn$2ggu!1$&X75s`!x3a9f^)*~3CCV*%%`2X2 zy|fdaQK}7ya|Sbi|Eef9{6L9p-0G3NmVvkErM{Zi?qr%W5qI}Fzi!7^_%2y|tr$j0 zrAZi!9qFhoQ)Hm-8%#tllivoqA}fAY3EW_*D*HfABDq7U#n+vnZ$Z z$+-`!J`On+W#rQBL7*2UlL<@*MMa(Bi3$3-?p4%a+_0>S@ALgrEz(~txN^A1Ku_pR z_xtVgKo2;sJLQAZRR)!IHt?X>KvPV_3+dtMDE+W9nusRh6C(IVq@BM9r|eWIJWKM> zK)#VatOOpf&&YP)5jTbdJTuNcLHy#cDW(}~^Uuy@{jC zb&Q#?=oq^X*P`1Q;mEee!(5S40~#)iY*M^bcsrNkt~)F_Er-#Jxy@9Ahw!&ZmvVx^ z*n!isp23oKS+X1B&r(5NxR%qesT+8ww4yy&GHphF1PL&f6(lu&I~sP~K$h?O3C^NC zQ$$<$jd?(ayp=jHjfYjSszTKpA~X=+&yVh^x^{r15|RbmWuY0&jxZ8L&A-(2w--{R zK5;f<#U6pV?}K#%WN(Qo&Dj?;T+Hs?y-O>xLyMu381qx12A=_McI<-t8=S9r6Xnop zcQq(q>znma$gBy{{RlL(l^AUAFk^AK4H;mVp>E{#b+C9YE9u!m*+MubWj_!h-0N}T zc`zg^cZVN+(Pr%X0_Fs2bt2@EiF}T8ty?9{K*02898E{`MP<2p>ur$#S)XNoc)H-# z=CdXkuB7M{r%c|?*pCk#AJb2Fm2jgVPwL=**`(bj5Dhfn1OnEccM2t0Gkmb4bwP;X zJ|_ODIaP&LQDTJmv(}dIN0YaSmAXyX((S%}atas;9~m2seGL=ul&~ToMCCR~5A_uy zTuv}iL?3T`vYaOlrMF6+jQ~7yygXx%St+Q9er22 zTasoVv-YenWR~p!S}yH23s=a~93T8?*TeCWnEOv9xZa9e9i`3N&;ga~IsB(mSSF^~ zgal8SVH(3(LbfH->Q*8PzXdnDy{}$rRyA_08ZHuOjK7VB1n@`J@%9rv=L`; zS0b}<0C6&diS)9nV{HP5^cqJ76Yu;nA$y4m?71tAEia`uQ6ztgOnp{5++lpF?w#%Y8CN?a*y1gorMeb)lJweT;EywI5@Y z;T>wd$m2)oqp+FsAjDqr*I?md!QV+g_z+4$y2pUeWpCm+2+2Md!asViSnvBhNrtMHH5I zxCwH@IEq&m=?gYpo^;6-y9SplA@*ZyA8vqPTtkPz>w6Ik7ak3rx5**XmBfz0n>LA{ zf^rL${{*OLujXg{4QSuC615kvKLjI@6{yT+uZ^pzyWa%UA>j58IHh;%2QV*i$sQ{! zYO8UdUyjT&Fiv@YT2`LxVw;V^jm3GfL}T-uA^ik;T}V|rfUouFfSYzUrm@h>GlPr# z%E!VlihG;~A)3)*cPvmYPX&Bu>bR1dHY6lNu%%Qpx+uz0Bt4{!+|DVLCTP)Fy%)Y` z54Rz*PXnl2egAZ~P`>uT4t7ub^>Z&I%$9+-=`UiUDfJh{D>}i%)G;QHwAey;Ui_NN z5Iv|hHf4IvE`oykjtfGzgVkVLnc=jW^P6QS{0yac%yWCaPp%u#HSZ^FS|!X5FJW?``~`EK(qEp7 z;OSh@zJ2wR*GZw0z#B6oJ+aP8KtGw}B3Jo~8I#6R_`>bJoa>J!*idSs62I-; z%r#p;R=tk{mHwnpzP?Fq!`KD}@xP*(zo)Qmf%XW|XZ&Sy#v8^ikw}Jvl0Q)a;!Y8< zXbS-Q$O8*?_8G;~aekEWj5YkodQ8oFcvGmYYkz_89TgaD0nLk+$bcmR1AVh9pnyp$FbWddo`J-bU(W3$|R=u8hH&3hvmEz zmPz)OBervpQ*=>+76+I2pbhha#$f~9M}m-5LQgbtoDanwyEy>1x4RCUYC={${+kqB zu5iw4L#79~;TBk-s=QP>D9{3b;)&tRO;2=9S_Uo-r#9U&a_-QCOv`q%t^PPol2pWg=<_5PD(Qz;mAxB~ zoqw(08nJP^YW?4(NMmH{DOu#P(wLo!=94VEeEJA>>2l5IXb#$dV&CcjAc**-NCB1q zD=hnndCbQIIsfJ0Q#77fw$o5{hIy1v;`Te!$R+}=J#1ADRkqKuX;hbY9^BmA>eB&Y zkp9C_66KkEXgOXX?2Db)0EqknAi`dSiWU8e*lVLyMVj`_qw}!h2%83Gb5tZLc-QF4 z!n`>0#yTpf9Nxa;=b;+ng`i}qFXPo^quaOZGYHB>$1DIY{MzuxWyE=`PU@)nrXmjE&5?!K4qy%vYX#nh1u*A^e-&M)>16huD#U2q6X`}d z>fra;TAEw~&CXrxH=eVTP5hX1t>~xgs-h1m1s^?wMX5gZVit`h%o*8P-`G}itJz=?lZ$fehS@8)6t)8 z>?$vCcT*1-ow2Wdt#@Ex;uxqx6^ex|ahM5(DcS`wzAPrl>2)J=aeEY{_8c7<_2%Hh|Y4j=3Q{hvm;^DrWu}h7c}uj@(wO0mNWRk zD$y}9i5#&>XE1<<#?gM-n7}Z4evQOE0D8d$q>q|T5`G|KD!@pqDKnv+-K%xPR6EBP8}zN z^iRZw`uTXG*E5!W)#C~kpkON3c#g22Xi=VeraC~TAWP+4oyNx0{5|#g{pLEt<`@oB z_xHP~1NL)>3^_Hh+FcrqB2YM?&<~wZG%T>XO{oVLgWR{#D{VqGQvN?G2FFSoHOuopyW4Pz#uS-l| zKl536x%aK!LCZN+wC86VJZ^vR-{r~N=} ziW@JXqmj|;jGL~K{?Uu{38D|>YqS>T_pARS)4~*uIFv1)cn0=|bY2)m|2||09Ii|s z3kPC-G!|hk7XRNAnUuinrT9!~n@{qQSK@cysNU7FA}Yb;W-rWEyr0NoFX~te@1V8# z8Q4Fu8kB5yYxM>oM)8-!|L-wrKmq%({9dI;tsX=E>sp2{Yyix0{1Asqn$%>0!=`?) zQoGNhCiqpttK;Lb?LsU#Hv^J1#YK>JQOlI!J#r?3A@ww|g8L6|+Bxsj=mZW@Kbxz^ z3m2e*6QchL@)d?5vV6@+U2q+(&yL>xOm5t{0u1U&oPGEl=#`cppk(b`Dpc^wTcq8A zMFdD`(eY}h!MvxhG%7aw+czT#&+NCfPo-fO4J@wS@^`n?x(D}mc~#fzx}<}@#2;6` z5c5$F>_lB|lBBQdt4CB9OsH%*I`geBjqALYCO5$yRKcU7i{U7^Z@Dn&%eqfqJ7%)!j4U!BuuK7g{t!S#E&q`#*99DpnCpTTf@W?k;@D~Xt#co?UKbynPO^UIU`twJ`=UJ6 zq}xBn2zi;5NQEU-H2CTPE9iyZH_KeC;d{ z|2mE%6`rS5-OiMJkKGV6Kbh@{%!GZ(jiGvMEZk0O`4=wjz7?MqR2$c|qx`P4T)~Iu zY{Fx=>Qh{SE3)VGwziyqWbRF%zr$>aMq~?t^Ufq!Ie!LQZnPlh>`6yJ(1p@`6dldK z;Y1tK`1xk*?8YKWLeIbCFOL2OdyxAIM3MgL0LMfOU;@CRc8*vQGcSmr?=Kj5z%Dc{ zYofAW;LSyI=nz|?b$V_6-D8hS>s9&ob}Ch23n+XmYsysfL{T93`ol!R%j|P-|DSQO zU$;u~{+o1msg(NdDD_M%JJzKNj|<~xO?!c+PK`b;^pR=PI0W^~CC)Ysvyiq3Dy&_y zDJ#g*j+Zu$50@~L-(7=jVG0VJ%^S2@a8T{)A=Et z*|mFg495hJrUpXea@lK@-+2R{$@x#em=9SXhfLBRK^%t5wEliKyZXeB{1{wYRaHOI ziYD1h*ioUq(ju&rtgJIQp7rPmwg7M;-ipue1*08%nP*1@k`%4yT1AjUv@3S(|540xkQAjGs}od&L~i2 zP6(~aj5o7jBFqFnFq?{hyH}Yy zF}+>2c^Hlv6ohR_ib5hUR}bWzln?~wn_LH22fJAv=V zU;59nry`^^q%0^Anv>ej*0oM6^_#8Wt){0=a6gOQu>hWg>FG%bOAQL{G|r3Zfg5Nr<&L|dMFCK zti;?T=(1Oto|-&1%znZARQ~a|Y%k`g?l6d{AFLG66Ge z^)AE88}%J{1B_^QB$8l3=$|S5f3&%p&sN5>aJeo65RB&!3i@AKHMVhj1SG*vZdSgw zaGo_Oc;FC;l+$iTVj>Cn>t-lN$t)%1{Lj1qD+VO8ar=eJ| zXTH~2ZpUFfA+px&iXkCTq z5r#6cU0Ge#O$-v5DSe&OE7j$(jQAC(uRn%Zn8$J)F49Z~^$&T_mP1BLI4@L03O>n_ zB-(^+pKPuMIxHa43-+S|__)G}_JUv$t4an=mlpk%Di#p#{23j`9fx6j6}0F;htDUL zYJiWr+C!X{__}S1#>aLQw2f|Rf|joU@6Z8?rEE-^N;tyTZS|A5gjYIP4bT_Fl5)YU zcIXQ?R{I)aups%lkc12;}-6Ez> z5wA(IX;m`vK0~c91lG1>naUXE4VxkaXy2_UO3>bo^mp&XTM_(tqwDYcUEsBDaAd6I zw7*{uplSX)M^m%tt`3IKhwVO7ty{^pj=RTNNkgIx?WLHM7l(%LFf0hK-}kWZd|LQJ zRJk%|FiA&HRT2Kw`$U>*FOCFenSqM*!}C-9iZv6kpJ>7biRtLwXH*ycQojF=nV8&O zShS_lOW@y%1`BiWPUFDwu=XSB?tekgv&=MX81Axw2Z1{QGOCc3B#+l+5+XlQF-%jm z`Co;WeyO{0yb&nlgYDU+MI;sw>~$v6eI7++J0E|yJ3T3?LtT$kl2;*pL7%TTtTHhBx!-GB zfYyDdEGqWpZ#8V6s3tRAUTUqjz|>bNul@GR?#JEB`o3<%ugCosVTZw~s-B?{dv09+ z@?P>+0&CuL{`UMhRpDmm#A4`9?T74GHu!PWlVV>BTaB`C2})jThFOnXSSUm z1Vk}9{8j~%VQ{oBz&yL+)!NqN(VXt;nb|#T2&hmU!u)xgu<@e4dk&tzewnErxLdl? zoz(i_o5+i+<*w^(*s4H}&*I7^ToJXNfeP-1TAv_)x^0Z6zbwFvHil-Iw+$S>NdaDC zehRnJH(r$Ro#L5(l^?i?*RhrIQxmj5b^JoTpu6D8_wVCMJQ&CH^zdu5SDinnGS!A^ z=EJmtl2@eHoxylXD8CVmel0|VHjw+%7k`ljl1{`WwamxZP#AtUI_H`{~ZN}_zpoQH`@ zjq6`ttLh*05n1xQ2w$ZTCN#f`juzNgM6fVv3&!>XBx3cS9CGOw#;d3jwlS-11CCL% zhhl!YvarS9@D<)})c7+V!51~RuJ83DEt@LL17qxSU3lq)DOt@Rj%3!7%GW7fq0w7V z@*hwq8K>8#fJEx#(jvn6CM?RrN_ycJA0S>0jP6YE*wv|kQ4I{GxR_}VV8hWlaOpz; zt3`F5Td0baBlN&w+(13SKV4_Q=-I=&ty?9A>-#R~#uaILh6?SqqCD}b|myVLpD zr4rCI^S$K!DpTh5FVJXm`5pDD7$rDko2X-_1{-h&e2bqO0*#xHN{j{6!>3@XqMik) z$m%HfssBUQdB?*MzU@9uL>Ik_AbJTAyDTDl$%1E(GJ)5iKx@kQvo}69Q)j*9 z;Vl>vfkAiOudJhPh!x@QoO&kE^?1+X-M~t~>dUrxX`!F7sj3PPC(F30^ibGbW5&_l z#sB9o_QR|Iy5FsHsG77980mvB$e8U)*pOn_r{Ch8|MfBVj62xAGziSA`5N zLTz&oFV+f#FnPyqqH;fqj$&Urbx|lmK2B_w_s_`4Ybw}MtuT&AOD`8cuu0S(Z+2`3 zU|(0I{~-LuttP)d`<^~&lo6_y74gB-KyN}bOKtiE_JmnDk3=d25f?-*`PsM6@%3i< zm{=Cj0$NKBIHa6d#hT@a=+oV9cp+WqYMCJ`$!U%bG^1CK*rAgW7JPtqD&n78GIFkI zEFRdJlECR%Y`?H>Su*76GjAAh{z9J%G*Y$N-$m_~l@H-LA0R?Y#ufT`80~vHG(ze< z!bgfz9*s8VzkzjbNEyKeqm3FxvPZslW}Uh(j8kRgX0sk6>X26T3i-sjGP^DhPF?7- zWG(6eMj7JK#5ie5Vc{D(=-YBF_L`>AP`K zP0|@Rn9ALAmWT;i_cF<~$AJA20`E3~&LW;4h}f6Nz#Azj-P-7r=zrT_r-8r=ehWK9+J77dXlE)f8 zn+C;UEebO)kvOC?AY8sw*;-@kr|90iis#_hSr~3><*m?{|L?`602qFqLDBPtg@U#N zrrD88nmufjY^KGviv1yT@Oo;NcIFMIGBM=lC%r3ZK}moUq8X=Yk7cz?{u&Dlo%^yW zzboR8sMQbk&4nyeTEI(PT*hiFDTnyRO`*QsGOh2Ly{?@XxYccqH(NK~zsDKPI^+Z` zC9{po7wxCBS{{*C=<8-B$zVuH#n=k@Yj8PhA89EeD57upXY)azhS>)Jw4+jYJ722N z*6AVRlmTuh+q9J6P&&vrf+Nyh0lZTxB`uy%?dN#JX#=U1mdXNggYM_p4_>ZlU ztq=0fcC7|4r)5>VbQ|AchxVs=;Kg6|7n%`yDID|9<2~xdWhLsxULk#(Jt>eSUIELz9wZ$0bjl!r z3qRmF!>Z?Hs0UV4Y1Xhen3qUAWumHK5L`}oH}Zt+o3L4pdt&i+Mok>`Li!iiSNx@@ zV*Gz5I)+o!Te8;oducXt(UN@f(QgVZ+F#NTDO}sjbD(6jN!rXTDX_WiOiXJWq@#<` zCXdCi2BlRTJ@vPZc<{H^rh8gO1mb~v`bHafLUXy-o`?q2JLxJiAJTsaKJe_jACY_C z^2D}sDf{H(ZG|L=LH;mg_v>aJsA z5n_U&%C&04x}l|Y-s7*p*SOl5$;j{Qt=+x4*Yq>0%;P(-Vt7}`2VTYVmm-gz*!k8w ztbG0RC98n6_gEQ3#@IPk7C|x_)8X!V$(xW&S8EOOdFyy{5f^_GEJ7^EC_H>It)=N- z7S&Gw!jnNu-R$qH}bDiXoMoq z(LzIKzABUjjVCbE*E8+k%^%061S+mzWo_u6Y-f{~0&gMresghBO-X}9z8GJaOQ zXggChed|`QkQ|VAMj5AtLJKK6jpt}&liZ;ju(Um8C{$IK{xrJ8VU;j3dv#kmw(PYW z#~+BAFdGZad{)@}D4rPn7Vs)E(Ml`mnpoR#H>*^#<56JnN> zSI=WD6+8Ihi&JTlLOa@jtkms{rT1Ge8RSZ~^?OSGstu4&6G_FrZB5OmqJI8)Leyta z=(d4HKriz*q{H_2_rFiy)u|tFQdVeQGg%fC)%3UAd=*T0mK5TPf4Jx!_39>;FQd9D zZTH!$36PID(I(+{&DL$Kd{kL(JjSJODh1*B8!XamI6!*{>n|L`8jy~++_XOU3X&F1 zx7?aJ7n*SzJ4pP8;yEU+PK=FL9Tu0_R|Lv zrh+5QQ*HrS!#aD+3qBj-z6vAN{9#BRIv;_W53|xSGwSHH-6I3m^rxT%2Ul>dj@G2y z=1wj{?)OX@@(7(k#V-LLW|#!MvJiUB6Pa(}VOza`f6tbs@YtUu@vJZ}6F-t-+oNnz zq|j60wsi{yUBW=2ZiEmOmK)^J7Hi+Rv8Ugtnb`OWVfs^tO5cyeFx6tMTZB!qR}rJz z*Vc|TWWg36W&OD)!75kY_|nsiE%VVrc>WF_1uCcdWv|15#JoMjR|736F(ci3-w|(= zIg|x}NlE>8%CY_zZToyL_2TiCw!WU;PVC}lRWXw#W6ns9XMH*C&*fl)~U(Ml?5;02Pv`Yk#Xe>LbcMyVy$bZ)&MEd0eGPY0uRU|Spi7B> zhyuw{A{6KJ{>W}EXZ0^wE3Lp+O>@Ytq3b2i5<^tX#cJ5Q7VwaDqXu|(=}b1o|Hzn_ zfbz6xX6?PE)DK5Dl2m<8!u~%RX4hO@)F)tGhI07R_SVDy5i!BC=R}9J?N4Qp%&7+i zO^kGNYN#juDl1fJsDTUbxQ-5g_`f8~pD#F5t6PrZ4S#QRtWwgCHZT!|X@h~CoDMwu z19x+cFW7nJ!+KKdFc{4?nLvrL>Gu^fE3`>EIz|WXZ0F(*aJ99+gnv6Qd2;jU`=uJ0 zhPaDQxfNuH-SQe-SWb2pp|;>7L@w}`#`&60E@HIVsscz;I2~Ju|h-?_<->elhYHIyMJ+!`y@5S+!MMt2;e*ME7LKbMy|}aeTx@V0k|( zl!A}mp{!0RqeuLf9YFQWAWtGGHY#n8D4IuGG5KT$o#^QD)eXBXeS9Pr`vn_h>L?Ka zi&c3ZF6!Tw_85C98ZUuYoHqRIqo|_fCcAL^y0mw5kMaaUotykKajyKbsmzAbvx!Jo z$asN-5WKBUGT_-EePV`3?vIxLw|b+5BhEO^2VgNCw0?X<0k2k1(C|>sVb4o zpVpSvvg;HLZ)kTVtE!Mil6|qB(Dr#0UitXpz*l9Vx}or1>;sSQLOxpLgWcu>m~PY) ztM^PR&rlzu^4>V5NH9xj@!SjNZ{n+yD{FF!M^khGn1Q0f%N30t)Kx>z9&mQpQCOvg zFxrI)!^lQv)*CNP#*JAg=eM>rc#VHL^5OMKYXx3^>gQLG9Z#2-?C+u`l4CiI~`*IAC>9`ps+`5?ixzi9+^Z@(vI=VQbeg z@5aOOdX;p5rBv-D3QiFuMq*wNt8pRm9Z!&$sqw*0(W4VLu`AfaN&ND`$YZ}`cAAcn{)@%pN6ya(fp6Iz7ZK0;l%$|;F;wJv3SDqUWW_JJ0!RUaogtd&*ja_a{?r<;~KUGP|Dk{ z!3q41VfeQxJOPgYNW%^nH}vYAh;Lzx<{!ZVso(=0D^(Mj*bosd`K@agadpox&aJk z3fKGSs3!bUl#nv$fyeqos(P|y`7eVa|DYkO=9989J;(TCJU;j2`cuLm%pcQDe;*K^ z#um@wqK%T0jc*4qagGNwD`kXWfLYAm-l3=6!bD+ajYS&*FZeAt z%krl2BitV8#W~}p|JEWv{9Z*t>CW9_M}nU4?5Y2Ey*>irUEkR;(a3d6?-vIAJlXMD z_0PX|?N}NL#7=u0>Lv>qb&gEiO}HFRO&5~_i{6WUCy<4>Fr0X@`pw8Mg%dVIF8&@_}~O?BQ|2 z__OAqQtw0#B|Q*0>&~&|z;VOs;^^T1G4A~Q9H+J)iX{$^oS6XJp3c!;o=3c(l4Xb6 zAC9twymkh~b(=+<=)F|#3&y42iNnm>vNjrnmyB0~SCz0HFo{1ypBgUCN8d$V5Z;aP zAK?rURhJh9!N6oldq?|LP${DesrJh7LF*~aY41W}2 z4qyduKY0o}eLR>+@zVntQBxyfIihyq(HEQt|AguSSiKZeP6)3rLNiYBao&nRo)#|3 zfK)m-(tIM=cG*`^7eWBxBQ9g zltV9I7B27n&ul;{EILe@f0t>A@*@Wj2p!GA#&b`|hEzx1zw-zbO4ir&KkIpg+F8=3 z*QNBz+%tBtR2MT?-_VyyZt&+%5Yro3k1Qju{?*U8)v%k}|9xxXt=Y8gd0IlQ5ip9Q`joR7Y2ho7E*Iyc$`-p%O z$f0L&a5EgjkQZ;`m12L~c^)CKG3p?!;JGoR6|zE#PHJxA0!1dQyIo94s}uO-X7#`Y zn_*hpZ#dMyo=k>&J^~fJyTh@w4OM#g3xo(3L5fcByxvZyp$N`gtfZp__ngNTz6`+e ztVYmSfUHCdeQ#-;z6IEJdL+-fxHu4W^B7Rq6N&2Bq=$;#TWTJPlrGf}Q;*a9LDDfa z&T!suHzRh}Gi4_!$9tV^J5B!g5|6KZ50hdvH{xsIX(Dx)(AssbuE^J*_z6z9$2@6E6AQoi39S1)Qf{UGMrbm?Z&mptL!U6#VTgkS%4|&KD!6pj+}0hJ^N$J zOJSrWbc(TdTejKMJ-&y&N%1|!G;uvFJ)}!ZD{MW4E!Rni?D+E>FK{UVidVUxk^v|z9I z!h*)`@N@kl17v@rdKfwi8cz*LBKaJ+r2l#iH*DR@XZgt5ecu>?AKSy(%9+MPlKY< zpB_6S2o7C!bWuO-;V);KIU~>-Gx$o(tLE)DZy$@MMY`~k2Hl##kj){zm+f2*M?O}> z7L>b@DFn)&W$8D?1gb$iUK=L~QidJBa3nS9vu*x-NDs%|yGW^f%iPB-1 zTcNMy4}EY}CS!4O7Y?;z%k||{O+;Kfsm8S~iu@2_LHd{p>dh?cI13-7X0xI>8@tLK z8D3Fc`-Eq(t89e`6EEoZfN`>^4*P&MZMmrdE{0B?xMd#h2`5-e0ufD?xPn<0^ zy?_)87EH}M*C+XsR*|-rayaTPvl2@MM0@b#PKkN@*zjXT{#S#D+H&l&WE0CXj$YD@ zIBJ`to@Lv>*szFO?vivH_dD+gX7IYm zV~XE`)#SySVzy2x1iH4GU=Ks&xNHt5w_vfCzOkess4l%y z0fa%`mgust1p&ZPf{Y*2q94VZLVyB?={c2?wzR%nBJ@(Kd|%UgcUWlXwl(QEF`vT) zjv(q=@1S!tmf(WlaI|~+Nj=p9T3|p}QSpNd&QqeAP!EkMML0hC4jJuwvUs`$3+geP z?birY3`jo&I1;kH;L8hNoOSD!uHHw_)C5iI_4B$tQ{qf0rKeTOm?VP%gL+oeTkp1j zjZ*q!gzJcAK|ikyVySr1M>XC7(*L+`1&o9)i7cR3g^-g6nPpH3@c3xmL1Js&;k=tp z#!oXA=Iv|0PESD_7G{LPa!@#Tj>~oEGUbm0UPArm{^VAA9+aC~kh_$4F643*J87yl z(39PIA523~oci&lu>fRTasMS@6=n&-ap^5{cd2=xub?!S%24}e9$@WX{ajDWV)FdX zw(2LB*Iwv(EuCVNxJ!8lp{0{a)8YhJ&p{B!u;DGGU<6cS;qvkYV!xaIFY$uvzcIAY zev_BzN5}&%z+BKOASf}liyOAYt*^&^8OaWZge;jK9C-n9TnSYird*~s|D6*A4hBNT zmjck317Epdjtcrytm+@%X!*k}hxJlJ6Mwm20`4vLRC#Rx|8_Z#{{4{G-Dxs~{@WK` z5V~`$F98(H;Ihy|Y91e%z_IE(qIb?sp|sC_g?L#&oCzG42xw;4N za$kabSwkR%Jo=bprN{$}*Jz&L2FE((GT#r<3^_$8x4bo-kn~5VMDs_Fmkv~qV34<^ zGYO6$#!C=!7#bdJEGY>baw|z)nfEcs2i^p?t(H=HuxDkz8C6oGj(r)jVsQN6>TSAp zgEQU)Z#fdB&{9Lm*T@M}9<<-^dm8tFEgmGLJe4r%wmR0c>^sD=)}pvB5Zgal2B9EU zd78J`-f-)!%OROUAW8cX+#gC&{geIic}v8jFD)m%@HzwCXDA@ZhsdQtHw-O+YVhI# zr7I0=WJln8pAz(?W-d3Q!cF)?Xen>Cno_aC`T+vUj)dyLOTctst^@%#7=$xHW3#LP zln8D@Kp)Y_<#u0!IrTJlm&=Y49$za>nCw6Byr$RBsHDgg0?HkWM{vJ5;7zCv2w7eu z4z|yb(uCEhD7^~rQ&3kzDL`*VXj(Zqx_X&^(xc%65u{MM_niR4=*gdd{Xjp>r35{H zo%-h_P5S%*G#g2S>NgDZBTPYH-%q#lR=4sF0Y{n|xp3su_(31yNP=YbuSOkn!3DT2 z@PZd!a!6<-;K^OK<12Tt#-Z20N_rV!w0rrU^ z8b>`*Oa_GaAp}ruTL0v-CkN^NDhq!DXM8Lx$%yoPyne9A%C|DgM=746NjlNgn_uNyQQmJvu8<0r4Gx>ogRwLA=^LCe`j=D ziHYdO^w{DQc3+2hi|bv8{AQk)Ki@-?56p#tjK$^&?ay1hUj=A*JSBj*1u~w{WQ0!b z#I~=Fu&7pd@Y6qf?;r+1=*EVZT@-Zi&-$)cvQ zyrO?qMSyFA{CTp^Y9XZ0Q0`ltA%<<#>f@;Ap8zUZs)VPRiAt!o%e7m7^tpItek3n3 zU5aKqu}L#!RBoUi>sL8s`rdKPQXu!0E8mwK5RG}R|Db>A+ZbT+8b|nACG?Eo{vts` zJ)f38LIT7;Ik0*f`Maw_ODHL|5JvF4Rv(`7(Hf3y_;SY+4V<%?e;AXUVw@lP zsXTT&kB*9Zk$o4C)_lB=q@enxV83za%0)n;&w-?=LQxe&&HEJ*QsAUAaY2gypqSdx zmN58NG}2k@MB!C~UEokFQuP~ljSQn`J9XSHDHGzmR+jVkFhAuf?E7HnN~=JmM0@M? z)`7uJ^^I^FuaaaF7_F>T6|;Ix^LxcZkRirVZ-`M4%J&vnnPNe!lGTaRRe@q8KrY)a z){$7oOu>L!-CAV<3}c3x5QbCW*{(PKQr-nb`h%jjey}aeWiV)30$xu<2t-M}!^T;K zN{mx*)m`d`q+S|oGtZ#RS#k-civ9s!4^v$O2cQa~NW^G(q$&T8=RHKHfT#0G+N#sZ z9r$~wIKXAE$+PD-5vqSk-uTeSODmK0rn9I|6we3mN>wrGXt#Ss+hmPd&Ig(%7QTFQ z_LU_JKiQf^Ek~p*Uph-Yen{QdXP4ueaAR32eT`1+0V0XnPiIHU{OKbpNfa!i)9a}O zS$CS%J6(CD*V=2@)ZWQ82jz}=Y7rBw)~D836HNfmk{HC(n5ja=8p&|;{*Y(CmTwll>Sdm!4t5yT z_mC#qO7pX4xkX{wUOKUi3uZ>%poc2lfp>0rd@Qk2m$_sdY=dV@ydP3-5RsDjk7q+0 z_&=r%rTkecegOw#jyBI)+)}w^;m%sgf0^cYU)S@`Uyx)CTSG?6`i(JxM(|Ldn^``F z*?Y$u;mr~i#EgtC)h|I1+9v65E1Vd$7XFDcR~rqVI74~bjQ!C(FMdjcz9g&rR)?%s zx|6nK^R(rV?MJ|_=`@h;8kqX9;Z!XZCo4*^x8B~aA|=wSMoiF`3wY?@Oc>i&b~4Qx zicPXH^JQu_%?F*v#}U$ZILh&<-%3gE-~O_$Z$Kjf-=y+0Mu8j1UR>M|z&W2CK9H~^ zDqO{$Wqb(I8+v0KK7tj)UvQ`gHE{h8Md`!uC|lI%eNipSbbwY7Qg-uV%Sg4AgiD7H;0;rmExr{*YCvbZf+%aIM%9_WnaOBJ{_ICb!y2+GNsu zoq4)8K3-uq_A7K!N=eWHgMyKrT7{tj|Lf6@scO{}Ml1!hfb6bla_Bu@+SkhRh!I1# zu6f@10JM|(bKs`56z+FZ%w8fWu-t89K5Io;x5tJ2v_r*N?e9=hxhwAr0ipMQqk`dwpG1=qs$Sw}6jD z2ItRr4;*n~yPY8WfvGjo9OA@a#afa_YM4;4e*Q%F9^%lDGjJ&R+vbNC4%4LL8%vwL zIf8X>fLOK?s-~c6CmJ1&Ve)qQ`pAP7DJAR%> z2-DxEe9JS;74#X!KNJgH4Q6(VjvwL&G9x4SaC#_cG58M3ki4cUvu}7_UD-2aF3G%v zDfU~IQ?zN@e#NgK)onK3juTC(UZEuQdIP?g2-10xDp{#PKFhzvW`#r%&3SM0Y0yqg z$Gfz;WUKn~|M)U0iTMn?EI(s*f9UIWmERCz1nCarKWg{?*fM~mPIEA;$?iAe8xdCI zxy6(=GcGBnZyZ?cpiQ-oPwO{lwC`AjND5wF)k@R%2_5z6ur)~4G8wn_dVCu8`mlaV zW*_Ola5B&1^HQ6bqDfn#Y(YLK&upls($QFe2=~T!9Gg7U<>z$5VuK1BaY6x{I`w$= zqFAw(>8J@gZQwa=VuN?mf0Mc!gLYH>5jC6MeYnn13%-pzXVH6$9XT2koEfTITALO> zMB4j&s`N)LV=*nO2E+-cyvJv;fQ8=54@WD*7%q9V{M(VLMbBcf06}Tn8@+=U6**gK zdNs`j^fJh_nq$=t?5CQ5gJvERSYoSWVPuLtfFMY>`u7J)NY{`itJxQy z-1MIm;mZ)BRc@a+8ZtGMfbi41@E&|-FKZvYY_yK?h@&MH6 zmA==c0}or{%NEs9X!BsDH)>BwXW9v{Fl}JB*6w_}=I{uVV9wxez^3ORS4GOmzn4DX zDO*!+gfM5aDtk9_(5Xeba@ACP8loKAOBJEfdKfiiN}pL!^=vdtRxZ5ofiQ4U!L@n= z<=Iuo1HEY~IoI9l6R9&a767Qa9jyw;Yr?0^qa&)+neBMoSbr*0|MHOY4^ilBS1^ph|tk^g7{o(GiA6dhjz2ou$VN>;Lc?XsD)5~RL zgbweGmo&Inkm!o?7tS-8oAKX_Qq0HxFZabx15%ss9^Ff4^=dHkU{>3uaj!Yqah#|m zQmOGWg>9p7dd^AC zgvW0v-I0Q5`gjhs6MAQ7L{xCEX-c0~cJ|^AasQs5NyTSAtigxW>V>;Hyl!dy<>B}T zS9s1)r`CksdGp*_ivp9=2$HAW{Ri;Y#x+kaqtu6$@6_0f$5c;T9|ya5jh~7(uNq1< zUNe=nte>K_)_;CWA}jLOko5bm$9DT`-Cu6)G76FZ%|e)B3Gc%YmUgEa!t!cLFs}BS&6KcG{&ty@0It$gLc8e@$DTldGj4__37OuOp)RMR7W# zHJaqxNrTiRq!|c7hh}xMj3}SoCev!EIm^gS{mpJ=8=06k?0`BJ^=b2=c9VX$4Bqg< z?jlp^nofD*3zeC$_?=_hJ|Yhzg2l#5UL~r}5OI-~Aw~Z3F2n75kFjYM<8PfJNMJT6 zB`f`_Y>DX{7x6*;&NGp2$6WzlWeOn6$29i2N2=Pi7I&FCHx_6Iq=n@iF zsjgg`vwFYqCR|3BzGW-xBw6017kDepL2kHpQ_aIO`$gkChgzSgX-hV>TW>rV>?ys8_+BE(v(L)I_OqPl?yK6`=iOWW z*19Jf$~s0CwAUC{i@MvU)n?SR%!`Kwjgs>ma`dulY~X^UBQc%&&qD=An<;t^lHTr2 zKCM=<@-b!{B-4F1E%Z_MHZ|}q^tA^0n&r*b6k1u*AMCM#_FWiFKYA|5P`2ZUKr9^7 zntU?vX(-~piY6)RvQA|e*N#D})gKauTD^BbIWDoq|4JvH*>K=z4?&0 z#IY#@3exjZ3sSi7buvVq2RNV|WGJ2eTi&VVwx?FH3a&6Be3)@NInN7 zmUSv%{R-+s`m?=CMk2X?hR4Z1T^t7R@sroL>TmZg``kch1GTqelMGEUtU{0 z0+Z0(>u~LrCVMNtK&}augh#Mm!@LL(Jd8R(De zo^a(rLr0(|&*82=Z|2VjP7BYtdSkf6)v3$Uh*+`Ehfrzl+TN=4CQCC3(p2iRNnZV7 zmCr|Pk=5hu=#M*ksPQM%Nxz45^b06@s`g1$*I0^GErom=z zGD_Vj+T_|J0Y|C4ixexn11}2C*}UGrtwMR)6B#N_xJ0IOov=7tpNicrgwJ{xkozMZ zp@8CNkt?yaGEKMYV}7M`Q-4b5=VIkZ{!nzP{Crn%$aXH1kM#G1G7CubXyXqkvu}2s zl{|oBNO8&g3trj!xotaO#-JA?x%p}J+`RMI8(F~1orU|}_=uKX3y4bF=WM*zH!0$L%5r)b1lu343O!-_4GFsP_o^fySHKH<_c=A0#0%Y00DL^JN8uZo=)~ z-2J&C@+G#&ZZmrDn8HQD*>ngmB5=InMs2-uV|>vb^5P~^$$qw_M`epLae zfPS|6*yk5YJj7+GWNa(wFB`&i!C0*_g}nJ9I(88H#3(tSy#0w;52s*|0KeAzE{I=ZzzO%RE^i&riwX8}{@SrWw4eH;ZOvJJ zRMaOFv}n6qCOuTqkyiQv!ZxT?4+eY`u-i zd_P@h)I#sJ{u$=uS}!ruZt@vI!{SFwJ;E!Z%eR4-6Ntb9^Rtm)At>X2aNhkyocGmH z*-Q+}tEP9@^v1h%dLPox?>9d!hu(`_fN=gbMNmRtf|_&g;5%1j#26b1}uVg@vM@$~Ma>}Y{t+!U|D@O%x} zZhWhER8(J(Q%SS_zG~DpW1hOYNx|DAo`vr)S@Djy5m(3@Cr6V6^@deh=@y^G4u8eY ze;#>ZarXK2;t{2CanBz>rp#6H@iL4>d?HPtZAhD@_4YjCz`i&>`EOd1Zd9wjsx5nM zd7RF-4>tr3>FAlM^sp%(-oeczV8a!3$iXN91o`SRf<^yf+h+Mw`7?#*+t_Cha5yG<={ZAE;Y@} zI_F1ELsVXixJ+U-IqA~gr-NaySSQU|@_4P)-x~Ek&kZ;fEQB1cnP`wnt;jh4ZWCrv z?(;6`HX+vvJEQ~Brc|{&BV+H*HmPoX756P6*Y48zl6LvVo)wqvvn{i?zTEGy-mqT& zyemNFP+Ri>;%|4jJPDJ(SI1hLWwZQRhnX#`m_p-DTmPY|+3|+yNWH8|hU59Myc%&n z&f2yE`^9XHUlGYQ<)|p6bEfcSB@+ULjoe9sKQ`muVz~m8l)EAvu^&Y(&diEo971|V zLin~%N&9cSib`J<~uT}+30PY)Ug zq%zMJU*66F+Q1jsrO5RF-fu* zUQ@g*AC`S#+-7{f0X!H+ta23~O5pEfMu8nX9?{b^YdwTYEoj7L(kqCbsns!)mk~?}9bF9C_Au)CMHMZ6a~U zp&d$*-Npe=iR9YipZhn`<|ysIO4`lyn#Iph#UZz3+oufAI1_@WV=$!yhHtG0{^b>> z@yR*cB||=HLrv^^fdGLzMs87a+6_)M4q$xm9DM{ zWVd!oEY?X2M&FHE?AH_G0-lJ2n+)k3uZ8VtHkmzOAMbg3>y`wSaGGw&k5Qk7h}J07 zldpZew}SP)lmacdJh{Es`y$WuLg+%zoDH{j4O3 zRTRyp@SWbTlY8EA0S2hsGu$$2>TPV3D-%_HUcE=wK&k@xfum&%GBF^E^0jj5T#oG}-)w!du^)aLS7 z-b*>k$>;{I(#CIXA~*oU2WPUbRK;rk2c-kEPdpR{tH;fzJkx4X{PD2pw&i!}J*;<0 z>R8B}J1v{vNcvr;Cc2-Kafks`e#U=?g)s063yhDxJ2{)8>OZgg^N*9+bvXuyU*_^( zShs|jZ=>{*Sk4%m>)MhHIrTQkdN&lAOeHe^*JSC>^^BF?3_ropfY*$dhbRA_QMdRkxfS4->R2PHjfcPNg7qgTT&;Q6HvV zgOKVnlT;yc096M#%MABe;lqBphJDfW{D>`&QEFv$d??x@aL|S$E$=d{R(~Va>js`$ zyI#m7se>|da#@+m{;`>Y;W$eyQ~HOV3h5L>MoxPsGvw=Vou$-HK3Ia1j(_b(*uUzI&DC8{ok=8v3z2;oE zNbYcuf~V4Bm_*1TP1tgcpJF%Kum&P`q(ebn&EL3T@;|OK|1vm)tl!lRze6c%U2hE^ zeRXU+oM!%2`0)?D*IV^mYr)Z-7dq{SbMxas4?of9FD-z~XJlYL^863q8;4bkyB$~c zFEIaAnqLF^_{Hjv7}nwra#iVuCk%p_c7nd4DcZ>`V7pzNkKLmcbn5(SUeQg5^Av}M zYNCTPT)qhC@gGASQP-Bc+eH2onX`T=r(z1k@9u*~ zEJv&djC>BIC7sN-GD})o>Gc>0WL~IS;YX|#PUDX=DABq$cZTa%UNftz47k*3(H4H% z-x3#>%I*@%NwAvZwVD>4465UioVi^})>lplh6&qM+)LTCNS+KeD4<|Qn(dBnJG<0- z4QfA2xlyf&4)uL%ye}$=3** z72MxmO<8=j9k2suD6;A%R9$1vg-4M*QMlLPE(t26Rdre5M7@r;Rufhh#`L8T9BIh~ zHd`2`D0{~;+{FWPFJ7tE794riOqN>qs@x2i@FC{sjO$i4%t0cd4GRE=ZxttJ9{s8? zTEkj8Yk)DI&+}l!vur;-X3+Et-1BZ!`qI#!v&+6l%C-ezxAthQpJx$# zV(5+UUoyWV)iCPr>y^YT@L_6`e9HNeC>jSwO)9%7cr@);L!B4Jd-4G?St!&oq zqkH@SGVJCb+`U9Sk#RWwqMG{9DQoekrb%{dI7-$1 zY9$qlZXK5!^!3wiL1w(uY^rYWqrW=+qtT~iK`4#e#-Gv;?+OJ?)Ul|sf&SEk>4y3o zB$VXlKZ7<|Vt~|Z%5wPwyr`7mohR4AB?1;(Y&k0Icb!0bG`wM-FbaRrIDe>`qq`CU z&iqQ-`8>;il30U7y#qDB2xww(v|3Br1xc$Xb#532^#1&H%|T1S>*3<6ZUdciN}T?L zO|vUn`1hS2S|-ZL?mzm*?%{#@3LEQemCu>mW0Dod4S)q4k&{|33z7fVuKKs<$&2Dj z%X;Ea*d-a4BMMm?-%+xN2F%=0M49Jw4ME@Td0%bC5=HzxYv+dWr6H1B-oj_uZJjLo z!LP~Qo!_LUKO6sP+Xgs%sv)+d=aY8lnKAG9+)*HL`V#6BYIsH=wYp(R6t)|p(PII- z`hdZVY1{-8Kf`KVy!w&QU2k88!wo^b@}5b8(4o5Z@jNq3Xe#9sg^S*lHY8M_$&*M1 zrzpa4Sn1Q}eS{HlT2ABs9K#5hGhtIY9c&fgL$}WAfWa~ZQkz^szajY(EoGMWICS`C zDap{y8pKEr)LsC9csi-W?&;qg3~%WLf^M)@jQNn2LR}NBfB8}A5Cy?=A@|7ZlppEE z-wQP8C!9t#?mlj!M7xEAq;D==1&_E8_@iAj9p|3P?Az%uD^8QwX-Ebu7X@w0$C2EZ zf4q@aX!^2PruX+y1vD;^nDPNM#PDSQy)d{ zt%x6yDalXSFV^2#wDO+g3Cvp5Fl$cObcWj9AL@R_Dnl{8)?R~C))eeuR zt!B8uRHMPMERuS|m4Di{e9xNj9T#5{qiw2;Inq>^BP~Uyv4)tMy1DZx6)S~l+p?wc zHw8AehpucdVCxybZEvXp^$w{MVmMYu0@d#&dqXR1P@L0dho8%W^DB zd~?%({*JC8N#Q-h|=@>BOm?k+AZJ)EnA=wPB!zuPyvHcfb!Om`wsmV z1?|<4hCFDw3**Ocg8cL7kKbJ21DqN-`G1tQDxxd2?R?qb*Up==UUAjQ`WOj8l(0fR zu@XSZBUjvQJ{zQL02QPeW-Qa#q%(VM(q9rGIB^{v#b*KOWp?U+CS+Moj`ixKcLZE_ z+0t}p0t?rIS-#xsg7VO~hPJqHYE=bncoXM2nK7Vc4Ed3pwijQ2M?0c`r#%a4<++ zb48XjXmZC*F`*i?^@EN}ywAO9x@tnU>H}LAiermK79Q(p$Eyfa?aICVt|cs6zBTVJQdW{ zzI1yOf!b`jA=kq5D^$X@BzO6Bqh`qZYYFCcunWJ;=R)>?QrV8Kq7meB$GAHKc^ZMl zyk~>R%e=v#*bF=(EOi(E=LJ+56Hw$?mQ-FVUrfAH=)#&Rl($%g<0zY_@XS!u)YA(a zIKo)$gxIev^pHEzh*d^l7Gd?1XhjuFVa@-JJ2K@&26h$4|7r7Sz)}x(2#qeci@D{TWW*!9J})vSF4lMvwO- z+q&}&#{C@}`KT*4NLK~%LIDoCckc|QM$75)6w>260FuR2JwLsfdZ$fUZ-!7BxzBE4 zdq4(LwA3Y5;xPsp#Z5NRL))%{?+rFDH;GYyg3;zDm>Nl#w%~$m0m^8+X8_ zme2<(1&r=r0Dir+HS>I!WB-i&m;DdGXxLYxRKY0fpcSRj2p2IWkKW&b58CKKb5`Q= zCL#=EYMH5FMZ!k0n!zsA?}oVp5<`2QN_t|=fUJe0}sr+ z*d@`cpJ^AvV?88yLmyUGBKL0|-%kIx$5H$(DP%sEjG+bJcWZgxbd8TS%DFt{3FgVa zip4j#hcxpjbL+7aEA2dtOVv907JqIvs;k8vT#l&BQX=u|9C)Som1ZgL)3_{|c7pDq z6n=Dvgkp7fb#SUK(HuHO_X}=s6KC9aBv|I;aqQ8#R!sDp=w)XmC-4Joh;fXfr(kI_G+NFJ%hu!``t_J-3s@K-4e&;@boxYUDo z3SWIX@0$NSLG$><4PzQ3y-diL!!UTg<1UKPkGGew89vcZ&%7 z857-p?2ZrV)6jj2mRWJGkb=6U+!{F8x?N=U_z%#QU#~}U!o}d{MM>tz_~L*MdZq-c z!v$Ca-{KBvJn|k*W+qFLgR}cZwi+03qAdRi=9&CGnO$RlRj`?sZW7OItjki3<2JIe z;b&j%I6iM$zgG~$b;7g=bEly~BJR#s4c;+#J-02CPsjVlxDsG^l0b?7^9hoZ$6^gW zchLBLZA-P^q)RyJte({>$Dr_Lm^-xUV&Gbd6+~b&O)^aP_3qj*ZLRYlsLN=A@4@F9F$@$>xuug?#ondl8vgp#{D?!8u5ckAXYql7hQsA zU!>0AO(IPj)G1yUNM8Oqj=s*K|9^qNQ{tR)u7r(pC!E?HDvywW`^(%}|J1V~nwPM& z*-BQLZ}jeAc5oiKz+_!=k*SB|`=<P|kL3WBp z*KjN~CryJ7Wl83)sZ_R=e=oxeAw5x~&>xf1#U1PL9uMa&CcRKHrLfeO?OuJn&6`cy zc~8A^j)r>Db1rpn(|JA;>mwY>>=nKmnes9@ls=tlP0&ydV~L+&-FE&(2ojNcZh^&3 zxJ~K4aytr1mOCm#jwcVgc#IWCk>^HKHXC3m@ul@@4-!n4y9UN?*vAcm)YHAc|AzYM zAKo7jk_58!tbU=H3xRUOOeJ-RYj5Qx3oF3e892lBe7HEprS$~Ge{CdG!ML%-x zxfWx3(fY7uWf#9CvA|KMcT zic9hqIZE01%z30!09pJxXgxmxUa|Tmb$#R9>bG9+#24b}U%HlvqBlLg*v`u@PRzw7 zV0!%hs{~kQJ{3yUjY~CrKnyO&FULmNsT?ZGsyV|RU`uYoo(!sq{-x_1u(b`|b9k4? zrTXAkqd@inGAZK&RNP^k$Ai@g>ZqOa5R_$iL#s6+G5?}f2JS(z+INB`Hk;oa z?y4>2w#8I9hq+zGw*<7&AEw4n^zVivE`XvRW|jOl77*0OF+_{O%!E&$w&Ja0T16GD zp#|i(A<`v`eJ`M%?eoXkU%{tXh=->VT%g|E@dD$&{V*78AiLM~u8^)60_<5FMn z>%Au6vXjG45H^PQvn`2FDuYqMIyuDES-|Mvt`JVriz*p4-??6mG5F-6x&8_y1kEs% z|B!vEinw>CU3?i>)*zWB&@30;hUzZnS=yL{Xow3gO^|Ul4;fT^W*s8 z6rv7C%GspBxTKG82TcOt#)iF$d_Hej@-I~aM7YT5BW~S@&{d0_CY=fi>m@;hcLl=Mrk#cTr+yU2^yrj`KwO;Ffv92 z(YEQ4y(sD|bv0>WdyAR%syT6RVEhCAusc`5+&3|xpqHg#Ce;RASWSC>(dkxOeK8+L zI;>o1D)C%UcZ@~<9sF3y(K^|xK^G%#SgM)v{tKrrI(q^5i-nM3ezUjSxv|QzUV*>k z7;Nkc>8C``5RKjse;I{STojbtLtsIO6Qu?0toWCpps)2k&m`uF<}4LnKP>RzZgmSG z(n9&VcXtf1YJ&ded`cF*9#cC%r>Yk3?YbnPaAl0z9SQnKz0gkw1WtBZPjrW%So@4K zE=4D=OavXRcnVTKqVntq8%O{c@%G>`lJ+L)<%}pz(Urs?F|d&jK%NGKI3PqsDi`gD z4B`JRQ1jGqh@xLlUGtjvsinm%R{v!IzI>}9hpk}B#?70*N zOwruLWNkS*z)pfqIS*{1`hMeW!M%&fjEh8|m2B!r+N@I>CjY~)xIP<6hTx@}{u5H&Z0A9bV_2+=`Y3c@QfN_4S_$@ubnnAnPh7e zK2C?m~pI`Dm}#TZuVNZIYNgTI>Xxt*GZh0r_JZzBwB?NQ|<&Wu8 zmL7YJQJtpUmh18M7`4#Ia12#*`W!{`&)skjxj6G%RmT(;Sga(GPmJ` zeB4yS43-A4gAc0OXpV+i<1?xxpF=$X?g4h|&rq-#XS(2J$HeV1qCO5Gz1rznp&$iD z2ay;*j#KXxl)fzfCn~=S0)}Qlvt)N`|L-V=Z3gVx?P*5Y(%9~&s(XK0mk*Z`P4}Ki zJijJ$Uo1l~dYqK`NvLQ$yosz&iuh}RB<<@&EDGMLiC;8fAT<(7xmMt?`2tiS)PK~MkW%t z{7W*`F7CY|bzj|wNy_g#j-78Dg?y4Il-~~^370Mr;91MNds{%codqC23N&_b+bVtC z=+@xBAy4*;h6pImsU(!^wnx}Imy^@(GkWF#kEiz($r;*K5lY)b#PYp zXV;T6p@XAFQ72q!i-g8m#`!*t5QtR>wDD5(v{yPUn>LnwQt(<9Fu&}(!k%g!r;#}% z_xdG5T5vweMa-S@hm)A?2X)b%-zr}ToF9xolezn4g~OA*gIl&wxZfyDgf8UO1YzEA zH6XNv?~CsHhf>*rkm=~Ic+BL8t6cVzYbe9A5B8#+Hqw9D;a_~eNjUrhXyvDLni}u2 ztQWy%?fiPGPT>*@;)%hw3)*iKpA)2~EvaGfrd#ZBcS$%qNoW>%`^t8j-3a;6k_)B+p6Da@vyW*JI}ZB!+n}wvOBD$|xncRq z!^5EIU^d?}0iD8Ket&)yH|!6t^i9D_$g@1h%gi@~+y@bqqejD;36DSI8GCzBMBX4w z`wXSYJu!c|rB0n67>j>M%%EC(;jD7OCG`4t+k}PYdsjE6f-Ma;YeClY8UehD+(ca2 z{?oqo@V}yRf1Iy(-l2DKtX3eqR^y^`L63lS_T%&Q2N;pgft6){YNmf-rD3Y4ouSS@ zzx*^_Eq?fi{rTvf^)4?<_vhnaOkq7@om_#+Qm$#4)22XPi+@*z&2J;Ji;l&NXv4Bm zx{lEN66~%sU)5{?&Ku3Qab?DDuLsVC-2BFh~B2IaKC4T7QkTrW2g*s2VlQFY4LcZ1uLGh&UAy5<1OlC5^tW| z?1eOFq$s1U=fr&ZXEIDq3_^XStwBPyAG)4y6l*7IP@I!(qsS4t8oeE1@h;(kJYY3Cr&t3T^clpJI__0SEk5Z8Ea~F z;s05s(0(|aG&CMut~|`&bhMhLz0i!CrNEc*!J=7W_NOXZ5y9i)j}@h8JhzOXFmunH ztDs}*I?P^ZY4UqdS&X=O6O1^Z{0D88!dK!7@xBwhwb}Oem8R)2)eG&kt6mh+7eHDS zG3W3x+tx{{{5=w*A?s(g>EOpmN%CV7^GR}bAKC*h^Zw{n?HPQ&-a zR@ptDvhHS$hW6gGb`)b>P!n)vXEvp~JBX=rHTn4Vo3)KyxHn)8l=Rc>i*gWlG^6^X zCXcySx4u4F{?iDX~fyd<*8 z84&ALS)=}?>gYPlV1xMuvNQV6ZnPS@Lyo;A+0Ky;lBA9a9xQqK`D!lyW^k{})z#;y z`0ce;cK2-ExZGDMq!XYz5H~UKA$DT1SHu8;8x~%-uqDI!;?xHN*{saJGZ`36c~13t zl^J(Hs@P3xy!Y&IIt;&6!}>JmZ*9y0GbH6zdU{c$XH=na7G(G|I>obY^P24i}H z7cmoJ9BKO$b{A4v?a{vD4)`0i`xfHmt06s-8LD4C2y>^3!b4c=YpcJbt%Y}O_>`rW z!CL&W_k=kjXv<1(y80wp8{ecSZ9D^xcg;I`K$KP^RDbrxeDV(VR9B$Jh>T)qPsX4I z_702bu&xh{9*e@*O}#+Yl;8kL7LJq0sdo{b#E8>I39A(_wM|ekn`!-UT>USyt>@ z_)FS7Ro2!l1?o-VTX%j)`T$=sWSz@btN21UT#q`C@dV8Q&Gi8RKZ+OGqG{O z0m4Yg*$itc;|{b<2jqbp?cWvID5W5;Y@DTpuJAQ^nN&YR(N2Wy!8qw51TW}BzSBt) zw>=wXzWo+4#5W$gHs)i+ppvU-YYFEel{V2~tc-JoYvL~-8a@j)W=;Mxbs82@xx>M% zLZDo&0J3N8}9O&gp;8Ev)4%ip_yB%)q@oLVmn(vRfv_H5u!ecz;dVxG8{9RZ#Xa-8;2@LP{KRhJ( zqi_q+Vwi#lOaDZ~5Y9>^v_#lmFafNq%TN#$PUo9ZIx7+h<8<;=$+?)sN1dVaZpW|( zyrl`mHf#)B|5BsZ%O)s=$=|-spzlze`UKclGoK1vhz>SKS-pTRUCL8&&H}Tu`kvqt z`QL~b^Fn}osSQa!a<%bzSlkr18C!E+0;5z9ZMlKiA`BoHiQtrw2`SOR(4GIG-dP67 zAQRyId12{>QMRc#1HXxpzv~v0`BXhooc_IYgV^q#ycbOX1=81nT=;?LZ72T4QQYr7 zBW3sTCi5iO-k_x3j>ZX@qwf63?GGQQM7l+<@l1d)Yj(i`5L$k?jh*S4O}+t8OF%m> zV2G6Izv`yt8zZ-&Ep+erANdP@33{oDC)Nh40QzSdm^Z0;`VM{)+{f4IDZeT_y=B!s z`JquPlex>)oz=3l%L4*IuxG+cODKK#0I2N7agwG>D8?f6?#BD(%DW+HiVamcF#t zegW#dp8S*uB7L4)MKe}Z&2(w9amlXHUMb-mXcD}-^s&7;KseIn*jjEqN8(vl|F#QD zsN|ReL~)QoU}Dx{=hTLhiOb{^qUHEmg2k_fe&Y-2pv~v5sm9ixP7vpp4~Et%DAjxWwGZPOwJ#+|J%j0U5a4Yzf021g#Q<+ajF%VSqio#yPre zxzW^35~#Dw!wl8$;>aqcI*6?qV!M-y-=SlTGiDLyocN=Z65*hy_$|>e7sT_o2C!AE z1(2o$@oc5~h*a9SN@+*+IWYV8jnpTN+_TOqs)UYfBnh`?fuqe`sg@?F>q2O1ugxX) zFbwH2hAVS-o6j5QjWE^0-xiGqYjAYpF*NE~gREG400Q~(q8ub!&8}&jzX3)E6uL}+S071cu%BQ82 zMj73$kD_h4RcaLTv~fUn=@vHIbnOmH`yH4>xWKU6y)9m^#Z8(sWnfuFJzXypg}!Ff z2B3z!-aI$&$6_i5o!pPdmX7W#Io1|VB>vYRue!U22isF_&CU`Tw_SG&NX>@H5p1nI z7^a%r7F#?*sNj&gHdwusghF57pNs+}(KC-wFj^qgC$N2GQY8DZ{$9=nCbO-=zxgI0 zrl&(&$}8Rv9k29$A^He@_l4k}=sG9AKKk_$r%k2ZkE?NSF9@=b3Dt{%C7P zYJB=~7ZltRvpL2XM~RbV_k6r2FOR~K&Gj>fC%$RaSd-kgv+to~`! zio~0HOF`c=h+!p`tWbmch29d8NF2>-#ak76Q20OD>fzn4Jyt|+x5T(M;}3W}e!n8} zw`whzR6xkUw%|buZ4)G1#`lT+>+s~fN@cfAk6jhLaw3sg&;;+Rl{hDsIjXp~M4y&45Sh1C0UJK#g%TXFq|=85{f@3zC;>#icU=Z3Sz zhXR%^RtFiKeR>a+X;P^A-wn-lYs7C!KjkefdeI_U=lANQ;faQ{Rz80;{Xdot{eXiX z<7Y+Vj^o9zw>P{zIZl2H9C+J*3$|}{F`L%0!U0*aj}@mjiPl*W)(|wX-HBRSA`;hu z;)G5R?sO>$NEH;&Y<(}4xsK978mu9{tECt#t(%?e&{xWP3G_Vb9)!FAwqO^Vd7iq$ z&5s*QkkI@Zrd+IrG=nQ7c)W!=B8zZdYL0I?#%r*`8}b1?>o4A3=KZ z`J4SJQxxAf@j@tp;=u~1(sJ;~26Zkv1gUV)ua#e9&|{TR`qGx>q$Gc(!QkR2etHlG;1t z>UR^GjGAN4@a{T&9S{Elm7sbsczc)2T8|DKy1@^ArkZ%hr1kO7_nKQ*Ki`dH4=9z@ z;wy$51YsdQ?;Mu134J2oma1o94JuJ=kqpG&ubd}rm-xVU(}%3gP5f!3Qxg5)Y+qAD z34xvwN4x~xJ#f2+5-O=;WIC>88-JxlvO)LjYr{gBf~5oMHd0OMTBnioSo!lGBVr;} zr#N0V>#?nj7r&AX>LxOQ|LMfdtk44^s{up{=fN)pP4@?*o47f*f@jhx4Bvu(Tire% zF;N(ua(YGfJUa{iE|XB6$Ps#efflbMNOVB@Bz`u0#Cj|++^*o*BiE8Rt15OaAETKK z9uXO+K$?*A6lWPB?K<^0#j!n`Hk~S;NiUU6n+G*X@AR;;mL_+gr#s;uMoLCVlD~+9 z?=WGA2kHBV&w>-J3z{I&GS44pilqONTkx(M=5lFdk=CND`D!!X_pXO+nzU~G1Q}3& zu>lsOiH$>AuQgQ5>!- z?z{>6LgR;GSqqYp7-oW9Wk1opU^Z+>gp0CCPFM!d*S*hn`?tn~I57T~=u&FllKBjX!40g&&c}6irF*jm;5i(+vN| z0IaNlL7|Ew7cQ z=S|t>@3Q3NeYPL~yD4aZU9P-c5FwH!&Dss-Zb#ysUqLpy7x_|(x4 zfxZ<-#eI(KttuvcS}7)vJC+o7gf>~$r2NMZm2bE+v$$1`0(hb&QDbrjBlcWEwK~dl zfM0%hSCbiwc}OLonL{pOQK5s14L%gP51T`>R;toL47a_yY7;4Pk@+I@zH8_O?Xvnb zREn?Db|6t5^bj#=aCAFZYzx&p4h4NaHGPp8E-t*6c-LPdJck%^jaW}^+G9YvjVMg< z##iqU32?U_;YqaI4EZDU=HNy}9SYLdOWk41$|{K)AK#^Wcr1s&t-wbKRgXl5fHLE| zh>CIeG{Q~ZVGmep6on-uE?;!O?J@sBX7v9ca|P*b=M(0Ya3>SV^uBR) z#@R{jtYgm3w39Td0Pvil+@TbjD#tPtkzHDN63c4<1abRs*~C}i|d&}SE01Bk^J0|rIN}T zk7UuM$-9$~^&r5k{3)%fuk@x>@qF8ADW9i<^HimW`_Q#wJzY z__DzZO`vlBt)k#tl>VlbD|F5xL_v^t+29~xLNW12ko>2C7#e>5CSB>I13JK)kbmN!`1EBnKvW2r00$_7D z^Nl2-5^&a^=gG~z-OtLd`L54SxAAn^dd5gU@4@D#oJ)o-Xk$>FLBUCLT|7%F*=Zd$ z3j16l+0LAL{|V`MT^?(Cr7z%HtztW_E&mnUM&S16s@w$$$kNYooV35E&0MOJu&b-* zLpD-OR;di3(U0w}=dBabVIZU~LcUsU^646DRk9PiTm$?1^hDF&*6dyR)}2#GJW%sz zKX{W_T!yA!U6leAn#`c6nDB?0OH68WGT3$UY2PawH3KssO9dAH)%5Iy<4z_yZ)XoV zl51tO^F{#sLy;4_i%t*wL2V2jCruA(-Ni3D1D}Z~;=gRj&$PP~xC(L+fa}2{;h%iq zb!?8?NYRpWnz%7xB`0?z<;S-htzK&5YP&C@_59bJ8@r`>&Ka~!CD+a%lFgJd2e)V{ zqMA0V1aDi}YC_vbE~mt+g&&@z&}f;t&CDhd70cZvNK+y`Iz zsye9V@8j%H?6-kJf?ZK=rv@^m-{at()4iXI8949kFPM9w*hkDZ4i$^f6t@QOnP#T{ zWty*;bG&%sIX3XubT7wMme#3kH3CQL7rguAzesadT>TDpm^ePtYHjAf_xm{SP%Zu) zZOI(Ns4QV|dOn*@L2CFYv**ho9l;ND5BZ;aBi=r3ggXGM#@Ubz=}ETaYN>FhWU0Ye zEoq@*4V3;Kbeb$&v5Ec z_{0=kEaxSbYXp^oRo*_+S1JxM0<^wP4C`NjLXN&en-DwEVm>~?WNvhq$q+l4L*`)pW z-)zKXSElp_$rSHtNf_$@n~S@vM6%HNa=t0D;zKl|k#rGF8=%jx0TG`tW-QBcE~)EalF9Q&}^w1#Yo9;=yjKuo#FI|?mn_6*W; zwnzrG^2y)jjmI`i{j#2DIhtT5GC{BI{L5$0s2!agH)+k6M68Io3OT=mGi!eZW zacF=;41u-OwshtTC`(nnD%iUdx$+*OiY}Sxm38=DjL<|L5DT znIFQOtW;LAI17~YiXfZ%55pSZTM(_0XLmbX+`WWX5FxjOM=RHa1wU%wuqU85vuDUd z7=Om!x}9eqkeC;5eXdyiVp;rAUK@1!3Wms*Tzj+Gz4e$d{9g8MHkiI>nxI4=sc&v)Z7F-qh*%1So9dnx2B`Cwc99T!Y{3Jm4+kU^=~ zLnm@S3w(@^oDm;xi;l1Q?J7|rj+9rbl{An*I4Xx#^qu$4f~l6YtxnEl+u??bZk-KB z-)ldyjccC9WzB#FqkZ6v#)fr~Ie`c{cZ@%T&hPVcWM6^`3DhfyFW6U=1aFrYyD%k`=Y;PO^$ zK_~dr*4}Z#xYp^@o`IHMHV-1D)A6zQE6BdYJgL(Wi3Y9L#}U}qP7l2k-s2ysA_9~R z?Wqf?GndE-LV+k!(>IYHJXf-ko&1a3&O62kxkbo5q|eN|U}?^M0t? zt`(s_^!ldf-TMuj=N}&tv4_ityq)CzJYWwI*`Uoluv_KrJj#%KzHotZqCaP&LyU@~ zVk(uhUj?otDnDktA{Zi`cq~mxsgfxT{(Pxo9Ii7Fn!cBvrFD`dUSi(SknOht3Aekn za3rGhTYqZc*8Ae|CH}ApDEItNUAC}yZ@10m!_qX@gYiUiXriBrL7-DI4zDjG9PVp! zN7ZWoQgplmvHZvgmi8gufFLxpE`k@((L|vovZ4u$L3<4UQ6(!e;5_8T?sjTO-a-1X=S?_2*vFSs^>-LxtTBrUm>6g&qGXCqYF11=g zZ;>vlF{!R=+x5>WV{9+zM56wEpLU`A=t_PTdUMU>W^a!BSQh`A0Qx_j)Xq zzT>>a$4JctZl3ZQSkbc*k-bILZg2PR|5chjKyKJO_TL%si1|em;l{^P3Lz=4+7(V4 zL;)BC3{H}{!qSG?veA?WgDgstg3&+m#KV$JlwFx77j7Z60U2`<`7+9{^EL=CLv`N= z#-0Yz)Haw%1aKOiybN>F_D0LDcM-3{=X}GLlY>YNUDuU7>}6-IX1~~7^O+P(b0uqx z?2V+U+?UdvS0$T^wKstZwSSqhv2sGp|M%pt6z~XTmo)Ndu76ERFgeN(?d^FM_0l9} zM%rv)(}7iwu=J?cdDZK&YK28zQp~tQ+C6v55nkRblrAPUzB_~M-;jC0fg$!7Y(yb{xZ%C5N#yAb0v;+*L)fh`t;lMP@CZ8!XN>I z4;aG`e=NJUuS_=e?78?|8RwTff_{mq{BEw&5CNVLA}@vIT~$v;W9oj|`9^pFO|=3( z-DkyDRQqZ)RPY@6ARHLe&`*b8`Q>NL9{IE&aQ%!)7%&6cgN>;rY{<2DLqJqq0@2XCu4ZaQTrFw?4}S8-B*0|LpFu89E^NF#-M_w?rvc zD((qpQjKBq-@-cQ+!0Xs8yy0*#`a}SKxGhxBplFtWwI6 zpz8h9sj45Z_X$a_Iw{`ypXY!zeWT%fIW##YR^9rc!e@u7)a4dZ4Jiaa&+n2Z`%{Q8ht!#csqee#7!Ra-B}K}vlh4*_-EDViUmTkzs;5+w zp8^qV`7S+qb5ikvm8uyjFe}#1{%Uy7OyTcd&wveLITI<(?kxES?QJJShGs<$X-VZB zy^^@;%B0zl;t}!34M(%(%Q#8gIFYn&W7xp28z4O;1qg8ZhB4wnQXmM-Tt6ILlC zevdtbfD&8PNL$MUSl*@ z*PcO7-)Q2^lWr?rw0Q;zS}mR-F2@ojbcuPKN7{E{QDOIl7Z0boQqICap|nqVC<wQUd4g?ky6}<0jdM5=0k6n#3U)kSs98#UQ*R3s?CQl zVLH)GW}f?wJMR9Vopth8j%MqN`kmZEoQsld7BJ-S<_K-rpL3E4)&l*fUv2b+8`vwG z9!4(+x8;Cd99)Q7sZN`16Hh*8}BbR z<}b!>CW(7DFXO8xHtEqZ)IAJ6eCS|Y1hdrxjUStQ*S4|aOFgh)mI4Loyhd)_RB z7IOhN6E?g3$TNNzx2feYr~k*{+aqgXC6Yd_`8-3GH&)9h%|e|$Tzt68`ny>aROgRiJu=4~E`uEL5GtfSy$8>UY0f5v zf~4~Vi+3ZS44*t9v+V`bNVMi_`PwUsrtNkOC^3}newI%V5R~Iqwh>ldYP7>{?>&AU z68hHYno++2Hgnr<$$#}2@%Mqx_&~PZ&i@zL*@G3-lMw5-Nd3f{7ju?b*cExcd!ghN z%sz7CdS)_Iv-1=asx}nQ@3&HFG_YvSy{BZGVF#2})pt7Otv4&bj@q{$2!GAWu*+7%f8b-|g6?YX@)zv(rd&6Fy8Y+8=Or0$Gu3rr4}%b&RdQyGdW@t`>*R#45Lcb=Cz;Lq8X@u z&)tx4>0C>Qdt6zC^e6UGnB8dT9vc1(!zGiK<<4W{hB8V~{8|5OaWpb$Qr2<6YDQLo zYbvS$B*m=jHUH7XI5*?5@rmB2tdXn10VdFzD&OyZ=zc~Q zJjx71E-XZgBguVI+P=S2*ObN$3z@+BX+}fU$`8Q3c9jIjTTVobKO=%Yq(jCPF?Y1KV5k$bK=#)k z7fs2q0TzqV+W8|#rA?jeFa8h)R-t%F09nr%vvXYnX|g^HI4IQGScS0%4-+d6)KHtJ z7%Y<3B&U!Zi5AN4Axv&yiGacs`Q^^N@`91~ObeMm{{7`JPLm*-ioFJZ)cVG$uG8Cp z$~$+N`Fzf4CTz;ZJ=j@3ScP+t0`#($PRH7~Nr}D0k{Oz#aeQcDxqB(^2J31v?}m`E zj)$pn)9~92*1Bp>x!ME!@*3yJlDzlws5?sNzL{?mVMajIO=y(^4?NUa+3yR{7?XR38#oABC1!jKq z#@kBZM{CSdd9^-ClV#(`;90U)*h9tiBBf>vYxgY_zN&k9v%9J%;mSiNhtL1 zw^Ctb7W6a=q2#%i)%g|GEs3{b1M_KoyuuK2do{}p{+3e%KHle`L4C*Ue+N+caD*JB zGQ}BhDir9~eT&E6a@lMmj`)DAE9!9#vj4`Ql9;)DMUTmr>H%u3?!+Lwt>WImo!_@X zD~4d4$#qg*#g$V5ixlwiHY8(-xn**;i0dbYZ4=?2-1Y=A`q$?5_W@%;h=qHK54AkU zc61j7z!1$z9PTf>7=5(tP^M^_*d3aHoRfSWqPBdfZh??@XDzim(mUxTb*E4tgOZBZ zd;MH^hZY3f(2aI8s7k6}p8j$@(|gRym9@wo`q07>gZVg_i=Xj@DK6str9acszcn zU}b_+i052BZ_ZZrE>w9o8~C0DT~rZSJK8KnI;;hC(|)qPcsUW}7HOkN!q+6^otGbl zTS&|n89WRvGUSkYWu8cvyHo{&)yeqg%^+Tq0AgRt3P~@~-Esx5%ST`)3!Szi*T4sf z%<@cAo4q(t*I4HQnbg_GCrAVAT4C_8lHCPaHK83SjWU}dGSwARVGD2z-6ddMKy(iD zV3*na*|+-t-lcVJMfP%dkF$!$FcyKNw1TeqeU%#e3EcS-rg)NPW|5wA*N zv}H#{6u4DQ3bdfl>FcnZnbZriBoz8on#m_7tCYDVh~QthbiE^|%r991~EOb5g9`Z>Xdcn+>Saf*8@2#{?=GfgjT4pB+1-6og zwMavb#n`B_dgy@%9Yk!_3Ck6T@U9<;8F38w_tS#+km*|*S_%)FpT>Gk2s66P^$J|9 zJ+p$<3?HE7^79+%BSJ4WKutpz<(Mwr`|(H0U_-uY!HJ^0NDP8g_mg)0iEinLKIDn; zZQ}!Dt&YrpaZf)dQ>7ZRU?*F9M-H-#RXz=k#4Hf%`I~=Kw1`hOE-yeM5-5gu-|&4* z+7)D4eOa4lkBfVz;R%1a?m?QA`7fv^2FBcWse|9h_25@6iK(>r#{5sG9v)Nc^>*0@ z<5lX}|Ebi6{a1bRlf*EZ+@H|Woa!QK@+^FtS^8_`=b>G zJP9>>)@=WFJE%d%WMogGa&Yr;CVr3`e{=sQQ|l+cy#VINa16E{hO*23+$x)*WLNp_ zlNDgsQsck!RTJ8Z>ZJ084r|okc0;T?1}#vcF5nFWb}AP6i%3ihdhK05cs-uodSzBB zBETB@H%R25r>x>^-8YGAG*tJ=;HEf#B76%UW8Ug#G$sG7>gdT_cbWxPE95x^8St2R zpGZC2iG|1Wj87L6vDOB&E2aK|f*}j{tOd$QJ1mkUGsp3cZUt5MJ28u@frdUPkk$;} zD@sJ1CKq^wa5Nxt4)e}!eXpqQmPNwjt?R^^CNA-__-l@DpCZ^}^VeXXjTxO9o&hP9 zV@FE4Pv)k3x$kBscInnoV)cB{Z^nmH*&~D>gN2WJ!o96LzWz#9C+A2$?57lt=bYXV zy~cU~Bv*J(ENp>{KOly9cS{m7^6Mzc#x#J&;xKeRChZ3!p|C*dBJs?ZHcy`Ps(fO4 zM4^y+5Bgl|UjS^k;y%Eq$y)sri6DffUtimQ`9-*;yTRljD_jw7s$0L{D`6J}S3iXvX6!m)-mlj~xWmi+e& zSQXU59WiUcjzkTZ;3N&1*)N=bmpQ}5?cY{lnz|dj8tIol0(hP~(uFX3ZHpiIZyxl^ zB8ieZvEYKKE;Z)s*XxCck8O-UO<=j7r@onZO7zPU zXL7=AAr=ti`I8WM(C@?FguZ7D7iVCo4H|f|cNXCZMkt~U3@E zONaKUz`Z=NcPtZ1E&y>I#i*028ET?^G8P6bF<1b#-tLhiWdhH0G>H=- z9NaE+a9Lw(7%e`65E0Q_H zn-Vg3c7kn3Z@UVd@xf%HY>sL!W|k8^@PvU(1E7xvH_T%4OzgwIJ3}Z7$5~LYH)1y_&^%qzKFZ4`_yKSQ3fze&dE2Hcy%hYFEYG) z;2mm(M7TvXO1asy+5XP+?AD94kgBsbn#jLNhKCP{rLt9jPiNjxh-a>-)M5fMv8J|3 zJmvk7!U$JqCfdF{T5It~>eW4$^?Af-T{@tXjn!h$Q34@n;&{}LL-I2Bl4WI2u_51O zdm~r(T!H0brroOO|A(=+j%&Jq{JoWs6r{UrfYQzA0TKeE8>JPM5yD1Iy1RAM=q?q8 zpwc}YAPCYq0qK-FyRLJ-=XdV=-1m8$|M%DS+4g?Fp0Duf0J~|e+uCN$Eq46mLG0Mw zlUEVTM?4>e*7S+GWW1CUV$62|*nT$H=_1Q_j{zh^dXFV=l_5~2Z zr^R34AtVyNyb1VWczrdTnxSr2t%IHnCyZo1gh!eMQBEWeiqL|KK6MB1y`-^@!nZuLLce@8PZUo&KXdL#Z6?6snryX}W;r8s>G?roDEH ziW+e%vH5dQIB2fpS=bZNcPQj`G0Y8)hn(;djX|A3yj;(!Xd-9Ab13G$w9DcBtD5B= zJtTRnecE`H8kO1~AZKz-K6%r+j>X{yuZ(@0z$~=n*>&yhfdkHD8QAY9Spoo8EDcZH zdDWZH9o6CizfBspj#RZgE;J=@Vkf@^=jcXOksQ<1!s(f`1QB3ipQa?~YxXNsB4SAF zVfu)mLZ;juGWu@D%~DYkxF5S~Xn^p9<$9GY+5L@{G$H-dnae5Eoc-L^+Va&5eRF!K z2jc+!+io)j)KBtzZ$Dkgr^6Y;#UV^<8BvB~W8*t5haw7pmAmq5P&d&*)Y4+pb$js3 zM=faQuui*$4EH{U(-6xZvm?`(FeZ}qZ`DmcG?BmPwRMZ|4&omiJ62;W^7HQc?-JEB z^ZjfWUS6P6sbqi!N}?8Jm0x>PU!&*C4(3_~8#eQ;REhvx1`3#fNq9Y?iehYktI-oR zlPYw@$0=N{2t|IT$R-Xzj?0Sh33aIPVi4DbV+XmC7UaPcw_(me~t+EV*IcmZiOynBU4@i;S5wiBHQ6Z4b) ze?*oC0zLjE(251$y9eiR1RDAu0xk4E3H1LTfQJ9C1llU|!|jr@jQ^)CB(c3t-@~;( zRcWgKJAvMv3Kvquzf+UX9P>%p%+7as;nOvZF0+c=JS-y%)ZKI93J7*meMH_SkNp7Z z5Qeeiyr$hG2iH%bJY!m^n`@>ImG|<-g6Rd2e>&llzyk>XA*B4(rE{a0~(ny-Sq zb=dzRiNiMUPd>xc`}hxn_NV3NH)gvsQH#cskZ< zKhuJ@4y1<4(e#$smL2lHUQ1gYLR}53b^iRqDW8n>SH@_C)(|^CY;E-^k1DV{S+YVh zSJT%UC+e-h`5Ip8Qf?UeUAfQ#p#s!wYr}z{JXfD^;hn(ccWfsINlp`#JXACR#b2M2$&LZ)f6g4O@#(|KQQeq#{JIdaR+P`$Mk^qetzVm#4Mv4RCp9;!1o${ zJ+(*^_|s`||Ib&*>z9Ilew+yBHJDnFa}jOWHU5j=CEL>Ua#!%E3{Jl<#ftUjad(vz z3o=}GEizYYgg3XZ|z*ZxwbXYuOyPr;x=s*YkCSoi|sQ*kS!u%hM1#ut8XhHXJ0PlK7x zT1?dRDHDneBsu`OGStVL#&0&Ef?K-{EK&cop2K#*0c>61t9Uwly z!~jkmBjv(ZSEoq^!#k&;2^1E>cK8WZ`K>M^BH!|5#Vj!`7_`{K@mglkO;}D>l z{6O!9KKZ+;F-ltl(^HigMf;Omrp2ipZ_&M^t+VmODx@AQes(d03hk-F_bTKNE@Oi= z@ZGEfz#kJc(C+cIc8)^sduGV8%a(IlY^CZ5it78X|0KC>ext;uTA2oWM`Q+(-kh(7 z3BRb(%47r=?qmCY=sKpjmIaZ^h4tHclXcv%H3@4 zY=q?GR$esMnP;DB za&elHD-elGALHj<4_1Ek(5T-FLU!c@7j+kW+!?YFd6s}nKWqFy!p{|OxOkCCX4#*B z3`#^5_4-0=QMEw^#&B&R(M?+i)O@5HxDNgZ+>*&JyWb0ZGH{XSFLg%YmTY-dWs!RO zJ^GevT1Y{o6*j~7t5Z?{Gv#@ObU#n3T$3!o*1PXo)8%^M{;_HOK+*MoHN$FR4Dfzt z`i>XK@nhPxelRTf_fNv-^1befDp(oy9ceEN?hBRoSn62Ry)Kse0i`df6K6j?T0&;o zCa_P2Eb>JEQ==Vz_Ss}X3Df-pm~+*hG|=u_nm4y%&xsma&i$sR9i=JzVTs1Bb?fmRDSYpxYJ3PmVtw>KFn!Jo zL2HbaP%qYS(kKvT|9fuQ3~%XbHoA}#@ z|MGZ14i^MhH0G*1ZS(o6d5Zh6CE3?QXZMKP%x&JB{t#H`ycd4Cl;N6JvBBx_km)M1 zTB#Fns?pvu_|3WpOU8&N^idwHl*}^^i2aJJD1X~83>X@D9A&$t)Ak)Ju&3HxX?P3| zhi67+GFKlAXbQe}>t^bhM}rQe!Gxs27z){4MUMfw@l*h&x9ZuO0l)t!$ak7U zj<+&gnF~byUNpckw-dySZ1M7Zl0rFfl>V!H=I>zh`}DOj$S^xfU5ZmNHhXjX$WZ&P z-siZT&ScCe9Ybk2ndV1W`qQkiJpS8XWF|I65U0-e_+RdQk=o9JoCA}38Bia(e zc)}#pRXx%d`mQ!cO40s#sW-8#~Mxi`5w#F2^ z+&d#RMqV5vA<8Ji`4=GTO!?Uxfi-z`UZ;(M{9zsIJZSeWV^uQnD>J@yfR*F-QEssB zF#UH34Y?XQ`wxTu2SF<--h^w&;i?x#EC*I&`YQ>Q;J_nQSbD}!CJbu_3N{`8wo90~ z2QR86Xus)+T~_$pA%;2@hJ4~7;Kf7nI3ojg?T_5l*}Uvbh2TkZ)jpPmwg?HzGIwl5 zcwGMHC4HxKB+=gA2sPkRRjB-E((He<0yYCz#K2SYD)L7TzM_2j8+es$I|N2oAe(yl zejRBrZJfIZ^&=5CJgy8Wwl1=<>-jg(dmr64U3TqU^|>Vn(HDhC&MP&(B?^3iKCz5I z7Jw~2nPPR|q2*IhIGu}ClpgvalVrdm!xp&8m`c?FF&1L8gyoe!*aD2Ns82(jM1BE6 zp%vvlCyA>Y0mmC}mS1R=NIY7MM!bV}e=fh-e|56g${Vkh0Bceh1dOEp=!9jlcJw?k z3f_qGf%PanHldcYP1CG4mtyeG?<^iplE;%Tfe+3T8R|tDzn?Ud2M`XAfaugRQo|ZH*^ZV~p)3Z>;F(=w|!md z7StU`e>~X`*i|3kV`B4MA{<^yR-b<6200cmMUML*rQ)7)Ot^iZ;_>EcY6BAeF^G-~D`}L^`px80 zSU^nrE&9#YdzZ$((+2n5qzf|f`12xxY|_Vm@nBwx=uZZQv>o7*uyCjMpM>9RLIJZs+m>ShrRU5Ut+k^QY&dy6roF@f^e3k2f_pt zGB6Br+*an8N2TxdiU~@WH2;I55irWJbT^~Z*S<#FqsAp)y)lR%ztp0*9+FS2Ojooe zb_HXrYaHdyc8We2oOa{Hkz>`g;N=+@D>eJ?upKyR9JvRau5ZuW@#&Js;U{l)42#NwrXIUCq@Ajyak-&r_t7-8lu9=NAoSjb_%{-?gLuUy02fo$00f@-CG0x_WICg+UsoFu`t?6V>{4ZBO(= zT(QPvcj>!uKMQ1^qMOJmD`jgd{5mTTx1US*;L_J9SF)b@59BjAF+QGo$6U(+Fq1`- z>8yf!C8&^hU&?<~^9*g0Jixyl+Xkoy4&AE|7_=0j|B78e@yQs+!J*$JhNiH6`zuPL zSY_G^QJ_=r!;pjy>}(9lnv%D??4#WfgGu)nF<+?eFYfQmwVTYNVDNc(Lk!sUC#2XC zqPKwh0L|F=v{d#AA%nm6nL1dHZ_>y#Qcy*)a7L~9z z;t}C@#UAK^H53SH$`mt3)H8^54=1BafdM>sv!r!>I<1tRck%P*0pV)9spkN}fuLyb zO>&;@+q;5CjMBi08XBd!nyRHW!&D*Z6QB&C#1K za2vL54$0|_9foT#*t1gnn7{w3v*%x+ZQ9qM|LB&97Bo(QC%G+-nqPA2R?{V94eSn|BRtMO3yL;%hiiXEpYAsl66m}=yc?OX_Rj^m>Vz#< z-_ep#@TgDoL(k1Ls2b*lk*+ZuwJ<2!P&T)ki(^AotgKcQmnRXfhZWU?)#V7WxjmE- zluid(pf2X~mb&U2DrCa<>~1 zcmwmt)Nf=(=M))f778f?;mOoMJ7iIYgqqF`xWR2x{^7B}=ECwbjF2#U)C!DqTNTBF ztL5uv7{azW>CqQBIQAi_qi!-nh~y?Etbl;& z81_S4>e)0J7enWTA#nwypS;es^?Tvxx%g-JI?;zXo~-4=oQ%~B+;?851@D^fsUVnC zihix`JoJxiGX!beCX8@d2Vzy&?I?4__cOkzmEVgk*BfCs6z(4WoUgl6$m{@hmUu9! zjJr&`%FZQGK6dQ;sy+O^D)skL+DlB>o8?qF8^KDY&NIX&YC*fYKkUjKKMlTlo7AzC z`Rx4uWoi+%D}m(wy<5jyjbgcWWCPLYXh-!9k%5nA)k|+A@7pdir<6lV5o@i3=)o|g z?7hh@^-&|=@l7+8fL;xySqYLd$k$cV2y}&3)w|jD?b-+Y(M!3H_w(;0k4wz#1LdDt zXkJ?xJ$&aCUJK%In10k+Y19gz94)-uiVH%@zrycHzL{ZOHAUow>uZr1D$NmQdLbL- zpsqSfAaRPr=iZQv+KHC&Sf*YGmQeDU@QBov>aUd)ikF7=D1fZJDfPUao3@Qrz|jbr zjoi)OtI0jZ20b=3c<;RjRY5A{Rf(jBqQGkXEYq(k;M~(l0uRr%ncv!Zs&@K|Fl00LDFV!Zt^wUr=14hLJMQey5$4dA z4hYQ(7!bo7#&+N|ONs^Ut1wO?2>QAVOE@@^ncn z`+gST&=;;#;>dg*#E7iOPA~5cIisO4VU<>8xWLZKYMg<4kkGIVytCY>aK!)a^HEpi zxRc(Cg#k_96M;sT(vRNz=FD@;p?wFOII%5(ME$q$n&cFT9pk8GL8vUj0kkf;FQ@B+M>m;$k2chC{ACgl1DZzOWgK6{~d}%O}l(DiB;Y(+D-&DX%j_5CdUgKplGVv z+#1k3;S=ZEgM=IU!B~Sj3sZ~Ft843Z&plcT#$Z2@H@lqPKHT?tzB5(jvq=1H5z7R=M1CR;jF7mrm%`@SeSpgA(bM!TA{Hqs+jC zA545B$eLOjQ)(fNzHV8E<44wCgrJA-u}MQ2v*azjVymwN5gDf|#gh1;vh7=w{>nr5 zGuyHclO%D@Y8<@x=aVEwl#2PuLDyy8)80;M(cTItr%?}eyx364z-eJ>Xte4WEhp1A zdF2CK82amBNiCipUjJ7(RJi`CD26n%5!>c%KKd_CzI?MYGU(E``|pMM&-(Jv%>W4` zA^N3X-P}=F!Le6UI&^8|5@(bZaOqz-goW^LLg`5Z^Enh~HwaY@V#7@6&@67ADE}I& zc1Xu+Lhz5=>=A6NU;e)!SvcG+`+ot+@c%2444Y<0dk6r}H2(`F538w;Xtel#WRDR6 zj&j*fhi5ypb8~ktr~0u){=Z0aOMCH-5Qe^Bfg{*x-5mQ4;;^5RbBAl|4OUK7>s%+bnch(2KC=VLZHbcOz5sKD&AZ$n=J zj$#71jaLNI@1}X;N6qvZq{;0r&*%#>5W_U{fXvAqE(CZ9^7wWah`}&rW6UB%Y>A>D ziOd8|kxstQRC&|I%Api{f)m-{53Z>di@6dSM`1H<-pwzy-N+H1=6;8rgD)r< zSb5yP{6+1y7wa*!1d%bwAy_ST?%`o4 z^}{$dx~$?Q!E%B49P8gkcbLJD>yVO6oOu%ngf5>}{+eQa|J=f01N;rri)!U#%oHPS z_i^+o|JHjJV6-1roX$IE5V;z9)_A;}n8P>x{Hae_a#Je;SSV`>ZIGYoYQZiqe7Fw( zY$UN)#G(nvU4u)W$*{ZpS+=!5zsJCCWdoJ3*s$oJBUD0L804`$cWzLcV#&wWeO)Ej zz5i)JbG=#_7NULc`Isw5NMI}U(d_8mvbQE0K7KYTHew2U@X<>qn#*J&UY;EAtDv!? zwx@24F1b{qhy#qgX2>gOm&?1!+;v~N$CHP3fvtSBKJ{?fUw?ZBmrmC7m0YztuCGG1C^K)oYq{jFNe0Q*$8iSP zR=j?-x`l9FZu{RUmK2;44n*ejhr@}G|47!ywB4)bs**+~2^aNJRZ1IH$2|2sIglzh)P zY}eh8WH+|H5C1=r<4f3Tn1aKFola!&@y_44FSyFgd$r~9^Q>$c|8nDteHFQGkWW1^ z&VC>zafwT25{_D*f*0leBY?PvfO8@IIErSXPWTl}eOi8~?fm=4a%O>F`<#1@wJOj( zl|8sRC0xKuG1}x$Q8$SQ8^7z4Jc({+jhSleBsMa435~Mr(Sk!2CpK zl}~y~WMa)f9$AXAGP{_K--M@Mbm83o2i%?(nFQQdInK0ViVqAU^*SvzV=d5YC1i0w zT)uUh#IE{p{BaMo9RF%z<(aVm?BMv9+J&pJ=%aZ5Fg|!AwELn z+i}w&3+by5NV^$-w!Q)dHciD2>Ei2&&egt^;W++9x7ZqZg(VV_9#E6o2uzMmj=$Tw zG$SW6BnphnVz-xTy5%?rF~sd@42#a{AI1rV+0kCF%+tZX=XRuOZ)`5Yx3sS=TACTZ z!ech4h$~pOI%u_$0Uy9##zQmz>CW zg={ZOAB4yXbC$h^Fb1~rc%O=RFx2MF)GsHx0|e~b*#ro^D$MyEpzhl~qKw*6?`W#GHWA)Cy$>Lsz5h-XE4BJFa2xa%l2Qbr9} zeYOb&qnSufHru!^rpPN^F$?fan%KA{2MkHh$Cs71=pD7EaG}|z?)dg*DD%hfX>j|) zl1v}h3pS6dOj6+iDW=SVcYsv7;B(uhy@k5RU{ zV?Lg1Q9(*CmJ+JWnR7tHNiGy5kt3$aO8GGz1UO2zkEVaJrlbSQR+^7x(l>6>5e1Su z6)Pep#zVKXWHO8#hid`dMC($J=H9Q;igXWD#2IXtA0&yT8+w*xu6Fo!x&0*8Q+l{`+!3n$I#y|>hC-jHvWn}&ON`4socu} zJJOmF_ENY;3UKgwj{?M`_x=qe3n*MA58Ny{pVD+o%p9u;8BV*oz_VQMz9_z=^AR}E zk&A|R6@1pF?Yi)nl61av@$ty^>!JD1sVvSDeSgpiZp!~xyM!GfV17O1K&b&0c!0xGo*=SD-`)3GdlalxH%!p1i(W84Vt} zxnC;T<^xs{u+)SX&`?|^u#Nm$Olg4*c3-}ESWB*gX~#`2BOjvc;>?OO{0$!A_LhpiclFa zLU5!ISSes0zC$t|hglCj6bunBEc--rWHs=*#Xuek&++FvtN3gGmIG!X>?+8=wn7tU zuAi>Eb52!p8(K*;%vdl`&M8SKtGuU~1u2&ab;hsc*wNMJrxAQ{)XDTd)fvE#I{}c> z-(QbXsoi83zd^qm-sracQnX6@m^&rm>Cy4-fN<4GUogRiB+r=r^UccW%QqO4Ux1fY zq&!15@Dh<@ML$Q^kM3-Can>j&yZnginr$dyTFhz5LawKHpTXvPOLDC;GRE?Y3iS z*Vvq`N($k+y(O8Bpw;u;o46P2gz1?yc~%r7@T*{LEv_*twq3cpkCDYiaIGgEW8cqO zr_-^KM~Fg#yje?JKQq4WOkxk+!pV6ou~04r<@03@aSw+vNvEpd@yZyfimyo8@?$DZ zd1JBP8BsXF+vOEdC7Na(-WQlE{A-`=)M2aVwOe0%f83=yUuXNu5&L_0dEJZ7$SxK! z_+xZaQ-a}RBbDA@Iv=l8tNre8lPDk=UL z0aM6dnxnOp(v!T+zjE_CClhxg|GWb{Ha1C>do(X*fz)J39r@V$=*%tYsbKcC@Hyqz z7-tTMw{}lml88_b^y#f9pg}ZGHyH~NgoA(IZ+e0(yel0k5zpd4{HpD4XB= z<>>DKPt=F2opf4}d82v8U%^YF2--%p&b7uje}uvT5sHCSe$* zle&~5Wx748EpfpY7DW_4Gw!qT<@?D2F3Nw*)O>DM?^vh7aieWpjU``3esl@ji2?Y`?umwQ0@U%GdOx4$!Kkpc15}0Uyx+%hyS)IJ z!Z*-XqT;P1W4{g$>i_Wy`NYMcUW-i2MMdLC_FbJYLopG|U!wx32Ld-8HB5=NFOL3Y zn|tc=q}^ki&BFRBEwitqkW7|T110nmYy0rE`>{TJ-%MkhlKrwyw!US+gzHpAIvuqH z?!l=*Z1~>X z3o%RXrT716Gl>}C$Qb>u%$5=6x0)Eg0e+g6u5HjqvyT1+Mxi1l%O9~RwM5QN7S{tW zljC0BKZAEBB1z3x6KRHzR5RNDQL6Z?30FxrNB$E&mKs{ws4{uVmT#+~a&>}h+Pmed zI@if@o}{lH6ou~g3R`GXnpz`pNu(t;^!2_0cJXLosg8blsC%9DVz(|PK@+nOrLwD&FzeN&?>eFPiEo{}Y-}cIF3}1u__wq7dV?G(xQR}Wj}D_EZ-r8itsg3UVR6vi z8f5EC?yA1m?%h`iG(wq-tG_7@+r=+{I{LhOozGg@ln?%Z2}cSY)DiAg)gj6g0L@bT zhOHIl@-rehQ-17>B{^eXpN?#Pk(QtVW(0SrI0k%myho=xs>X)sB;NcmBn4+njK(r7 zfIkz-Iyk8uTqy3-8M@i^;qp`T63?N8&xy-lvcTU*`KQ9W1(2VwZm0O;uV;&dh z3kUh;Fmf^t(j8iq0*u&tOvz@5E-Nl#u;?sWz$MI z#am%vo@1USM|T}PCp42p!r>zTW=RQe?@pV>X%k&SV$OpH2KI!(RBwy-bNrO~1bKS- zsioUQ=0?N8M?NcPlml{V1$es~r`Tprf9va|xiT3w7fNPW67Z)f)`B2FgwgsjALkh5 z3(dF5D{GZmY8!mBa+fn;S&Jj;lN4@1vpp_BrhNR&#fIB=H8=So1H6M*f2SDpKhnqR z!#WuVPNtM-A{6%J{^UWZ3F{Giet7yHp0PDe^ub%DAI3PkS}sz&dI ztYo`c!l}6=KNK~00vOe+d^Xhz6^?fR7PA5bhy>ztK-LJw(hpdF_K$g6jkZZdO-Xi} zw@cj||btOATH_*0W*v3@nKSAVv|3me1 z5uh5)!(pQ7L^37yvB5wuA8GSq_hQ^7mtH4P(Sg!h+k~r)*TgUs*{Q=pOB%jCl*)@^ z@zc%cBg1yT-ngeFq3hB%yK*A{`9Bo{_5rp~K3D1&ceEWUUQ)k}4Wl-@7jgDPO8^d^ ziqEK8d5FRGo0PbN8&(b$K zB}`v=k3<2?3II&tEjokpc%x#OV1yCA)hKG)eL=y4WGPoZN)kzab#S6DBR2;@Pfd8< zPkgPfbhyuSk3q!v`zsc)zpgG8s(x>LY0Rdx?jG*r${=tRRe$cU5#&V`7$7bWh}iWu zEuEAP;3HSt4H|tUX?Pz#=lef?Y>(;9B$rKUT29S+!O9_jM1}7as^|u^D145B^Ps|z zJ0smLe`CdxXW%0H1B%%*W20%s5yM@)qF-{iA%Fenk|qMXQ4`63pK&&Kq)Nx(Ria?m)W6D;66e*$(zWwo^BPjOSie%9Q$>1ht4P5&K7WY%0NThpJAFCI{n9pcUOwLnC{9g;)}9xv6_QM?syt7QT+lA|5{&=FBif8AI_p8uk- zA9X2qKX*-z-d*F5dr+c5^hDt9d&JZnq{KKzD@i>26Y_z~tJa}gsLkBq#_1hcoO8-q zzymf@;IB-*gxQx&^-H^-tVU%~C-g3!=l;9PoJ0k)nP+I zf(C^*Y@>tEJU8Z4XDZc_M3f`Vx_?)w4e$xv@BWWiaBU^U`eE+YhAU`?z=C@ed+}L} zW74^?A~i#k(xkH}G2U>)oR}t~r4q!nt}}VtL5hHqg;|8sMH;?nI{5vvEi3W$lsz#m zmGhZVMVE8M(9bw!IBC3wJoNUTElL%hPGQ3-_GAjT_Ft6w?L@3YSh8MU!HCy_neRYH zbzdPHabHiCPjWwRcP4KRMqd3aHc7o1()2O+Bw~tc5Yvx$DBhAGy_~l&eaunf`ZM0( z6l8OY76{-R{Ib6Tq##N5RojjH5AvOhkMP0KqBS@WDT|)1){+;a+x@!;Lrkj6oT36Y zaVxg@;8hMZ+CRz^cgpC>vEXC_f5qbJ?rpmmZ|i~8Vv1BMxVrg;b_G!P44u08e8b5O z-bbo)+$EX8?GLw$y{PXRQ{GUW?YMD%TLW^FpgB(d5Zr5~znoM`QJH1K5 z1vwYLp~T4#WMGdBPD*>m{6)x1n{X&^^Scgg)$#>!DgWWn;171O%cUA&L_DMhz+fuw zbdP2pwdgek#g6)D&;1~!{qA2b&j5vo88?I>b5|m`tzAO7TMEmL6-*LKHm47cRSn75lh6a0u_#w zo*Af9*D2UtTCo?c)AN$avr@qvBFX$}i%P+t$yOSmu#QYv zc+96?wk#K^A*bzG;=0^8ZrvG?3Hodg)>ShIi5srXUSgtiI$D2_2n0<-7t~Vtb@`SP zwspJAY_H)v9VG2R@Ly)r7dGWpySMjYgFN_5oDrPrZ$ZS=UA%Z;7WIiooN>gn2E<4i zV&d`6GP6P^a^LUwSR2$ji2;mdchuC?-}1VK@N(ftthwa(`&Vx*SYKb)2BUGN`;Oa7 zb`my~f`vWA;?18$>%iKNXESDRwinK*zf`WgmFCW2dL4)T3)k<8$&Y)d)~_7yC=$vn z!7gVX_r#i#u)vWxB_r&lEbtp?MsHb}t+~28!Gn4^6c~|0tV)lf3ZnqsiI+@#7f8;c zg_iH^H6Nx(r2ZA)-BmhHNk^{xR`UsP$1T;Gtyg%l+1Nqw(Qcl)5c@TY?9ls&*X;I2 ztFJzqB(1#3g2N+}z&X+@Q(Gyq3mL_h&jJei>f_g#gZ<=$7!;eM$x-h_z{ygbzJAY< z`mG%Is{!jY%EL7C|5@#t4%6+Q>dEWFqPGv(D8{F7*u$ zH8qZ1v%o7MzOUl;IaeGi$Z}_X*0r6WJPcf81ZwCqUc_4=bD8 z6S<%0mWFs>yOaEewoP3KEVp`hh?Htbm(QLG(F8xAq$G(TvbQp~jSsY6)mmOvq}hS} z4)I&L$}phyYtn|_5$1OOs>Dk?M4)u|i12m?sf{FTdHLi%SXi-K95Y(HdG#S;%={VV zaLXtsAZ9Y=OFY5%LaBw~KJ|vPb_KUo+ivB<5O>NicQ&K6>424u`A%~%I-1G5o^h!x z+XV3VIHl($T-|=K*3hl-`F-r$UT5Y7f|WGrJ0iUm{TjdWSME*xOrE zJMVLym&BAUr86lVx)xx4x!6tZBN&M|Oyt;-$=1{ob804^>52(lMtBaysnZ*E0x01| zpQ?PDmL`hd*;mjW5iraUc*aK783!B>9{dbgWm!&iFkxO?dHN`Fj_SRUw6fay=Urt- z(o1tsVmFiP-pn7V{Zpn=dG{s#`9SEzD=`z_qB^p((xoKI0XL$ba;foTFKu76Ye%|U z##V^9Kl$BA_LyD>&+vP`n%OLFl1)en-ZH*jN_*x*g0`1vsqa^y<-ic?NUV?MT-B>; z@9#A0&m5KQIL3$A`R@9%0x4l836mxVqZ4#T0b&JPiH40Z13K~NpB?JpMoHe4XZ=FC zdY=I;uF@u+W*_5y5lyV*HN$rE{jEyfW3hZkGh^R#NSdBosFj_=ba-@oCBeLKAN41w zDk~k=K(TdpN(Es3h)vDL*XSOO%s$ah^G7%5QeS$P_$;@F*ekzJjr&6dsZO=W65(mN zE3Q7dO*22+W^7}6=3WMPtY&k1Fx5`p*%R+@gS2hnzlQZ{$KtM|j4QycY%lu*=fr?F ztowjGRuGmysET8qZd^R~S8FQVhW3XPCWq{k$I$!nhW5cdOvW^esglQFfXwS-H1v_u zCgV%!w81MG7X9~+7=VGn(W^3BiJMXOA2@9sC=yH}HmZN$9ku6>yRhNIUe4{Fw%7x; zL9@#{D$<#}+_~vW9iF`hd$2-bypabLF>F2a>eh>^UE=-w?VHJn{n(H2V7UO%E*o3j zdK#MYvX>}{F15QgREdG!lW_^_8Y6-XQ)PO+WX(p*w5S;q?vj#t&31+LsoU&wXr>X?yea0AQu0R z2gL;2Yt8iubaF*Rxa-cgU`PEB;-RJdV2`+)OgVWE$K1Mcugr=)P}K+X2?&PuIXOccJm|l`3UtNRSQ8&Q%_BPKnVfUTila9L`@t)WA}#+O zv+(st_rnc#Z($Lx;wrxB3S0F19|Lw&Rk9B{?dB8H-+@;jIP4@SZVk=t+obLM5`SHO zzuN(-k0q)?*i8I zELKs&B>6=T%vA{rhwt2b&66t;I}!~te}CA+{dyzpCL)aLu4&${KBuJ;DZ>P#l(RZ@ zI%AkzFhRf`t@xqwP_$#j>Rq=-*xZ^h|Cd*02>6MV2oa6Bug_KO(>eY|vr<~eLOE8t zt8^uQ3t*@H=BTBFVdFwZk1g^fzznbdDfy-I134N4wQPvZFu4(3Xzk+-Z{k9)CjHjm zh22W;lVxGbm#ZRz(S{&B)5x%VwSqZCgj6xbS;9j@m;E9^DtYxZi$^WAsWhe+CWl=8 zHt>*l>zzAx3pHBm1Q=&_HD$M>`nW1aG$W?arLe8t z7|-qa0cH$e7P;SLeNF#vq0eN2_K^CHJzN|c%;udT!w|7b@EZFK~p14qQ{JU;07r7I)dye@u+any}J{ zfta@*)yA>$>U9FKubg(zy}f6e-zvS}ddq?U9tCrOITUROLvxZ5{B!5@=HrLw55@u3 z^!@$qZ>XS^suFY@R*tqn$&rKT$5qI}fFb$czvhE^^%!sIljs zuq~x_O3$k~l|EX6-D zRYFT)kmdyJhh?;B9Tyrh_E8SEiNzXaj5RJfZ{#;)#ab@Dc^F%U#-`ASv@GK$h|@aJ19To1BW6=4TlRA0@uo3h|av zZxDP&^t&j*FErgZ%EVasnTR~fa^5k8Bq+IAZw%Nd`5DVEJESYA3GKXT<^HxKJhR@z z`lf5|kUq^8IkP1OYOY)1Xzs`QVY^X-Ft(d9J^co-FI2= zZBG{ip>AS&q_digF7v%;8&@IKyqihI>D-`dtorGn$3 zAHo{C4%kzFABxE9Ml@RSjPR&x?i6aPHM3g|I3++>$2OGLX02!3BHg^+Q<~)#3kT%c zW1!#3h=b-ne$LQJUNwrXr4ebhrToh-a8uz6PurmaB>K-TGb-v(*}eKkksQn3Bru>$ zR{XuWEoLS3GK+}H-`7U*62vHP2cWt{Jbyw-ILG*Ghm>cRTOh|I>OC@f&e5JuI@b(g z3~bqqpd4g;%7Dic=P^XnAslQT@ZSh~%b>QtFKQS{Db_-<2B$!AiWY}Zytum+Xz}7s z;1(+mh2j?EhZGA^C=P|<65NUh2yVgk$^V&o-mmY+%-o#0XU{%o_Fa4JwMrr{I=;%6 zV2F8&VOMWHCnFY+!t{`T`3##(CT?|n4-m;rmC-XR-6QMO#C2rf%8|9|c`no=QGh%Q zBv9N^NUrCM<+h_O71_`yQ*eef^os}d$IVmX>oECiVbKK2{TJMVg-p%k+UR>TflXIHhy)0fLRO<=%liR11wOHw$63c*hS$>`DHq<@$0A- zGYghPd~Lm`&IV44xO&>q^o?heX>iF9b0e38nRy~29(n4CW)B%#bQzSBb6-f93AJ-P z>g|-HpPNeKT(8hCpJaB55QYMiMdy<0W0Rj@!lSrQ&eNhSk2QGDU-3f>wx`|ttSlt; zYu4(&jVb&04`qUkJ}&?>vV$xVlP^A+}XuE)(mj||_w9d_wM5i`Kpf;+3dFL8X{ z<7`N@rWjl=RU z6Bl&T;lPa7f^M^f^NjpoIDi^2iCA^QKuRWn$9jtBmld9Q7bMJ#f-Gg{3TZ0p}y&~7$lbEoNsi_h-3cNs8A zNeW8!ST<#zidVqK4YD&Pr~LyPOe?7^nuOM?j0{dT9h%G+yk3}?b*2@OKBY%(x+}$| zh_CDku0;Xg8jWEZDpK{9(^s^T7L}>xlbg}rgKdjzLs90CFTt&c7uU6CoA`nAC@;9i z+x_Fol%nD+*i4n}!Gb=ggJIQ-qKL;>nr`dq-8$!jdz09P-S$v@8&12B5iwA23ezws z-*gCUHl;l!XC&J9R5F3hs2tV_Flki!BFfi$&w+V|dSfV`dF8B5yLqKQZFjUj7zff; z+s=KDYXSTDqtiRjr1Go4*D5!fRUv53i|p0_h+cjccysT3w{Y&uhZo_ULZR{!&U+0Ue{XptlhQBECSe1WYBPJ&n-D$c5!=xU_`vzBJn-Y>aL^_DPb$pdSn$h0o0Z(}!)u3x02kBH z^SV<}kH6=XUH=O!A8os_mI$bbT;O@uP>ZZRq$L~4kwy+ULty6&Ff`0O7~HqU;YQQz-PquG-$O<7)X zirb8%M>Yyj*=6F_Q)dLevHpLF)tAkWLPU;@`dqlZeNh=+Gnas`8pqOm4BPIKo#Du+ zAYzcp_wvMjHwS)8kW|vCQ_(eE{`mhIj-M z&0m@c=HrZ)GLI`X@8Y{oW61wLEIaZjGCRZiMDhJ$akJdAo!7F`vXbc(VrQaauQ@tY zgj2l=L4#VQ?*ZIw5Bq6d$JTUc=|~>bh-lZce`vyl)p_p{PODB-CuchkwowN{6Vqt3*YW|O%y{EwK`;9;Bd5Q+jh}x*p@aBp%_?7Ny`d}cUPSe zPnyEc@Os6x4Uz6A#;;P%I$p#7()2E7TWqA|Bh02p92hQQIymJH0}Pr)pO4;szi4E2 zPgAEin`J-V+2tM`bBE&uD!d@B;~ujmrUm_enqb`;8@;MFZMg}j z8LxaJU{=0g5WOjRpK%!-@`vHqXJJg9ZFF%0(HYmzWkFal=HX021I3TAA4}%*6j?pX zGV|dfV$?(q+lxKqoIJ*9}7U}0$%h;*$l$n@YW*|ub=6}&tNx^9I$KhvwjJ3pf?70Z;C)=WC zlmR~*Gb!n+7>+Zr)yCyn9U^hH=C!~v`@b?QQR1?oB-S;0lfzHiawVECKM>#2U_KUi zWA*LglLeMHnNg1^eO2^~3$6QJ5ugo1!$bKg;A29l*=SvAbMd9bf4Hb^i6)UTzM49K zaM*#%3x8<0fWT{M7|Xf$k7@Rk48pgKJtKMx$^V45TTGv~oDy;D;_mt}LFGZA;8WaO zYml~Z4BIG;Mx2<6**kR@cgXkmQ-REMxw;RHKA$N4a7nkKxP8$an{6@|xc5>YS$O%D7Tq5iY?tyGWvwgQ#atH8QF~K#L48E`* zoM(%Sdi*xll*APOLOL#@Im2#7R!c(cr|+0WoML2?)&ubZlFjVthx?CxmFeVNMe&R> zm^hV+2pS%F+??{Wa@Vb`RU(kewy$hd??BeLuO<0vTP4N(L+g>N_35L6-vGqYpbW4^L) z4>68Oh=Kjm1@@Y`ZD=NqXEA&1gkY4wH2|Z!HlhjfbCaKUt99 zag~>YF?lbU67Mz^W_B$GccB1cM(cL4%lYHfM!1wg<^ zWCmqp38Ew2<$g`XRdDH(d8H63Cnz`;)l_qK-FijFDrR(Gq<;ljBmRB8ScxnWXaKur zgO=N|4;bU^_XK`}FyC@>1>gz3juj06Z_~Z%i$BL5MQ)?Q5%2a|n|oSk`M9JX#tvGkwEaqtgY zeLmRG&&q2G5P`K?dlDF`1J4%9S|ciuKwE{zV zSin63^3Z5;GTW;G zJCUs9PnHI)EG0zw*55%B#PSnC9(SPQ9wom8+qIdHQP4K(nr8EFHCuDKYw_Dg6)B@( zRtTn)w2x%Wb^Q;=m##Ihtx*#Byuacw&{zS0p(H1*D_dd2^qYLC4(S>)4EpvK>T)iR z_-o3g5PxYkDizZ+fM=xfDyFBNRM@rM(A2uMnn)7gE&=-nFN|Q5>dO! zjG(&CozLN}F@B^w)R-|muVUsq6K-Ex2JbzAwUf++WP&_AO;{n|(`(4Mh=|XgB+`RK zyQ30Sn=>|Iiy=(R2M?eRbN@suPs=EdTy0GqcsH7}4 z#a^MB0$+K!YCWWnfCQ|}dqKZW8Tfx))4N-7tH1Jiz+`=x0VVI(qxB@af8lxzh4PyW zgL;s?eu!`ru!ZIs%?8z-WHzSY&<&(!4uQ^r&+Ud38e3D7Z|&-?yC8(;&Hjg>@y?(5 z)=+pW3vO=CI?I!nn38UoFTwy}Pa*l8+!0jWv1G~?RxI9x~d zWXGzx&;ZH3eDRRdxF(NGujU_qFc3~8(dc*vL?&Hyaj6T#c76YobTA#y7TZ);vN<~M zG+wn9o#s9t{a^Ax8e9cxeRYyW<8oO0oiK-O(;L;lBWHjZp4d*vxAt@&)~&yvx+;*l zcC-Zevw{=iIF__Hfi;}~`pS}K;_T0AZ;ur4NE?Y#@wDo z7}xWwWBu*2S2M`Je>|i&eNX8=drDHM4<96W)vUh#0=_1wel$(I_xb2IhFT?ZzrDFw znV_o}js&Vp@R^>OKf9}>KOUwz@2!KxpOzjWuMl#x5)|3SO8{0j}jq7W)8;w=rE7FTpk!VhTn;rZ(b=mYu zo_~hQ2;3@JA}Qyh&s%EYpbVdvZQ^q*)A_Sa)Q9!!32FTKO%k=(l6+)Txem{Uy=_Xp0EQq63HX+4fUpoa^Do69>MXg~^?w zmRF(b-()Dp>Pn*u(=zhhyE9ZXC70H6DOE>2DO^{583pN$eq%!Mev?>|ooEwpF=!Hh zjL#M!t)g{S#D+`C|10J&YuP5pmM2)s@dGjgsASxj$IH|i1nGPUZ~D!q^FWsZ_y#gG zjm6oRV1Y04fpktqHU}PMAhDD;dToUg~I*igG)5h^1NsQN?rOIe97wEmv?QNwiPpZYRvw}Iv69J9< z%0#|hg**EmhHDq)-KM0uaYwH&XgrCTF}Fg%xSod6Mtx2WbjL|ac3ZfrxXu6NYMY++ zM-5n5K)i%*9xbPop{DX z#ryBVpXG4(m_)Y8>je)P&;7ild4SuOlIaZi(rFU!4JLKAw-^Tr72j)!>GKt|QGDD< zbiI%!l4p3fe&ot1=Th`7_L$ALjhEkHh}r3ClJs}uI|&e3VrW2TK_7!M_ps!fhrFqQ z8dk6_R;|#On7bdHdq8wqQnX0qM8CZ3{B9Vjqq6fEaT~_$$DG2rWzMk0$x47%P+p+V zZG$xDrQwNNue8e|8zr8Z2W(K(PVUnyT#b|e8a&2Hv9Oimj`DT=U#W{Q>>D-nM^lfO z-Spq*hSs00KR>=Cjq-LEL+>Q}__Ybf#iE&V!vwZRj0y(_*`E6z`8ZRdDlc(Xm*2L; zhYHv4J)x3B;dP|CY-R|q4_5$=R7|8tf$pzI;g;_vFp&JolduTbJ3PY=0c;HaJ^nU! zLVa!gz+`OGUJB22`OlN*uJpx!3+&J6V%eqN*$6xf7=0ip=kIjFC5VTS|GP8Y7N|rd zfKQ{ijVI9n7Z$b}{&-TB*Fc*KPbbOZ#V-Rj7MC5}5cpTVsUIY_P?I)b*HT+yC%tk` z@&~f3ZJO`G(T!G1{o%Iyjfkd*tI*`K7OJE)@&RdGQcZ+!1dB-)y?N)HJR61fY+6lP ztA8ur$}X8|3#WaJc9Cspin9nwX@E{&c_sFbL{#7T61YU;3Aga&(e`FRL&uqCg?c=_ zchC+JM;y^h->pfcd;S0~e2yQ~k%}6>>uZ0+4w1T57>7DrBf^Qz6+L2j6B-FggbFV0 zv;7NpMdeP{WhWkD{|rw07rSX{w-$W=dl{jH4*mhVOy5!@A{VS>sQ%YmKg{oMxX2Ao z{b%!dvavg9j`;#Mp@5z=mb0cv`x;_sm*9IL7V+z@K>?r6>2@jJS`OUMi<{{mpEs zZD!qr@lvYEn%x|*Fk7c*%x!|FaDgX=@hsW?s?anA(ix=W8$IxoSZU~MI@{Ki((Lz= zAIktNaJ9;IbvU}W$6bJGg0K7pPv!)g_j515Bp0*p3cJ4~MFtW?c@lid#wo`cu59R% zUyBGReX4D>n$mVisZ{%3*tXV=E!m!nc6t%skC0WD3vvhet+IMUNS#5Fr#K#(KLX04 zgIjFB7AeXbNG)@4+&=Xao0>lB4UjwEz52;Lhp|al`y|?HZSEbLB9QYRb^3EF6#`21n`JN4WZ zb0oBKr|vrtUN7Yk8IrHhn8Tcjd)vTDfNl z4Q-iz#vgemDk@j;X+|Bpxls$Vw@V~?jp{!!c$~&}s`L~#T@bMXIi2g!)HkgZ94829 z9+1F!!xJR_;p3LY|Ho=U4Wd~s`RL|tJ&^zF+-2~opGN!NUFNu^hB{xfcs}YC>G%p? z{EJIR(Cnc0qQAmgDT;F3_xS0(GE()<;Vfz+TZ>|r&{O!gQAc9*BWW$ zp9tqnrzE@&7X#kOhuMYafAqo#A#?xthsrZtPLx?L8ywxIRf!7?wd-4YAatK->|q#tL350VC6b z)`oIVH(-7@E+?8E_#nQbeVXW{oNd@ohKMf-!kZ#9 zJ_2_&+J6bZX^<6ku)1P2{x|Pv;f2!4^&J8p0O$L)z9kg&5fShRwYUs^Jca?QvyYoZ zcg;L|#9e}V-q$$y-9X0;L&9~I$)nkx)_prEw3kO()$}js(XE$7Ll5k6=(aVP=%Kjd zBCqdmWVw#4W$E*&8h}_{dGNZt13hlc&|kNk1now+1nrXA!U6 zAv@3$Slbr@F9pYU{5nq?W{zwArZ5~_=632H$M~O(7P0QJD&WrYLLC$3({Z{`{x}rJ zbDJjIwk_@wv@9Ih>G5zFn0wu^c$&=9c&pRCiqY}1$jk>&MpJ!QxI@1B+&3d#9>Q-W z?o|%AJT2_*&Uu=4DAD^zJ^ZFNKQj|<-M7eDd^80kK30?5C zEK4;hmjB8H;CpPW`7|9}qlibgg#T*q3%6EY(+E6o#gDpJ4e+EiVLsW&dpTJ(<1vKo zlUFSF&bh?(mC4?Zq*!rNLq})j9s){39_}dKB!78lE$vWR=R$wlTzNfilSAd!zj7;x z+{sx4V>SOg8{=nB+CVwvd{rMfjygPnF*b>>OJuVfm}_(Sw@d1fE+uz%H^@mgzq>4) z-4~_%N~+L$5ngI_>_HO6=!;$MW^MZS#M-NYgNld7R}Py162gKhNrYl!EDLw#C}xxWv-=a;ZixnmocI(7In|Hmux$IM$#7?r1tePEB@Q=t6@0gN`*|ZLfA{JzWBwv zDnJL{BrbTucQ|C9k;Omke7i!X7FIgO0Uk)QKM?&lsW(OAxP*8jg#AJ)8mt_BMDST+x5uGNeD6!xZruX z1Kkbs1YQ#4UeW_cKG3t>f6&`4;iZQ|pB1;D(d5e?G4P+zsQ*VSuwskq%00_8kb3a3 zcrfGfT}D0*@<`n%bzJ43e+Vp}_0|oSmMrSy&=2Lh%hAl4;QB`^?v68?)@q>6OlzyB zCv58M>v$9V5na)5gn)GDbK#h@w&PURyY04)1IMFtc>B&4^ty%`Kp3c-9}i!1nlH3n zzc7ZmK0LyLaAwNqO_r;DdsJX;s~N)gy|BdtJSp!Z;DYE{8FI;bH#ab3L6+qqlst4q zHPFkVF$yob@Y|3;%g0Yewf0r=<{0r-`)XMs{*@YM2l4IzgP}fbtZvNf^^kVoe<;}f zA<@!7hK1K;UHi?#5a4@~$vV1nWm5OMqftCC&?)uD{E@9^-M+fTY}SXg?@c1kb z3(#o4*7{Qnpgyjqm$2Dtb>|J`ws4Lv2BTWv-2T^}nUCnr&6 zlj23O4&8+*2TikO(CWQqBih6#j{`Z2{!q?m{YFe}W~Roj96MtX`NMBi?>E*vbmN-y zbW4;m3K%gWh|SbhQ~p4AvxfhA}Kh%G{ zKH{s2dN5yWooR40?hQQadIrT)i$n*o}aV^JD{qhd4uA!a zq>$!wmB=nB`@kBssZ++l6|Awmmbl$64r&BXAQXbqO^;3E(Pw`yD#VU~0nb zu>tvQpDjrh$c-GKs*j+dtLhyGO0rw6Kb>WveZ>PFCt>a9IPLenB@b4YslwY^CZ~ze z_G@Uz#vSY~2i0+#Ue_mavETA|Fn=leuz&l|P40Hz_*fmZm|(W_7OikBrH&6SuV-MEQhw3PejP84mknV4Q6&KHuB%?1_J7yH z_wHPm(fTDtFD}1hb?dp2Ncb)BtenR3bevqTxVzuNPd{tNw7}_(OXn5urmwr(y-)B~ z#2%9$15Pp?Pd4Cp!?y$VSCblscRyL3V*I8Oc);hkX2|aL)XbJ!;G6m(aS6<%^~To4 zclj|0CGa@2Uf(f%Y6QR-eW%l_1+io~}T< z^^v$$Hrj@>m+aXUcKUV!wr#LUUKA9H<@DPr}K3j`4c zRjc7~UZS~1$tw&l_-sgKLULcZFGc&PN{|gCBk@8y0n1t5e)ya3lt;eCq2zKhU61{K zpxn??NY!?+Y0;6Dk`hfcql+ck%qOAm0$<-ZeuR6R{q*Or7d;Yr67?IZs~JVw8HHzs z5m4@w@+{ee;@AtAZOrhOH*oy)XFPq-mBJ%6*f{bXM;gjziBa|7NVtGSf$~f;BK*@E z|1p;)Wj;oirV2TRuiRpei_~^vAbtZQ46ZOpu_kM^HzUC~5H3Yl}1`Z3;CvtvOK)!8&(2%MsP;#|E`@vz)7O|$Pc)_1&97gXunW?Y#z^i#?-5{CzjjWE7hlGy1n3dCg+ctZ@ zo1d3$z>zSp*bVH|Ng=VJkJu}>{Tere2{&x$ubPFxquVu~j@zXzkJg{pFLkKSdts3U z6o)Z2v0#jsR%P(QtSuB#$E{>(>S_CWAvhZL2Y!FYb9Mc=R(H*RH$Z>?(4pNf>& zLj_%ffX#Xs@mpgrCs~Db#r@Z}#N(WwqUL}#HT!;~tE>Be-^vC9%*CEbG+lig6Y)K` zhPTf81a&V3tw%Kbw7!*Ew-y2}RN(C=;-e36!0VyNqUl=aQ75RYWJ^&(_p+^{YH4oW zjB-dzSEcLn)rF%&K7q-GY#Y0HKS7M!NI^-N6oz?Au%uol~{d5TGW2?m>G|V51 zYVe($bP3v8X?GYy1Jf8=sf$@W05n=uA`k+jt!;iXaw1+;0|~ zeqpbpMr;uktCtnowEu!adOM)N1aNu$S>*7VcgE|WNXm6m;Bk2%3;Ks_wADg=pCRjI z>tpeI^PeBtGpIS^On7`c6po!BF@o&U-qgeIG-&)vMK=j|KF%b#b0iLO;DiVl^{H~U zr28fjV^Qd)Q+Bid*rRN$tT(SnraN6_{2Qr}ZWK6;{SX@A`*Y5}A4+?j&`Kx#Rf*)@C2W6Z;B4!o6mj%jldkF;g zvK$zM)+sohUx^8q`DKzm4Z>U?*__tw!I`R70Y?pdSO(0#%6)KPcSNjRS8^~hCGRn; z$#ZJl5Ww>3#8pMe3n;o%s&ggLE_^S(cu5i~C=5ojv+9wtK3C@TYK_S(l7qgmd*H>U`*MX3e$1j$-F0i)yJ$x`weI6 z-Kd3xaspGf@ao^P#V}t@*OMZLp}OQZnaObo+rz32e_l4`jZWeIyKAadm1y4$E{V*o=n9&iMO(_ zvVsjiXV2w(ShRSLPHA>4QkZW4SzU+^G`6~OZ)~IEtky!mqAtGHCQ^YWpnx~>eGG;~ zbyYA^sX%E)j#+>N^NE24_6I#JaCnov_dkF3o^rZqm13pn_xecu*KaOKcBR?ryozomeB1}pDFJ`}f>#8v4M(&9fkDv#=j_Y5rpc|L=b+e`*6ZG1 z(5F+5%W97Z0^Wz#pAhh>%toq)khYB7aQ7XSSG=`7vaat4$Qh@<{c3`~N=VTwK>eqn zH~j&Nq4I$vlfVz`_JFqDvR|xHiPfSupE$x9X3XJbyk8VqkK`kzFiZ5mT_A-CRN-g2 zq2-&EQfG55kNpT67f2;|TN-JBdW!@uvxF0FOhtg}&FSw$s6!H%QV`fjw9C@l-Xz77 zGR-N4g@TOHc<+#kKWERCyWp&o2$i*wd^YQR2?c2PQ6%H6L%ERu*T!<2&M& zKlFf>c>CG%>8g8%%mTo12aLc>G<+_JkVD7or0sEDJxk#KS`gE-=2tnwix*$ST0-Nj zSq-I~caaW9(-%v65UP4JW&OB#@&AFXHX*HF-viC4_sV=}tn9w=O6b$191_&o(#q~_ zW!XrvbN3qYRhYSpfzgT3R;dub&NZSOFxt@;i!LDU>wgQ8V`|N-Bz+rQR_*&r5AKM8 zWF;z1YNw47E#{wozQsZ!Ph+IN3eC@OEjZTO6>~BAa(F7>9-k`qFcYx{i#z*p9Fl5OvBv z>6}jP3ZBjDMB*Ud5Qe`YW8O|uuGn{*ndaP22rPBLTDrQkUVQ48Q=B{A8C4RDtJ?O;dfUmzd_Vn#2kSk#Kp?9@L{y<1%b6Am5D^OB`y;wNRmG<~M1baN@ zSH5v~SH`^ie2nE}T#>8DYQ@6#kHYnA`ny6AOH*3YDd^Ue)Y^o88XGofEcQOtyHQgc z@9Y1=3QC?SyT>$a7QF~JG zqd)R(&Npfe{G*pwoO_uat;%%c#*N)!*7ft>hvVd_a2fnuCbr*Z=E|7PXW^LqSY$eS zf?r+#+pzgc#2V3IalvAMH-lp8OF@3`y|gKv|Nqey&;{@N>1tf<4u z0yZuU5wM^^PuvFi%JolXLqYrw9c;=3yQQLP$hp4(N+2W!K&Dy~wgwdKNLme69t!?y z3U&V6h0vy3;~HTtKvuk6$7SWuZP11g3JRMW{;a)DS22lyTrG6?n-67_t@=43vR=M? zUM2Nt0X=hs1sq^GH}AMX&j#+MFG-I)=+C?pi-@aFh;^!@`OQbOyyR@qL)6@STAAE4 zT_g6q3&w3g{&o5ba2$xF&|el#?*_e<*zusdpHmE)xOZ+nVMi|slDh7wHLQ7jGRR8H z?>iVe(O8yYOZ6ErrM6u~l6yIHmpD$%>xrzi9NT9b)%|W=%UwZ@u<}6So!e%w(*mdG zg&_e!bFy!groPf9AJVwgQ4PLmj_drIu1LJ11pq524=1{_9QIAczKP(Q_l>3AM3nA= zX4jVVeiuX?h&z=InaiuMjy#ajwsvF|(j`bzNKwN-=suIlR>ED1X_u4UQ;~~s%^@03 z!>yq3*APEfq$2CmNpp+j?H<|mw{9G~E=eY0&z+v1oh73v} z0ip%B1M`Z@V&q+DBf^U~NQ1PWAXL8Ex|Q4apjHwKnUkT`jlPgz%`60tT} zN?bzoznRHC%Rir3v@NWCeY`x;MFwgG*c)&PH+rQM)yJ^R^;uolU%u^WRsJTGtvB={ zCyC%d${h`D5aS2s;wt^&4*t@Cc7 zbC^?xm|%hq)ZC40ri-J2=VYoKnOao(!n-L{$ZSM2#1H$)s+0K?AsH)`MzEa(kYkp+ z{*R|@G(&Og>|kNhLx+5_GkA|eaf9*6Tot>^Af0}z`9EZ=Nz+CWg_45R;Yo39=^y$c zTZoG3f^>kxnS1dIN+U2QIw zwEoy5HUBE!)7v~>WSxNlEPGpxnxF>;a4H!@>5OB|a6EPyqYPhB$l!fSUSVYF!gQi$ z=3^%_%LfjPKeWc|87d3AKX3l=;4RF5Py%b=wx;HH|9)l@;rA5V@-y?t6ZLoc(l02Y zemq=c)e^rkl1-VY2A&VlRJpI2)H3l)b;&#}d4ngzaYg(_cTOjq7{E%)v`UWsubbmf z6j8MP$r_m@7gUmt6dK6QavmV3S}~!YST!hL&h_@mPKznr z9#BL<$1w2CIB*&STv}&XoRw?bR0_A|+ArfUPA~(F>ylxJkB_R*m(^zb3}LTz{*o_A z&FjAQtt(*K-fnVM%1D*$)JlP7DK1*_% za&7JDtbBEVLk}~jc7j8tji4A~U1KkUn~jU#=u+-|{X_Rr8$I7+^3f69amK=n!uu_O z2H5@OyZCu5I>E=ONAbgRSN*`rx(?@y86@ZKlJ<+980D?#YLX|LsTE5SzOTe-60{87 zlWx$qsD%KWIvn>Hq@P6|;^_1E3s@q2m*ms2BC;dIcY8zyatT0!1bH0mg#o;~6lF53 zUpc>!S3Zriqt#2<6uCi6KWs3^*6eZ-lH$+na9M2>4Uw~qNAbEoVP5q9!x!>%otShv z*?KNuHapR0I4<2vj*T%JkLP;XJ;5}^ZmZ$_K@UIR&rG(x7(P>I(2Cp|@LkP3Hb+Zb z%=s}6Kav0YG@W3^XqQ}!lRJzK`aT~k3XA0lse`4-s0Y2LRs2m@fWu8&P+io=w+}nX zjej(p&_Z)>=<>lO4(fmKer7WKAzs$PWNVd_9VG*0gx9$DAFw;9m#vyA zF@auuE+-fiOQH^xOX?1I6YE$_)CaNno$^x&*jOGMu&pkMq5rK#`$1eH8#{*64?Sg9 z$s0nlIq|cO%wu3%ru^BSeYiGD_D`wL03iKEA`EFg$Wxp_;oArwHEeSkJFylqf zP_xzDFXDd##+0G>55zuG@a6iCHIGs1)iRguKj-cJRxcEZjRKg%W;~k6ecYc(`t*^q z{*pBm4i}i;?)wPsJweml;`Td8Z@p+ussMI_NT@L>C%d85HK(i=PaSUJf8W85vTlC} z`3oy{|3bp7Kb)yl=t>z=3zIY!WQhB$qh|}3uLx6-@$0lDx<1>>#D4WmE`yQe%MWaE z7WBgBgzEL1_?os^%Od?6rBYYoJP*+&lIKgdwicIT5%>Kij{{k|QinZq%m#hQ$3O=G zTYcXrC&+vAA7ivj)<`!E?iZ%c8$Jd;2%TS$q4kXw^rzDUj2^|ubuk3Jm;z8qD>WSQ za{{|z6eZD%{ertXL8Ht3D)C>{aT$mpr;9CMcOk&hu6*>0;L&=x*q)UyO*S?`(cfBLF z0A|ZQrqmU!Prxa>_R;$D{a*ec$59XqxckoBUO(m^=y~D8!X!m*>nW>q`vJ7~nzl~r zlsP8hQIW4B->0o2X6o~n6y#syZh1-kwOWkS12Fv1530MMwm44EaDD{XaV#V5n?D4% z5(MktU08?bI+pvsY|XGeWa#*&@W-@Ym%boIl;OXNYByzH9dF)ow*n8ni?x#hn(m89 zwmV8C$s!teEhPonW*T1|d`u2#-p=R=V}7?G9Fe_`Z!7g)jl8z5SBBhXjr%h8joSA~ zQ&;kmVLTp59=X#6p}1P04=6jkHZ7 zfq&7qY8$Q*(+nnORBdu^0NFs18CO(g%0{d~=bKtiqT9>tsf?^Dohf+Eb1dZ-1)JRe zQ+I)5aY^s1GJz~rpT`|pPcJ>)m{^&n! zdlQi}1qv^IzpCGAwQ?~^#6Id69_K;G6+XPQH_kraQALQjL;1=mO`NlZtyzf!*!9qCT$AF%ksN zB+|?;b6J&lEF}w1=>hHn2*ujn!7Z_QN)Km!;;hA|G1j{N zh!=Wdi(VP!ZeN;|6J_4{HY4o9s8$5^V}6X%vG@0XAQS3WUwmjUFWXA|mi> zZ9kU3kk|bTC_Zf-;tkguq5rg_v(Zv3fHt&7$yB*^;UXAZqP3pweQ=f%3m+0Zd;~;%OMXvF&1ZmJgsp&ZIJW(%n0y1 zt%$wv!kcXFjAKVnk}7SO=R~~JL>bY5iD}QkvoEtb!0Pb*O@!pW1+V~Zv=q8sUJ3eh z*>NSmj|U2-nsG_+t&Wchk=o|FRr*Zol$)MOgzI8}kRS-^a2?{gM`l5M(06C;RTO zqhl>a>hR^j!&Te6In>CvgRPHU^LHTALE2=#jn0kQjrp^1@nI?Cq>Ve>U^5W*O<0Qx=CLFF?5x9J2cXq&>JQ^Amj3(;G9A8iAvJ!V0d<50}vYXBEPcuFxM(^@c1y~7 zquh$psha4SOg8ykn}E~q(-_{2mY+`YJ9Om?HP5CJ(O2Lg;xG2IND(#C6cPW+2MV%R zhn?c!pivYi?j9gY)OjtHRmjD&Unev%rT1sV$@#dBS(N13s7(JmLDsqcLb;bk3|(5w z6)#G_YE2~CVJrlV-y;e?qa-%;lZoZ9+R|6wyjh&Q(%!NS(*|Q1pz>Ah-$TWUzeGy& z+K+9%lKVlm@45!w-fA1qwg0Z!ui{zlcE-*sgO=xD&-f1Tirx9srs57Ktzx8mCZ%%< zCnwH|DD%}X2L$wAlL?V2tcI1W%!ewp6(BB{^Au>?pEu)j?wa&`_`Yi-_z#D*t3Na) zyn-4V#fcpc?$4tD|2eHg!)oxkwc*2m(9Ct!4CF?JK}Q#HMk#=ogi|%hfV1Mh6!!~ zgksrpuRZ<@`Gu);M+C+;e*b5DQdssj^UKU;t5Mvdx!eTl7dc!IJ}8V}qKdVBYg+1f z9keWxCAp^Yn4u`SikaSz+kn0hu;1WBQv3c-(E-SC$GqGtG3vqlPMu3aDTk&imHWa1 zB(6+zfD0Vp7`UE9`_#_w-&)*tSwPMYR6ohKqLLC(gF0;7DU8CW@%rsLmdBGk8Y0B5 zUA7xni^q4ii)TYpBf>Rx9ghj9LU25iseVuzB0VrT?T3}AS7b3gu%a-c2Cur|3kzlr$}hdNet?n!y`KD@v>^}b1Rh&EWw#6X7X zz=ihkvNO{^S%)b2gdt{@I@Xf`q(A%eFI}Sop<}k*^K5zDFZ@EZ`ly{sI#VrLO1#^gM^3j^Q{UT}_4iG3 zZVWNQw%Frq;=Hek<+4%lll+~FeC60r;Xu9`$m#l-!Jag!BOaQkb|}(SXk7Oy4h<$m zF7-d-*Q25zpZ~|-#rNC)FCAcDsC7o6^}w${fmet-M@S-XH}g-G|Nn4xR&i0ajoN=e zkP?t?5RmR}5Tv`iK~azfX_l09gLF%`NOyOMG|a#dLw64h-#qXB-hHqS=4{T^Z^eDZ z|MHEAd&yd*P*B+Nj@@#`9zZ~1Tn6{_wB|b)O+nN8S&8T!kaOfw9>Yl9_eV0tUU=2& zHs}sBnnhQ8CPrwW+aNz#sUmNK%R(sTDj^=#bx-Wzd|0bST!Z&Qs6$^-gBG4gTLjwB z7z;3yox+_;oloky7S}XhRHepct4+f1rlgOY#u?=m8y;+gAng#ziw*8M%UQ+94C=M^ zNXhMzGfX?y> z`>U`$NvBg>ee^%{qH?M&A7=}^X07sqASVE!?U8kOG!v;}P@DjS6t@}WZID%70y%D` z?bNzl?XCD4Odi+mukczKM+Sq?kVh}a=G*3;ig!h5sHfn|;>1#!+4GlCDH9QUB6(81 zIlYx>8g*?O6bzgL7_$>u!3O)G4eDw5n6s4T+G_vIN-N>QhvEw@s}#Ou9lyxzYV}(;P4d_`L+0XdVdi;0bnDwT)&0|R2|ox3m!6$ZNk`-(6-4XimU0Ktbj9RI&y(W+BYmM z#+(sX(lowsp)Ps6W=S}jx;c#Xrcj~;M9;x5NvBcw@uKR>@%@ZrbrVy=$5Y>BY_7m; z!prbyXV+%5{i#NJmJ`!&w|u83KhUP7ZnA#1+(3pWLD!hwqJmkkPb*iTqbEjbUfL#k zp)i(ZDIP(mfdpn%QJ@DtVuMriHaGVlniOUyU3p=Yce|fzEvkwy{k0f@w;TuC zpy;59D~m)abT|agDf~_7U!JVjoReIEm@Y8POb55_O-)^1ya6bL?E8{4K)|7bcf$>H zVDMgmtV0m4R%GI~4m(R^i26+*^8i~ibkOJBMhq$}=FefZpsoMJ4tbPw2U{*tRT_=4 zcQC$wDNU=cNPIzsh+X11?YO_$TW9^g6fsS9Z3SVU`nZT;NnFH`Gsc3=WX6TDkHDq;JTKz+cz*iBxmxG5KaSGFsVZpdMXrNr2>2ejy9F}oR zH)%bybTgN<>Uka7zb%QTMUBwJUKU=6f$5ay!X_b0krc--?A$BI2H!m1{4dwi1us2j zqG@q_HGPa}Cm7cBOBg}f_Jh<+uW9RX+EDunxL^2#&jDf|T%`m2;_6&jHohZ=S)>>i zU#1@!eXT*Ip~aa8zJ>;ckMb<)w4&jryG9$!Y^?kH8;04=FLW4=v%q!_!H4Schdhc{k?;x;z5d8e!XeIb}KC z|EdO&H#NtQ+JfH#6T=eOYImy$GgK%Wgy$&}13^E_98J_Y)|#rMGN?M{wF~$8t9=Vh zHG>~&yH)J$vZP?e_X+VF9NRA;@U9-^!gk_}v7rh?R?C;6s^KfcwEhFlE2V)!)}F5) z0{;#>!J%B6EdD*+_b1C@prK31JwL9?SjIPG1j*6wgW;?9jKRj8^Uv$fxsy_mTF+bG zmQ*pX=Gzl7A!xusK+AzxR!#fu@H8L=0V2iQ&zrl|Dw|zMpGF7RqJ@q%U43r*NQbrd z(xtnEzvUW-KhV|u!sNpe{%-WZ$q28pz4%N>;x;x48jE|IUF3_x12O)z^sfVH9tU9G?_ zC%U+?QktUBlhKP!`xyL`Uql`CSsZ8)lWKk`upKPeSs+7!yyOk$2M+yEF-Ckqk;^~+ z{+lmwC8@QxyKS#oaz*3|?mQwOS`R!^>Lq!J2Q0SVM+DyRxXlsTcHiv3j;&7S7BWtU zEmc@oY?He*_`%6Ikyq@yTP((*IWSm1!(k*1pah54O;uo(AC8>EW%O}Iuy8yJk7;Pz9?O>rb#lc8tiKAt2V<=0E zvg@zSejRSsB343{Oo5#rQQG{L7et8}EGg`NuM?c7Yl@~*05Q{0niPcjiRUA6^l!=_ z#T8+`3wV2#h<9+IFWk29@459W3(5V<&pa|y^YU?{^w~0H3~}~3X#h7FKP}_>%%n+e z(=u3Hd5&bc5k6^(@3+Oj$$}#C1Ul*kn8$nvuWL%)w?xgw8&sBIBSiTXmjmY=XNhfk zsb^_i2(X9*e&~QU#X{^n+oo*Wya`@WxGms?QU8x2u(x7Jv8q zgvz-cN&pX7#8hrF!;9;GzZN}G7nyJ_^BDv%OBjHze$hl+i?zc7d~XW?;-@K#r;P4P z0lEm*+fc@H3zF^#X+jyjD1-7q^@9biHroI( z!T+`WZ=pgTSaC(9zj)T9l)cS}`86!zclLRWnJI!B!o|`jPMAc8xkHR83f2~m+rXeH zyb|9ZG}HHW-_#L(8eD_L6Xm^Wda~ILD&+sTi8H)Q5S;4&Z@7rXnEcpgYLe54wgc@0 zl@A%Fzgr!XD^SPyuia0Mu=~|5YwM(LXl;CJOZ@vaER+-e$x`!0#yc$6qt?p$i5}+a zk|4e?Q-|%*T`TJ6I+n$+M-DEWe&r*;Y8zzneX}AHmwg293W9?{$WeitZdpa>5m%P_ z5;k*Kh*vq&>5LN=Fzern(1_8TYNLWioEp7Ns8byQlE@JluH+kFaj;0QF}?y5Ermj3 z!L0olobIb}+-R9yE%VFUQf@HWUT%l^c)PC9%p5wLc+PL&dOpbz`Pl-QM@3vf{_nzJ zQirQNI6V8ex1n7w|0V{B)l6+PohtGTjo3#bF6PR2;SFv9AaSt6o`Cv~pBNhMm=(_C zPq)~BH{8;^}7AJXu^fhM*L9T#4DydbrsPccc z0?OlzmqyV2{@4^HJ#jpj@U%`3#*I<&_%fZ}zcQOm$+V*0T}x3B#n<(r)O^BJjY3!I ziZ$oTHViZRF9l8tqINEkUbwVHSbAZc1bN#pef49-@P7LvFXDLery9L_t}l5e|R`8v%8i zn|>H@N!IE`Yp79p>dv%$V2A;xBk^w%sak(v(?vHHTLk4_70%@R}?ayvz!@K>4w>s5;sj!Uq= z8;D33_V~IV#%E>!MJ5E88xR8BRn`VfUV<)&o0x+Q6oYNip0Lu+MuUo690jw6hys71 z$b|BFZC@ff8ryQy^AeI9k6ZzA^B`zjW%euCPl`#2LLUY&Yon_{vmY5oY!_h4&exQ? z_G8q%+l3Vpwj=W%=!-eKP~d#r^H9Rsf7V?+@cDzIByKd;6l#V%uzg>cA8$ahQmT$D z>VMNjG6jAFdmQIBga-#c)a%KQq-mpFTbY9=07jrgO;<{>}PnzA>~M zx?uWjk&BAq*%?QmxSv(*^Eg?WOrDH0G+ggf0#mkzt10^T#4`d;Z=JJI%M=7bRa-u1 zX>fcFgS#(`bN9m-_FKl0o+bNBzP?(2%@-%=U6WoO*4Lu6OBuV)H9Z;QYkxaW10*Nv zoTkil_B%y|uTeCD#Mx!43im~45K&*n)KHIjg&FAz^69GI#3_)s>j9_*rjb*j>avZ>f@fxdZtS=A}%YJ6igmh z!00=@3>eN)pcP4!mynOrod|Cf3)B3-P_ROw3)xNGNoX!3J?DWEo2OQvD@lmc-z+nu z0Vh6E$uwAvn_8uKVp?Y?o8G~m=aiLP>3f+Myu>Zv--Mv;g2;yXZ$I*l8`**`Nrl}x zHzH3IH%Cwh+>cFaQeu@7#QVY;_q{h-c0v&;%);fUBt+O4s~GY*1+&4Eo+K9iEeVGB zS&2os*WJFTq^x@lt?^cpoj_NJ$R4{5a3-zn&GJHn@RAUghY!mFLDx24d5;Q8m??fl zalIfdl{pM#Ha&&st+F-H8%?Sr?`i|hB22Azq;%Ql|iAP)jJjtH& zWVA#~@e>~gwQ{`r=7zL}DT3IK5^7%?;d_1TEyp?OC>W9;V1>=tIEtF?=#(LG^d@)N zq*W0}3#c(L`wQZykjI;;-)PmE-VB$vc>NJae?us~UzNZ(V%#PoPh19Htr&_CMuv3Vd zC2e4^6~>8+Xu%lFUuxvuQtk-_9u1piO}_c-LiBcc&*wj2)IbcVm9?W}`_ixSDv4pF z=f0O}c@VjWzjonZ?yP|Ie(Is$&H&t9S}-<-qH8CKg<$IRwCF}{6o_WqoIKdv;M=(a zZ_rdW7j>hrb^<5o$M=1!^bXV!%xCf&;Xfnq{_;&DUfx_>xTC#q>D$om_}A0*W$6cg z@ck%L;58<}PK!=xPW_dXmP%Tg3*jzEkciaJ9aJG{WWhj?Ib86W{;ysB9z>}59>s0*B&_QE-6hz8yfoJ`%J9S~v*jcj!tvEFQ&{8LY{HKz-pZBTyyKl4 z(Hb1<`IHxm#VzExHd1yKEkgY^fk08>!ZX&0{7OQ7mib?Ke7|0KU&Qqn9f>x7TasQK zX;JHw!jvD3(+(LPNVjQF6BE}@AhIo^JgP`C5e5SbYia=nhG{0XgdA~+(zIj+lZa@g z23~IKPO+wvaZO`B^KY`&J9XyP3rB0%8zt=THP-0clCrZh+kKbr*ozQ}s3te5N8p^Fhx z;!1;CggJ^aLb_#EVfZ!u=a^mpH17>3u+Cp#>(@50SbvRM&|#J0xvfbOn3LFO(1iN%#@BhMN6D?DSLh@}WgFEI>05lJ_o&LSUmSob)E;eV$nH zl^me!l{!M`!VlMV_K)JY&}~g@D=B-Iy6j@T%?`ip|cGkPDSoE~o0xMQeLG#onT|$I>lx zP9sU;$c=m0F-N^w^E1FYaw}4!AOzdL@csXAA2ghH$#aN}$B;^2hVfD7SG}&Tvh~7q zp$h^@9Iebs^kX2?xa*C{Jnno9i#OXFG<5Z(WI$NV+q_IpEl`|th1)_S0FOKsWvweU z$Dp^zht6;rt?rzf%rEwi@A|b7%L6B7v5)euc066{?`Vel#-!|X%yhCF@t!}G_?;Q z!ficYeIJ}}`t69+-4WL}8=?OcxmD&Qv%Q%ulj=xXd(WQ|?P`o9GOXf<{X&`64|RRm zB}ZF~Z&0OxTAc6Yda5j`9y+c`bq~Y13?61Pp2CMY1>4RuBt1kl{|7qA&8!bmyu;WX zQJQ$iPp29DTHHk|?L4I#yO_gyj0RmNCCO%jeq6;w)NGEt_fIlUXYL(p;X`7Bw`T-(S9oQS$&JLkABf?p`^8o zq*HKqDuAAo6l{l5t=FG3JO5HV%iOS|X#t*FtgA_=uX$&q$71P}6qeGPurT@|F1377 zZo1a!5&p*H>N_U!I@^En4%-6%=zj=UFPvYg5|WhrW1Yha^v$-vPkRx6Argfjck{pd zCCSw_I!=C~+Rha*m6w;p@Efex-8);)cY8{D%*XbR_*ES9X73=2RVWltD|LjQ&BD>$ zuo2>YbPzD+;RzDIO>~EMOFeF3T(^*bn#9G5UJ7DgO&{te)QH?K2W&{NWxvIF30i5n*xj~YH-Uq-rcQeRQqEpe*eoMmC-w&pr-K@T0eq1|WG zG#5g2W5sGMb4%8s{m;*4su6p;H1~@v!1eYmz&^cz*Kx>7C+JV}t;C0Xc{LYClxqF0 z=7MaN!kIw}$0uw z2$@zn9aXDsWPyPkH~vFmee4%@&_w%zz)Wfvsq(08(;HmYS1GnM5bHPv39iP9jpDMI z9bL;Rv<~G@`hC$0i~6~pw2>hK^@W1Ek#nm{vEAL7dwryR~=QgWL`6&3*w3xbwk>CJQK=gX9L?|D<% zN5cBTf5%b;2+D@I`%1e7#U>X+-M-2gg%jY|avElbu;7^_<(XN%GYbPMc<6qAt~j@> zo2EjOsJ0lA5I}#g4eh}O zO?1w6*NX&`$X9{zaS(anWS@l9wz#6Zkw#w{Zowvf)OV-tg68w9o!-mlyOa_(*5ne< z$gPCR#1-}>bYJ)0Lx}a$g$&i|TPl;;KgYZKvaCo->(0HAr*vWSj?_tWDJ0$33>9iK zbyQ?tFndpEH{e%4U=g`9lujA;mA4k@^^zIN?K>WaK3AE7?=m+`i2k=3vprhbTeHY( z4g;Tx%UiqFq}SkL0$ViQ1sRZf@QB+Mo?svgKK*zyxhyy4Z=g@Cu?ia_a;t}>x*4a< zf`dT)HQQ!F+GPYN9FvZ7yXn{O2~zvl(NC-Y)e1<7{v<`SGrPEqWm#|6pwCmBdHfqL zV_zmfho=CG-6yf7rMO+I>ykzAv^>37_IV0&sVJ7%2eE}ii?*km)2?GwiyH?Gcn8zd zg^>6qnbcKM+8P3mAVj12HsuLdxK?Ra8N3-`suu1d03SmX2K}7dCl{T;UtxZr5Oagd z;<8JAWb+!KLp=Y#FR0IYg}{%Qw;j+$@ZHP24Zv44P#$NL$CaZCjfzH2;zLR=TDSw3 zuhZ>K^MT~;c>IH*ZKUZ)zK0q70DKy_Ddp9DmMnG`{aoyK!8PEXSKi$H0l#1nrLkd- zcx1<^kcPFr;qfK+-5T8Q{mt`FF;H>WN3}vTME1W&KVl0PK^NOT$gxZ<_U-pGnvVBr zL7e~cPO6>AV37pS!LF?jMBUINOgOp4BUxPg{>)EuJoQz=fvF zFPs;qABV1Wo_CiUx_2ITq}qJ8_>6XdI1_BaT0dnK?A?pWVn-y@PP6+H14nEFoAm(d z0t(4Gv4AazqwC$(Zyyq?X@PpwaVAi7) zOhiNH*C{=@;)Yznd~CxP@Pnuv`c|1JElWhq(w^o=MBm7ghvDmHqd`?t@})as2I0n_ zLb+?C0Khx0JXiUNL;E1m}zW`YfZ%)6aB*Lqq@~wmVO#?qK8K62(}&ROCEU^y4(EWp8aU&o*+IFz=E(u%xNz1 zz<#0dSAVG9tByqL@U3Cex0HSYXO507X>oF!4YI`ECvFh@qJ8>dV4EdIk7)Mq==&)$ zA9ARMl%ZA~>2aP!X@5zbdAj^)I>}k)8}f!Iv8SFyhEVpDe{=Zll1(4ZxPMKnq}2p9 z>Y|-trdE|MU8V>#8TsJ=3R+v#SGBHHIG@eZ+^Q~C2wo#C0gq(1f@Z(Bhw43VATYzW z?W=#Jh8 zO+Jz6IrodA#}{@V_yfi>26{xP^!0U^U$F!g&TsD-GkIv_yYok4NZ{VX?5*YA*`@U@ zAHPsoPQUo+5;-QYQ^k6oSZ9rr6@Om_eVJF$TWi6#s@=h%% ziKljYbw$>uaVL)ixJ_yZT|UpM5BOnV_n5u z*!Eee6UgB*_Of;wOrbQgSNx2~<#mRkY}?PiF(q+T61ScI$<}nZ9c2f3ik&;+w;6W!xx|nm5d=e zn{s{%Are%=NIs5oX9~Z5s~j*_Tm|xm5F_jIdi|wGrk>T@jy!V^@tqzb9zFJb@gv3ze?C9hiI)vFT8z0SS-mQm$#W9IZ>W)flPKV$vJ(WgFmlKYRNUyoUE z>f@m%8$MmHnO~{9c^vsP^9~sSqepjOHE=-l^8940S+O-1Gep81 zlN|m+H0FNxUr(QVQn7odioutSO#!!~k4=cldh1tkUI3#htJzc(7tmR2{jR<0XdSV} zv#!>XT7ec2FUFNSnMoNlMrwP@qWy4cPbtI;8TH6x)8aywT-w3-6+8gTLdX>OXlV%n zg$CqIj9XYDqauv?r6rsYIx7f7`0N0)@HN)LEvNHrO@z6BYDBk)-iOL$qIy&WBq89R ziQYpVEz^gdj2K7`&`d{`EF4Hj;+pM(BfVSrc_e*EEa%Uvinlg5x=;O%_ znJXz2v1H)7d5ZzUQVtFIp92oY#Ai{5PqaT(Q z&}!!#NG!RI7Knd`*6!`q&E50x*`n2FYmSQ>x|=HH4!@vTZK%nEH$u6dHm#a(V=nUC zfy-0i{K*H*9dqf(wbF4e6h7-$nztSfM){1W?$pKNb#yO6e|u2`rQr-RiXxBLto2Kn zJAnGT@=ST$WqubM2Wd;tWBR;4M`fZjk@Xd*EvW3+YdP-;N#OhDjzSVgJ6SLNUViLBgODfP6V)QVmNa&|p6qEg~JsS@$rnvB~-!r)(H`vN>sOdx!~CX#QtKsG}48cX-#sc9uXiq zui#Yq>8|ozg}bAV{Vz45rG)&OK|CaDy}c*;u|u1iynI+g8ZBE`ub?`1xT!)v3lICr zTGwG`j#*LLrGxb2j@yT_n0ffeor>3Gy=*e^+Kh_WhJ5}t`2T7Z83p{P&HgqAr$Z=+ zm2<>E*HT|D!92KJoGs`V{<9k=20*hfLue&OZ+b(?;7R7ZAQqh@DkvZ4zuqc*uFAZg zizw4kCk{HLIZY81G+2+;jzM?^FZPL)6?3s>dAEDzB4%p?M3G@D?@$Y}EQ#~-rLc~y z*Tu8V(h8DR(t~kP$@pUTCMa5>#wVGAS5%MRpW04vd^D#ff9*3~^oTR74$z_H%3};1 z3X7r<&-%mVIyKo0(^I2l7C7Bm3tr5|RsiFf;rRozW1;bwse(9ta*E}`dr0DFa>S%% z0v_QXdz6?_Y^fp6-LEF}FypF_F&U|@QS`r3dxR~7bh9duOR$tNy_yKSN#{N7)h{pj zgqTyM>{q3_JYR^geS51T1klsi|7h#a;-#w%58y1|mna@@v8|-_oem1WMJ>9P;KXiQ ztNZgmi~&>n(u%~QQ`6q>*fIku;PW`4+*}a!JB1|N{MOAe1mI?H)> z((ABxP@omq)bKK>J6O&dPdMZzr!$zNH9dU+x1t&S)7ISS1OL7#|7Gj4WpvTvmG_uH z5B=foRm?_5@&x!&`589NgaD67;-BMwEw-V?+LQuyK^u!0YSt^;pG$`&BxUL)FrZw| zxW?T!SDUzl_cv)V@5Q&AX#T9j2p~f+M>&k<{%+t!JPx!up!VVmWf#dvHBI#($NGg@ zgP8fG1A{lNs$5;7W&UILQ72l5qmkY&ES5@rr?9Lr|Fx`}Cf>lew|K9AugbDTmCv6D zdSvBdIL1t)u*UvI8k}j0vR=@a{rjD`ZBzuRDa#S18`)-e>VD(>>^#x9VD6U}Fx4ry z3F`!I4|Bb$odYi^Y~pwpOx;i27nY%*%8hd2A`jsx3oQ?JwTcv!)YT3d?}l)R2LFhV zUtvLZp*ejf5 zzovUIw6n>zSv^3GQ>X-l8vf)$QDsrwKS02_reYLxiV5?czw+i?u$Tf(@s<+T)UQ8T zSb2Z; zS%+s`Y$Q>f<>Rn;O6Q4UkV3W9Z`@L#Are%)1HJgKSYWqB*taCUO&pWdu>aRaz3&}! z0Fxc#!?)w_{2!7D`dZI^pX8Uc`!ocyCmxx8mrp|}%`NfT<51n7%8I2xZMF-=)~YqK z*ukIW zt1G1kBk6w1yWw_w9cw{NL-9UoJ*|+E8o7prvQb)kU*lgL&@a#+Ar+}m6+kCC6@XZJ6ic@eq^Z;P z93!^dgOuCzW7ShRo{+hT-MXeHRr-Tc{oTr@yBnq83|Q7;HPH}RRE70isH+q3a zDPYd*ztEQV~ zG%wnDM>^!YW%DK1=0mj3_>aN}jOoh>+k&Lb)dQZmGd`EQYesIq9{sNnQq!tyz1-`P zMTmK~UDlu1Kr)c`bE|v-r+eE0hvqsxCG-o)IbuQ>!(qrUY{l4C#(le?fUw6Rh6V0C;x0^otQS;NCxvWv)Ra1;I-V z<8J&D2c6TD1IrSC3%m!MyZ)qg=_eIeO)fNz)*z7B+Wt--Rv zS>W5q2EV7JN2G3^?o+PMfmVD$;kEwkEimB@_{Md2)9RI0IUY}SV`e~0AYWhfgfZ*m z$5vK=A1XmMCAg2*K-hs!H0x^8xO?CkPADo=+Ev4i5oz!#T${y8&iK;fPSwM%7Mt6J zZ8M#gB42-d^rwBcF9N+baSU?T`1Pf8EAaM>acldO010hYu*S=x?X`^o(yQFn?1n?sggO}TP_LyhaTgQ@x)!dydTtWq4G1IQ|&0mv|hU&vk^)1@aOciwy!ZrjT%rWl};fasr=U>FDBfrOsl-7Ay zm%Y0P{`K93eTZ3ZTc=cEdf&?xRya4`TXldv?7F(5q+kDCfZOXU-ek7kfqjB#jj@Ca z5vJ1Yz76Lh8S}sfm84omP*qToN((wo+KCAUC(>0Kl_>@Za7Ml4UFhBkQD-<@-ai(= zs`0cUav)89lO2*ORr@J^GLayTPL!~~C0Na1PVTU4_?wl$$6(bLRPSmOe!JN+;p$L$ z}bO4mg{}tx@*QLOVO->{y=v?NtS%tjl094#i# zz1Nq(BGi&W^!eSWDKA85564(6TvX^9MDRXqkn;Hf4QM3_%Jfi;-D~|zSY-S2brpWL z!#{GD0^Uy4(>B`;lXB@RlRF`L#%zBw+-8GSeo3V`#eS3_TdXRWXP0;GIOyM4clPDk zbJ&#ZiF+gR)fhlX^!GE?T6`YU(OmF)jn2gwwxqLe7s=9*rY$9ZgLDmBS)!4DF1ABKh9`&NzTEU@p~ z-g^!|*ROB{eKT%6yzch-urzS>GS~0EaWS6&>Y-@HG4--((C2dApfRA&7b3K4l!qPX zX`=K4w0sHpm+lXP)w?ojd3mN1w#v0^h?VUDK?{k!OM~aW=VZqQb@;BvA^Es+jYDlF z99}yKK-zbo7Y(Mn5N)aF`(dW(2a|$J&N}(Q9p@a$bDjnTVEjm|Yizg(K6<MaboU zGoo`|ftXUe4VfE$dL1tLSRfhwGXg5%{@^Yp4D0Utc(ZOH^t6)~wb(5RdK6vr7YE=9 zhG_m*L2Tk*=4u}_J8nMAS=?tV-v)-*N!-Agp3giYGmCk;4lnkT18XV|X2HBq^LY%v z)Q(8@Dx@iEHgS&7MsQ$f!5iK_1W z`&@j-3l`1|g1`p~ACL2Rc_XuD4Im^vx~W(tJxA;*G~B`M$4BT8NY40;q}5qqGy_Pj zFWtAq5%+#tnl_<9VJf!01cy7dqse4p4N@+E}$zg#J789B+NDQ7KXEArsiUONEQpq(M{gbm%On(({fKMq~aMC&9)+g!4VM5H`hKedEJ>Wsr36m}R~Po>jAYJ*mt;g;MQVYq&p2 zeiv2mmp2&iD}<^mm8ZNxIblyp>8>hX6ukb5iPN5Q%q}=q}ja+EwLA9P?_qW zy4LH`l`H5{6tE~;iO3Mnm)^V=&Zv5gq@+sN10 z$dS>1m)^gNy4CzG$~yJqWIsEu8u$2g%j>dX`epf-7B% zR0=@<_elfa5d+`%lu8_PfqLnq0{+T%Aw4EFAgD<+Yv6cGG=eucMw=V!q16L_N}@u# zbb6=D?pU%GN!}|bI~*ElbG1Zp3~p01$W5P%W>h+_=2nISfp{8yljH^+1_2Y^mkxGP z7suzpcKc5T5lu_+&0W3EP74Hqy5{DP{M~IMKq%l5cbLMwSpV%x`QcWMa~2$w%=mo9 zFRxbsd3p|A!pX6J-W5FkBJy-StoFPi1Tk|a!E&pM5$gK*z!sk&evO-DX9_3QAI6h( zGb??4Uke9ZZVsPW%%7DxZX^ynPct9yPu24t2WUy)aFa=?+dc2&@%DHcS(e>CsrpPmC*B}G zfPAp1%EWY3tj;cM1ewd$vhz-nOIh{M#X!cOFWru1_)RNe%{KZNrt6q8gQ-CQf?}7< z7gG6xrA&bc`l|w+%;)-tFC|m$Q{hJ^S^_Qky+jS3@qn4zY>17rB;dSgfkUC4W>#O=)=h+M*N80|i&r@W8A-1=`+_?~gw?MO`F z4O_=+i>}Y|wa6QQ3tx?R-0^%;@fNh(p!c2aFedkw^Xw{uK}i{u<15^;W;Nr0VNd;> zr3z{TMrcx;C4ccT0_{+z+*=`E+n$78#Ai2LR!a*DPXwWb3ufsSTzVG$vQTC8=M*kmxJt?q-K5 zh8(tOQNT!WseZAC?{L^UCX?I-ZiVyRyXvYX8(X{WeoQ;V0w#aCS&WfDeFrP9DN9n* zumw{mt$*;zYzN{w$u&@w#~Sd>VHqPz1!sF68E9$aY=y4=E?g%P*`Z26VW>Z9kQ3Vr z56uOEU2zgjA)JXxZkfJwOv3iUDp|qOGIJvg5_{&OD~Ph1;>$c+-g4I{86JFGl0+fI zBa9LfjO+TxD(;qvzUD73!V52d{*1tVGXG%uU?Q)(!jV#ULH^HSQv=Dkh0MOksHri% z+_giZ_MFX6#1&LlbqfIQ6nFnHj#V2?{x#A&7N%la)RBB0S19vr84&2FB=L{X6UrAX zPN$5&cP2GA&G3q^LClLq|2;h;K1v4EXwE=s=3`9#{>Y}v!FTYrO7r_e=cT99;R^(| zY1)5CT5#HbOV2>!Mh`Bb^wIS-wCbVQf;yediAuxw=@7`hsiC5QP<;#>zRbI=IjrG$ zCaA%M;T#q>3ey-Lxr5DsO2?ivIN4!Ky&YW@fvcNYfT34!*ulapFs;f~soeE(1k~e4 zGdy%^jDE+B_Scccv_h4r;eldwbLZy=Xg8bxTQm3T?dia*E-|M-6<3cJYVgO=Hi(3M zE>#7&05Eg8eEJ+=&`r2N)zEsdFt7?@8SxACXN9FNYcF46?da0({=<1XaUG3oxn)chzS+#_q;p>Uq zxpo|phltWvfhn7oQ(ZaC8Ob1LLLt^zqn6%t%Wy*`G|7zOGH$u|cwi!`O=Gs7_^~h? z!OnwvYDFUC;`6yT4!L^M#6LIa;abtEerRyRP`r;nur9#$7T818J#Ag1y18r-Psweb=cKKGj)clf{!TW zk6#2}KKTw7rZ@NXCFnZWE?x*08^~tdipJA1#49tRsOvk#i0AKlLKe?5tqXlSFcq}{ z!Z@p8g(Vcv?W{z6r1Ac+4AI`FIvirros#F1Di+oe1uIhlv zBNy;NfJtqb&)Vz-ylF*`$~hNX4*hs0>spmZ0WZ#t@SuRztv8l%gn=xqtLeK%b#cl` z`}aTI;r5acmf(vo#ewNO3`BaRz&MAp{fsN_V`{dTg~hZAM#lxorQRp zLSa5pf|v@jn%*|=l4D_CRH8PYP&_4V+4H^#h#S_l-dT9j*7{?V%-2`UWHoi(j(AlQ zcG%KZQ1%?^4?oeAk&)4Z2tugDDYNEk(S^@@^(2lj)mhEOjP%o2mtIG@%z0ghBGCI-B1Zhgw2x73E`@PaNBa>t3~=? zUP&?*$8e3f-8kWSnAKv`;#%UQ130lm@4Jp`4feqwx((qF(HCj;4j4Q@?~~3ap-MY( zkGpRzN82`e&1Q1}$&*Fi9V#Y!DRy9DI$YM$f0>SE}BL|w=WphxsPWtRXWft zaw<+3ckBOegDum5Kst&BxF7%9tN?=FI6p-xxQXA)Nfj+FJi#<_9yDrw)F{9n&ZoCh zQ0Y_eZ3Fm4z{x7%8NgHf1^3V2!M)##@F{3g!?blDn#M7GeJ*>B(t20~d~QP(FbJW+ zr(Q_TNv@pVHkQ)gc_6S9<1smaoI;Eikmj4EtvD$~JPYy|EG28UFG1Pj$MNB%;Q1#> zulu>~uV-7`DP9kSXaCeFz!7V@t+GubI1b25DLU3$Z)+eFCa z-!#eVs2~0Pn0;>JRSQ&wHf{4dSCDrix^CF}q*o&?J?9jj&9!!ZA_xwMP5(SwikC#9 zP@xX>z>sF&@BJ#uP2^)wY2;~ZIYdAPQO=4%YPM8pdh}3gh=_SNn=aSYSKRlMQL_%_FweU8}$$^w>k|lYExPoE@GP3L`ONE zY6-LPfwE$j5|!!F7A0DM+Qa9fA+d?ttTKJY8KW5Z zl4~?19NmQF5X%QqxnWNw)GaQ;&K+55oWK!Cn8|EAyVzt1LL5@Icmr~_`B|)otEiI1 z&9Nv(YK{1hE_G0fHbjv`P*`_!0h%qAV8@5`(^dCVUD3Luky}QosvU|eyIDh-eB2mX zmw|`EC5Lpfas9=1bmCA0cyq2pF0dDHq6JVAx)UtoUj2@IFK)*!(Nrmt<4{$?Cl?hE13swka4G9penk?4<&%A#+S{%p7( z917*OUAQBV!Me+|&&DQ&(H!B22`eK*xhM1AHEr?WE-Q2%VzE)!QPw;Vb{l=$u}-|c zE3h|d8>sx0jvK_RK7HpQw(}lvK@c{(csbRt^!xR^2)-LPlzW=@Y45W$^JkfxP6h|9 zKi(BJv6usUqLOEI#&1qGL9SVk*RVJ9>z-6N+Qeohay(uVf}+c@mk1K(6OD-k?_5YU zZ~Zs)$c3giHLUu#zW`#TvCgcU%L8KY_W@G5OPDmdko)JkAo;zXSt{WBr;Cdh5JQ#< zPS^2~XAes2oo%G~gV*8mb_8sU6Gx){ByAB4TexEBqO9@#?d*Nfqb_-{K@4&~qf<9n zh0(ZAXhoLGul;+hxq@=d3qj9G?+*~heYtWxBypUHhb%#GA$aoD(6S;m9 zX2N17c()&nvLso)kZGJzm&De;(45><__zMip~=oP^j@B7Wzot?MdDPd{_#mVd;K|m z)j0TmbDk6QSS3=ru4x`G0fR~otX|x@&OQIb$VHp~YCNJ~ykGyvH@W#G>eO zGd;ei^Lc+C9foAX`qaoykr=#X*K)!NUBk0;?wG4o5JC=7??>Is5nFN)5EJ&#)!Oo8 zay1@fH+p0EKRqJ}@SYJSC}d4|jsOIYZ#(N4x#zQwEHO$+S2mD)>yt1{AO7J{79aOh ztnqgpAnA_!QACu-SmkFrnFMTx=a8;6Kqfm!kSgj9BI1sY=z`px;Q>MEL+fPa+Y2F` zQ70sar2c$^I%0X6>WofKiy>od8=L2kR5#yEkX~+Bs+mE9q#G^iY91J505Uz}+_&+i zk*tQ=LktvRcDfS3sQ_~P%DxzWNIN^?k^czBk4=o7mbsn%&&&@0*)C;lfAvL^>}KDE zGZ1Ef=+g4H+3@ugn{|6IHG$y3b-xP~zTU?_IVw|DSEGzK=Ws@&2!Ptg)q*;KwMrx= z_CUEk9|2Ys)=zGD-FOPXhN3y$X0}h3=!Y8U2J(%#azScCgk74pm1&3C+va4_GAC!G zY6VX*ISr>rP@Xp59PdEou=qvyP|VwhMaC2dnjqwcD&ZQ{@L$9}b*1w)$)94eRz{Zh zy7TDG7H9$(nVYE7!fF{h*$8^a-EI%F3g1a7&irP^-V@q`{9&pgEBi*@EtO@!Cp44$98o<5)JMq z-Jm-k{}GQS@ykR;fN~QBvzjeSI^=;bG^1>)pJz4`O_IJueNsy&!+)C}ygwN5slxMFt^^2sqyx;#jy&l_mxybpD0W;)dc%NLG z-w&d*KoPO{{JipSWfpa3MU9TJUy42Je6mrl$#vlTH!pwPTylstZ2K6dJo8(~~z@6Fi(jmgFY=N5nyAhFn z1z~V;d1IGR!@9Av1oeel;4GR%NOV{tAPJjmq738^f6PW(z4)Z9)5#0knD*-s`P6>W@dpqY3sKI#6jz^X6T)Jt*6WWod5j^%$m*)~Zr3aFk|^n$Z6B$)HLP`G#o*(b0Q3e|knQ z6y6?4XVrf=LtB26{c`T23c7HRc-ecn)!&lQ|1>HZ_X5rhvk`+){etc6*{#Fk>&^X+ zw@KA!dnHNBGEc@9sjT(ep&ic}73%GFZbzA_m(CzSs}DgLs^GWRR`19^+P)8=Md{=x z)sK700y)%VNbD$S6T^y10j0Jloi6qcJdf)P(0eHM@jH<%UhzZSsq7=law3eHC@-L` zp;VmujZc!k^JktE!oHH4R?R9N%6FFTJtup&L6Eh*r?o3J^R8=vnwv@TA~DhhMxgkN z1qK|6v?&^m4Fj>NjbUkDg#wNum2-}cwJBG*?Y#y(^!1&dV;(KqX~KOhqKPqXof?#r zoQywDenjq!@GTs!;j!iMitjX3vDoxy6Lda1ZkagSkY_NwGy0ijGNDZT7b6PK!BPsJ z6oB{Ju7{^29b@X(y^Ge?(^upW!iY1B!2|+0KGBaLQVFdS4P!?*$E!+GM$@*pF~8SK zL?*j}#GS3j_rjY*hPDWON-^V2hgk(iKI6p3S!q{Vx;>-kzD5GG8) z9TJsd`1=dGV1dMH+oO1e+4hLf%tLgBfvJfjZcJXoq;l`v>gY%cD;1J-dowqK(hN+M z!l(6f@T}BIQ`2;jTVujlI)O3j*QLKaT<|lsEZ+*O(IDWDGK%9dY_d?qmWRtnro0>N z=63DU;0jTN!3m5Ou2aP8vlT^gY=<3`f^`0vq2Jm1Uslt{sfW*_@a8YLBigo>4p6P3 zztB)7B5vPCU%bzXWRnugjaB|>LFLt+sw#mzfOhH{s`XWL(gN0u!vqY5gicf-TrP;% z{Y)9F7T2F~BTt3@?R+t7C4Pj&>MaE*=XKiSHVGQpOaY%f6h6!$WUCy0O+HCTWE<=_ z4Cm#qmETAYRPQ-XAW$(h$$KtO5uYtRrXwa=*qM7h$w9#5(m2SfIC55lfn z9v1f~gU1TzAl+-12_xpuJ;&4Q1-G5rw1xlj%MGJ(y(I@~-Mt?Pr(1o&7!f3ycO{D?s~J&^OX^NF+v1eGYW{e0qe8)QMQ>l~!VE_)CZ6ATW#!n*63^ z09kw+}Ye4(XH;8|8G4B0QZxC{_~Rrt>Eo3Ub*FTGtUhznVi zJcIXz6?0<=3Q?{U{)Z%j-bxV5LkNvPQ+daNWlYCUJ6E)FpOj=!FsZ10f z`Ds?6%3-IThP&UsOirxu-F1iWmc_n)CgBI&3A4*6DecIa7)Fc84;fuO;P}I|KSc~$ z8)0RvGx7XHQv%vO=IZ00hHHHCnxwsYLy=s5m6l>ek4#pXP13fc9MX<8ArFm44PDE` za{0OcbB<2xsiY&aSK;rUtAj4sn4_Imd!StQ@R12C=JvY@?zD&+ADg|LbJ%1E3M-*s zlaO5go0M17GondXa?8Cr=TTsmn4qU^=Q%5RzKh%>dMGRIeznxTI(lo)K`UPwz(b$`jK}k7#_z& zzkRtbiZ+Z<$yGi^rb?TcxPHPUC-(3m+>5tZnoX&5__eR}IeZI>AYqUZJ_~O8F&({V zWejlf#(kH}QOhU+2-zen2~bC^t&C2Eu36^96ap*hZgcZD5XpyT76RCVK4=gARkB!1 z<%cXk{R9;(g30YT6cdgRO^%}!JSFz=DD32D6E@W#LKA3}IyrR{40Tl3QaS?&%hQ1g z7erVqI!SDZ%gK`qrEJijVP@_LR3SB$XcqXt-%@*@2}v{pYdehBo{{v=)5~jfw%lJl zdSH(>oR7)r9amQtZW7Fkl2Lm@VSjE`i zP2e3+AGho}CBeZVJlSP>Eo$N41k|uvMV=IEiYtcrcCZDHyS z`k{>PSd2<1*Bty@&N~oyA#l_Q&-oa_hJrYVT$-Ose}U0nxifQ7w}gi*ui#4E3gB-T zd0a58BUc^vVI5_seUlJQ6pj)zNVxdrNHdLEe4eAYAO-a+@XQX-VJ}=|sg}ho3=&Gb z&^ivAk1FIsl#8v7?Cmwp>4{?C;jvA zat_Q@&v0<*+gBfAjoA5vP7C!$T;g{8qu00iwYfPB9kxDlP#saenI?CFH5-IJ6PYPOxefBj>+K#?D_iG~}C?AV+fc6SlF$D@U_o+^9K?{Z;3Q^bVtyP+v0 zCQ5_juDZMb2-Z$`$~{>Jj3n?+%|@cATZH_`BS%{mYX`El(CPJBv5WF7cLJTWT(rU;euWO5|GvhO41S)+ z1KqXGo3(U-*~vf9KJAFEaRYp=jT3l3OLenxd{4mJPfw2T-)OYEX+{e_^Agh^aWoc zfSxOE+t$sAVgEk*ju&#&ea#(M9FiqHa(L;~er#Ti+xwjc3chCvb7EVcxGAGv77Gp1 z!+QOB+{@Q2NHG{YJwFUijtx9esZ6Thdn)YOCq<6$N@P(5Le(h(*VQQ`4oh&mpz!N3 z3#aQ+VY5Qv>0N-<-Y0Xa7mc+S4m8R0{;;8!rOkOj0mVLrLBd$#GprP!G$7f~EKPOIK#1;M}nhm3HqV257Rp{2``~T}sG2V!1gc!ft3&J|S zvZliJ4>xxUffAbj(9K(qrxSaBXzCx|p}S9ykfQuF>1Y$S%x;tYvIzCb7^D$ zf%f)MM7UG7aHemOR~gs07YTMYe+-E>@`*9a7KdK_@{AG>FqKt$1xzh}#bMjW-*+5P zQaPRYb@s-8PHU%o(Mz0ZH;-zk*wsAybv20_YJYMKPHo!cwQN)kwYyoIJ0oh$eue^5 z_Q|JA8DNWvnj6jGf3T(M4crJl@p$3_f4c-BOadvmZrnCAg}+(W!65?AKmT#&m>gX1 z^2hi0?k`AZIOuCxN^TlwzhHZ%O`1X)!|=T4pWKf(sUn1}51BMW6q?_p>$nW)TKscF zCHAcaIV-%tc%z!m>YC~&%q@Al+L|qy4QrSHcA#{MG~3O`Co;R!?#1KfYzua?6Ri;c z|8{|ghAJ{;UmJz| zVJ&X?podC0MtGbZ9?;vZ{UzI(xQTQXK3sE}_dj&f=)xP)GKJUMa&Ka8Q9~WHhX7OE zp^x?feV7D#o%EM^!TvX|7d+6MV#syGwz%8emRlhOsoxHpKQsHP(8dtV3lI)c(;8%V z8m3^nT^uFzHw-RT$~y=o3V9=vvf=C5ge<;!_lUOEd0F#lQ{mOfk{j6cs&^obQ9vT{ z&HLCeB|SA`B-7o>%rd{3>>`$&j8uSVCf8dD8SNAIlxAGzr4dujUNsL9fh5i2rJ0<{ z8@M%7^Sw;x1PwWIaRrU){0c^qm+r1Y74uhuA$nOW2VyN|BYhEju7uyey!1TG@TW`a z%;7y-)f&ZbVlv(}f4n_!dZqZk$-tq8vU^4|2zBiDrTr7~)x(dLydS`Og{V<(Ju-#u z{g$Kjxt}9)imgR2BL%nf3N>MA`)6B8hGEzBoNaMP5mrD$D^weHXb<(Dk0g%8J%&mi zT-U%RiN&ZoDArx~M8WqTv>yJd8^D&k)}ONX{@6inb_>m}3T`sEUU1ups5Ji`5x5+h zb3{CEUC+ZZVSDsEM?j0d$$1krSP-%w1#TU9NIo8M@w=p%{rFfBxG)3T?Nkpsbb{^U zNtAC5;`#K`kInbv*AyxJ$&=%0Pm z?H7@$o`b_gMYrwR&=xTcz@h!=er5=!*nZ_VQMCAUwrOq*r!>8NSZUwiY&CF}eE60E zyY{IE1zjCKc3R$)0-}C%Gn&8D9~R*#W8d)}r8pd0j2G-M+B5$N3SRGXc`(Zr`|Yi; z%+PMz%1y!lk?QvR0vgV%(|)3wQt}*qQ?vKg?`BMLK+sQb-tN98((EUh)6rX(;Ex>r zvN7`=((~RxqTS5;OYx!=75`&(P0sTaAat?LuA~hkGFgp!dmXS=WvuLCK~{_fa5&5_!q5O0-@k{4P5Z8($jzOP!TV=bK*(Cc z`#r`4H}^|$Ozf$Eo-<*MddPi`RCphWcGhq}T{wTwpy*ZbF2B&2A8=~+XCw7mr<-8X$1$%<9kMhs*zszp zoyFu&V6iXHHM6_dewKmKPdQfiIE?|p-$kXk<~h>@rRq%SKnw;ef_-{<4E(%UiKL;h zpqyXco%kt8IINr?_5eo>XL?i_IM%!_^N0sR-5y2k5CqLkHOvw zufWWh!2IRKKVTPN~HwNzFQvN}r0sTAA=mADdhf z?-lw`^15D&3ai*urK0>CyD}cozOHqBZ2;^w;0JmS4H#^aePjXcC&5Q;THl;s3iU5M z{_G7hmBWDM#^GrE+48hb6@gEorI!tPXol6`sMnEbHaksUNelC67S=`knlyag$A&Kk z-Bd0fzhmFfI};0b-bd8(z=U4gLc%;2VtKvYEt6$)OzD+;=NzjW=AQxn(15S%kzB0w zA0g7ZNY(BrLsX6;X>W-an*aGm(puJZkK`10%U%A_aJ`nVbjK!hWyr9TKZuAYHUjA| zm?RR-;lrDZb>BDJE4@-a(y){mWCwk->hK+=>2`kWytJ7}zj&#Vq#jaFWaHAwR-U0J z!jbRjIuc`D*#d8z!!88$?8dX|2pGs)+T`ttN8?*g55)-7sP%PU-r#(0iy0)vkJ0mZ{aka&^H2PaLF!J8*krBMbDHt^RT;`Iy>ucM0;}VZ$*j zKwgv;C|oNBgj7mcao9`fYD-3)Jyun;~h1PJ%$MmU!a4 zC&=w198KmuKW+Nhml;0~RcSWL5_<;QN?sz>gYFaIE793iQ!ot&^rgzNGBWYbKWF&` z)vL1eESdS_=kvpsZP#<`jCsJywt8?Ii-_0rq4RA>jl^|*x3>!DZsEY?zBe!LRDHPt19t1TF1C{Q;{HB91YUtwehJ*)Z0l$H zI*aP7_3Eh}Cl9oPgGN1G9L(mTBhl_LnxJ>`#D&utXAPojnl{k&3xTs>mphS`tl~Ty za8MyH0fp_jm=IWUX2fBw5yyYf(S7WC?+-jZpV@);)?MpK%-ZP-g~Ku`4h(Jo9usr{ z4R~9d*WSUCf}AfevFV(_eq|zzokt=bc4*N~eFY{j>L$;&he{fzT+OuCBvsgo z-3obnzlL1cuc-B~@i{T%`T6NtuYJt|)VzHy-ztClL64}ov|W&<##buhECMmC>s`%k zL-kH^n0jm1NwnvV=gRm_E=s2+;D)h@HjvOVH4bl(8#;6vw6t6Ctwi|R*A{$GH9V~# zHc{n9*=Gpo7QH$lxRZA)G>C5%Wqz0K7KGb#8=8yDS-eLZlVZFMsWY>8+6Wf}MzX)Q z(HjvXG9kWJ&1|GB3DYc>7%NL3Wp4xdOHI5#~`eMYRD0>@rCvj6I} zb)aeDJXP_5XtL1$xMWQEmjHU8;2%r*uD%o=wa~I=oG)dDM~!OG?CQ((Pi>mI-?Jm4 zuj^aO@pITClvF%yw~!#X&hBNO-nns7=Cyow$nB@c*ymEceW_Oy9~TzK=VEiGneP7s zNuWnuj>$D^PQ{sAbHZ!q0mwG+($Pj_aCo;wXA8ki(j<9)YPB#c;@RnWf`ySXI4-mE)U0( ze)e``WfdC2H}2jR@@EaDy*e31-kRcjwEr%D<0PIHZ$Nd0a+eR!0D4*jy@5sBobjyL zVMDzA40L<~$04^BA^}{koaD73wcHg@VE2SeLf_0$7dkCoLn!lxW@qunw~O<=+($vs z?Y*GnGLTNPv)_YsVlIAVN&IO3o3?y1YvQcS0hS)=$G79>1p+0^kK6aV1l=I{!G))R zOB2q6NFHu|JM(71<0$TfVUS&``BUZN>j%-Awo?|DAU4pufK1Q&`pJg_bqCzpYALcL zHlgTxML-`UuztInJ}Mf3!h>er&{LRgyylt3Q&Uqi;ky&t0#dkuNZ-s9s5y)A?LJff z9RjyM=LqJinZJaRP*NAq5{qdyH5dC11n(lvb)B^vX>J1BP?-Dk{h_t{8TLAhSzduA z%|gPU$Mpv1FxW`4oj;3_;GD%-Q0SKff;Wkif%rDoGbr2&(oN$WO!UjI&9mfR~tHEb{>Hb zVQ8-;r!I`F)Z-;OB@l2b*Le=J&C|@lzjlhpfe+@o-X@M%1z)+yCmdwD;q;LeCoh|i z2dkz=3w+>e3DW;Ta|w;(fnB{Q!C}fWzP=VtA7^8fpk+-8iT!fX?B-_Th)HJIT$*bq z{7_jXieiwBzHIXKQx1XIb*&=C-p2%TQZ)|qWTF7a^E&U=(##|l#8Nkr)UUDOS}dLg zfE*u2`Q*mu-PBNNJ}bnx`v%1pdx}=h3S`gR?gF1)H2eZ z@+QUYrJ6X)to`saY`B-eN|z)8VAlET(O!lO)NYMqs^vG|+H>#;nbPQe78USK z`B1_j8kdph!jw}vFF`XIr5$FS^LcmL1A}xxBw5}cm4-a=)PN)IW^)`;@Eef=>dmi* zS9MVKH2{=mru-enY74Fng3E$a)c9<5HTJ)893BLDyO|#t!3oOfKOWBYxs*qMRvS8< z8V`7 zIgN#r0m&1i*w#jQ4UAswlkHFVk6ag*a*ns3Z*t@1EoU)Nva6Szqx-*KycK)sYUBU7 zR6~D6lksR;TSk>?kqN+D#nB~b0pGZSg~7g@ILjQ1T};<3UP{mTxySD3>7rpO(h-Hf z%=x8zZarmxiTt?FXe>v`xqL{<6n1&vRI&8(772tX?qWQkeUCOH|6m8otE5+b5JlYU z9F}A-j3}5fL?A!sZWTCiO~WjHelOc?EqmB9-x`QtJkNiohEW$Q|6STz6_`&RKrRw+ zKx2|(Np_GoWE%CB+ZX=tLEhtp{C;Cj3)fSep5FCPrd1U&DDPv_S1%%Y_3P)#*|X3Ngjn z)0XEdzdsWdqRY+~QuY4Q4(08ttz!?*3iaW~z{wtU3Abyxla|j>ecGq`sr?1Wofk#=-hhv>< zU2YQ|(8axNKwM&LL-OT#5LO+|5rAJPYVhYXAF>OfV{TGMJ#N=C+Vd+g3eRz3`@{)u z*DVu#@zd$uU2)6iS*MQjY1f@M4RBqo!sTe@`oj1#aF$QqgLIMCieoKtM&$Xc#IyMS ze%pV6exGe=`g=hJ3;k`kn#9W(fO~g6GO?r%*v%2#ANvHanv;tgNcPw+=)Qi&7q8;i1W%#JAjzrbUc`jVbD7;lVdR^-c9c1oR2q9`++169WkN>dCl^-i#tJ*&xePEm&%NlWP z^5b{;iLc?kNDf3Ryg`UkT6k2+V%3{5>F-Y-<-vqVVLQd;1wS|*t~Y(=@DLIuUNYn% zc$2oUbbjpnCLqOFldPVG(hQ~r5A6X@=1pN&7wqI3tsQjTK!T6TyZ+Mu_|}t)zG)fU z^D~X*`DCx+AOBEk`9|&*FN`EMhGtPsFO3ut&kOnJLV58X-@M)=Zsn5&rBlu}Me3mX z2Sn_-!gdy8MVqj{m#oYr(Y*9@ZehU_9pgRtqg9o9B#!4=Q?=D@d^N`jj%@w_A+EIz zq2T+|`Hw97;&#XIeF^3%A>ApVl}3N%Z(+;vS+|C73Uou33m+Ixl6J{rV6Ydx!NpjR; zax&E9zG2PH-hZQnK5^jDH`L$*2s4?2N7#dv!*ukjwPeN2bi+8`vHs93*?CUYxhLbj zc61VhzY$y)EtsDiQxt{g7}yx1;Tv9+eIt(+xgLS3@wh74RlesT|DnD*&6?8?H+L#C2?X`9m5guO{BU!1VI|$Ldcx` zy2ehy#LVxR0++g(@kt@d{j;Ows+2O@C7YgsoBD?6BU}7AM1Me9q?>3_;WGvW^K8;@ z1;Bb~E!N|F_&9xx>O;SQv^J!Y?loS_7}C-SQ``J}7NoT%3FH?jGzgrxfhmcD!QIHy ze|daxRU&aRWBy!he)CNs@E#<-?E$;%!QIrnxljn+NnE|u=3D}n9VEngjNu7?;`0^Q zcN4zk9d#Y!0atlwu)eORP#=j4HqeDI?xAFFL*lO?m2Ae`EBA%>rR!IF3bh)RfM^xwq83$9#lL^gb!GC z`VOoezjb(~G5qV>~3+r$Q|=ia_YJiG`Wled!zGUx$FS>eo^gn+n#s> zWVg?CnVa55)vzUeN4>lP(*)saO0T$?8Rl*1AyTomcd;MIY_wm<<@(Ej7ybSdA*{*3 zKD`)9f)zSv)C0!X!h(Td=#Y!}b7QI7wCUdMBa!I(ZMq%k0;yj8d9wrTcLBe_{Uu~Q zYU?GzdHfgXDklKgxYHA3?J}{@Oda=`=j;Vn<^$+BK z^~CprJmOybT822Ha-zKm+A=IbP6?NJ#CG9eXTrDBwcoK)5&3)ubK5BA)@L8CL)Giw z7BD89k9 z>oLC{M>0KMTIc+!u_qO`dS%!GdzkCR$I~v%1UcN0T45|6my>B4jsE#h7fm91V@6s zP4b4mDO>IjUgB4{(~i33Y~-v{xw4wRcUYO3Zm|86Ac~=Vy4BQCH-KvWjr$-dGuF_x zHycB_S9?kNmv>C7vf|HY1}zDK?Qi_L5)tuX&DKU>)u1z~tLPO}@~gt!cgm)$#mfL1 zQ;UIz2;J-%>n;(l|HR^Q&%n0YB-WCMsRpUU5ViY%V}1(ao^<07x+2uW9*Qu(X8fFR z=cV!JlU_|k*$qs9#dX%!? zw=K*9H;z{m*-2dXv0EC-2Q-X*cOy|n=+oqeuI2RH24Z~;fK;J-%ThP5rU`JK`i^*< zUy;Trq>Q^<|5(4BWvI{x{h;Z&<>CkREO=*Wg8~B5rD1-|D`93}z!tk_ksd8i){kgG z7RddpWKuWV-P+tIIsD~|4O9A09le%K8NvT!D#^xRV$NOFIc74ghwN`KnI=!{eVAUe=|)U{CC|u2Nj8 zfl6aJi87AmSMQ9Lloi>lzLUpiJ94Ijy|p>~Bb*lPLZ|X#URWxXY3R)yw=U zSriE3iRnmr#F|KuY1uk{=jl3*M735D_edOsnLxFJ#KkN8=`HaZ3rE1l_AgN2F{j+t z98NYE7CvHg3o`L{IWhhBXNInxqkU$(4qOdR3JNL#U4S=!`-1?L+UB#LLt%{AVkSRFue)%_xx0wg66p}~@!+Vu#4cE3 zI*b2*V6d|Pe;CXd_;WRA4+45ID@{* z2sH=RQiwP0aV6dvw`-fI3*hh&_Y*i~GY^!N0J=6hy32(t&Du2Chv>9#r7&ps75kc& zCzB+`-{V-YS8Xd`F3u_@v!9 z8z580+lP{bwSioTgI?>;9DEPC`{+6?fAh^)zj>_BQG_jV5;I z{io!r2+KVcd5VT(C0Wy#)CDb%=%2PoWdYl93O-gT9bsI%M@<@u-Q03DLp+hYKYmkw z(m(pyn8Ty$3oRKB^c-bsB2@nE)F1h;i$QH1%#Px!Q=GHA0W$z_LGRXdv4#!wg9nR z6O-^gKJkJr*+h7(FG>L0MQR;3TipGEQX*f!aq`(?D7*G`;$f7;UpEz@8UCrqg#n6k z&)wHgGaQ}Ub9=eBhqyueHc&VjS;4vzQ9fuQmTv*>(9WXu{ zTr#^T_qiYB!8hlV?@?S*e+T0OK+oga?E@}wr?;0IP!r49qwaOvlOp_xM#V$Q+jHas z%=g8*RQq&@uf4oIZ6Oqg@c&Es`?KO!Sc>YA9E>p~NBQ{2#A?SH-hL&Xj%JH`a@O_t zsTAOSJgv!k9>{6kP;fp7(!AyZ%J#gQrr#B8{gP$&VYUB1xRop;CmgqmgX30k+Uh1+b2_2} zpKr2Z?ETk5@-)MjA9;RZ{7v)Gvjx1yJ!HyvAM*l0XZ!w2c*gB=bzc`elgv(n46%K9uG*;augqIPwmyxY z^M}-$tYxyr#&0nr!e7yby|@vYzGgXyGC^4K?*jP>ZFzqL?H?uRMC9)HYYcx%z4R9I zSL=#hCeEqG0c>?$7Pf^bgpW1XnILMa?&79F5P3||Yw9qHM6-0)15f*L0;+O3q_84d z0g6@)dXF%#NwMA&$fIsRTYDC5L2=P9+@I3vafZx9>V-N#Jqs2+i1j}rEtPS4ps9&i? z<8josrx03fd5!8JiIvwnov$`r)YAL^VEGr$;jvrE4^q(AkO+cO3yJJ9rm~0<)WnMy z>|)_!CizH$8}z1z8NZTHO{@hEX3Fsk&Feox)_)R06%zkhb)@3iIW^49Hlgq0z12Zp za6{Ea0`S~7PCQnV+hYk#|2Hg{OvuN7oSJ?3Nr0+mbK~fTQOR!l3rXQS=6-mW@X@w; zU88mZH#-s=NJ{=_7}HV}V)ZJyTQ(2XzSqO0RDuoXDCX>2NR96yLmr{5Vxdm+2vGq) z)#X33Vt(j#<>!VYZv$P@N5kgw^U75YIL{oOz?Jt$uLxp-6rQ6W{5{ZVmxW^JKP{8^ z$kD8)2CYhoqTQ$*7N?djf$5?1C zaVMifp=*0UYJrWYGZ?j5u0xvGDM45I$gl9eAcd zdSo{!UM5HKNToaY-v>Xo`0bektfST3T|QOKv?k1kTW0Mh!4HI%b?<**8ZN@o5}!6$ z^`%dtP~e7iMDUyK9L02`1Qfu->))G*bX^{9;}SU4`PZh>9gbV$JSSxnF?3A@Q)Hy- ze9`ZLc^sR39T)Rmt+8l*A?OtGOT3L`3F_01u(y`$=pW!cY9u6HA*dwZlubDMvq1r_ z-yrkF@0>sH5BW6Cr##3P^VS+K<}(f*_GhYTS7DqEs$=zrrCp~z4GiEdQ%_`$jK*Nu zuXJ@VhV_3QXyG&TRGkAiF>lHppH#SWhbleu9p|57{qeC1_E)+o>HO?w{MN6x6rigULZum6*^({-+F?g-~@0i)a@gnAp?>7g< zH=J)e-av0K5fj}X^_-1K38AbOzAJb(%qpDnmC5Sc{>3-n0CC>dr6`k?wjCi#9ge3H zZBgruf_x3S1>eYiCX+;VRQ)9yOT?N#?y1H!29Tb)qd*eJ0}_p?k-C8@3u;9B?ir7o z5WAe?^-Am^?yTNh$+5SA?(?#8nO5wLPuJoN;sXC7P(Dr67G=r zTkDbfCHn(X)87MlvhqJ=p}7?y5Jia$8O;y6Y^Qj8QF~D}&Ee(o7?lJ&H=U+po;Z{; zqT*92=)S!lF6+*}e2JO%iN~zpx*Ca==2HLC%IOQFDXuMh-fSN;ri3SRb3sp#D-BLHjKzo(XjrzRQhPzZ8?%#yq}PaOrxQ&^Hen!r}}Z zwrSEi37}j2qTk)|9|zkxAC|i)R?{}rfeXNCn~ui|-|2b=$X>jR+gJl#g1rA02Z6Va zqoEwkZwa3Kzk|6Z{frD+5yn~|Ejl9G~ zXf;o&ePi)l9cs7+(VGvtDAB!Y445am&Tad8jC`Jni62oFZzpR4j0E9;TXfAXfyTbu z(>s^eGpd9XC0+NrF_?K(#jS+Qe20VAsnd7O6-+sh{6^{9jt05V)!S;-%Uxq7$o0>DV>&hL*>5B3Tn0D=1Es?r$Ts% zl_%?_GM4Voh^!Uf@77WWyP*|AfK7t$L153oE~sX?Z|+z3;ANALw#I*QAKiwm{p8Ob zIqfSHNk^;Fr)n(KCFeMrLB;}UNqffPxGX-KS#|Iwk?Y;2P4df3Ma-f%F^ z+c!sN;Qya9`aiXg(NI*UeA+eo_nflh2_kHlc%x-Wy035gO3!C#=K=0JzD@!Rha7%R z)Z31QUE#SStyEcsRcXco^03BmI}cQe0%E6FQPz@#Q;=EN4nzWC6Zg08OU0M?&-+7L z@+cym$rx7fhPP#sYAJ{kBhP|xe(zv?K(A)=cV@9~#^OFD zvgyxe3g`oi@OGmHOii?Z+!R<_@odlWz7ym2hV3G6Fj;IKv#V*>IKHZj;giD4wh+nmXbcLKuKT7pj$gdDZ6o3K!2?hs8iKcB$;gEl7#}mJA07CJl zs5=@p#GCClGmS$;2Dp|wgc(kGm&58NQE{t$!n9Kg`i zh6b<89DBe+AeRF+V?_}N+Kx0ue(}jCGc@So*MI!|z4)D$bh&HMo)K+|Je!$OI<+}|F-~9*t{0GDRHTiCf`4k12e(vt@ zCApFL+};bW=;7IB|HECl)ysBG@Hp83{q7cL8^+JO0r!x7gM=gfnq(M_kAiR>aJBX0 zSM4p;H@=KsvNz5ZH5S4jH0YFMFvoQI6rDQq5*qWpYE zb;cnZg`X;p1+rx=pkYRls&BE6{s667)7#f;*2>~GrC+^xZ~3NVR=Uh@-W4}}Upimy0n-5EUwn^17urso2_pO2KPcT|RbIKW0;5`^c#5>+>>M+cyB&6O7Jg zbH}&SKri7}FIbvm?}z00nPsQ)hX;51eu!`9b6PgwJHPi2Qtr*_CGi;<7aiCB%$f{5-k8*i!#^?+_>#%ewidmhnj zAoPc7-~m*TairlXrMYB+uyX$fw6m^Bwpjj_rj@QHy;Q78fREBs1z=kBwaO8(dC+uz zamuH5^#sN$DWw()1jzE4cDi&UEkxu` z^Y>pSWu`@KV!QOBVnDO&i##^ER~|mqN~@Ocl{HEwJ#HhK&3{p?zM{ zT#I+m?L}^4WblI#Kf4g@zVF|tF915XL1yyFX9>x-hT!*kpWa#ZN+bz8xU9+EE;G^l z;%hVXE{b0EXHk-)?T^;JkBGi!cA87}6CiwSb*qzC<(zF$lmUaR-j4a_wT8ywfN$9l zQj^V;r%HWTU{deE*B{5xKv2+3<7#mR1a>0a0^gEh!BqfU5s;4ZQ`WEw4eDPEFC$0t z8ejD*5&D?=?e^&wq5dkT17)UxUL->misOsN?ME&$|6cUWiNZM@$sG`--nWF?z7^As z*ZanM5o*-+dn|bgysq9m+z+on;b8faIgOqe z3)}vQyu(GCaP+@?hX{>n?BwxO|2GzPy)cXWHwwr-nR5y{5>r0ShG>}_q@4{&Z`zsx zSY1*QE{MGR029c%My{S0U3@(}R?+rB&1~s;v)j67Lb+O{iyqgfZP1Yu$0r&hXX0f- zm5#Yi(zDO;hoD{c4Gv;zn!9@eb*%g}6oSuvlo^-~b||0D77SaqF8VvV`m!olR)SU> z`C|j@5KM#uSD14>QjxqO|tM*o_gBSx?cK1M*B1^>+fj+Z-CRbqh87D*TYrqRKE5z>Z~J&~)@E>A9EdsEHy&F=*RjHbk8 zG!LV*y_Ap}I>H1WPI{Jxt33}tM=HyjB1tQ0nk9}obeVVbrDw*t4xEw-qNyedz5 z`WD79zOmYBjjVfxLA3-v#bMjFb=GJGKLXW}AYc5+&Ca7H{CrtYU+%PNb8m&J+~DL(^qVEF5TnN1&RB2qq{kl)~$^$SxXmVd1AHn0qviqMv_z5 zv|gpBV9jR6-*vg#40I;pWLy6!>6^`d&?=5B8M~4zNFAi|C5TMvyuKR~`={6bU#(!H z9c1mGfsP3Z*$Jqdf!X5D?Si`4zRLhKy#E;F`r5}>IK%y4nOZ3xcrEEUq zr~PVwB!3rQI^7DKZy$zSM4~VT3n<%`fZGX_>vLO@x$Kb!Z5jz3QZo97+bLi|dyCL2q&=2!?(RDDb@X2rf#_>RZ4 z#B=dxVHbcnixxqI{2>?olug)gs`5TtjfE!S`oO`~19%)#YNFN`;L~6#a8+sq64Y{$`;&O1b-y+(CF>-Ew?=Qqxl2}(TCbAiler)_C z_TO@d+}zArSc-89!n zEG_zNOdEq-T$-}qM&Hq@t zy!0|@GA<_3KI5Bs7^_)W@!e6jW^cI+S@OIj?O zA}q9V;^(J(aZJ0};bE>L&%`@T2dWOy~^tnmtO3<#xZ)DTt?w zS0k*x{`rtOToY!@u+M44{ZXy>WS`MIdcAD4fO;vERKeUSw1T8e)WkTZ#qgm}6i|CF z)bqU-Vo)bNVtFUaZu6l5U6r|rl7tN9?XcTy z{T29>eZz(X+CWmeUz81~1*?6G4Ex4JSYAkF)9@Ksq@Ndcw;L`NWM%Cwpx>pJ>FMMN_H6^N19AN`ht}AKy)An8uhLkK!^GHenFS-tY+^TX_Vex}Z#Sam*06-P&L^G-o zIPYeI7ox2=WoOzkW?TK;xbSdqtILoxFj_oAcQ=lo;yRf^Jm8QQu93REE)Lk$1O!+( z``v6{#Z$IW^yhpkVyn8hp(17X%{;sL9WVuLc+T(kcYCzgdz3J2IhH7rLL@OFrs3Wv z(?GY4|AobMlndfFI`9y{ZwMW%;Z95u%srX9yMr4Y<-wGL*BkafEDywEWnBZ0d%))# zXQ^>2p1%(VvN&6|8>wrc+SL`ORqvhHYfeUz?5oROOBZ`GH2CwP2T&8=g@;;-utx)# zTx}cuRsE#y_=V}do~l(`IdNRWVW~BfolKjmmDok=pTRE>&3izBLIWIry70jccn3#= zIWFyE4&G|Yb5e+woioSv;J~gc(`&TugXO__a>04CTwb?C??Lhu97AFsUd2hk7Zs#w z{9@WHMUSoa#QUK5N&8p9T)|75{Cje3aCo;f@QMp{eI0BsKJP_^WeD$CHQjay2`&?7 zx{5QoqL>vL0j}@1sf@>oKln7gAhRSM4A>yT&X(-Couz+>mmt(D?QkxNl}UiZP9`LlW^hBOyT=;@Vz2SrDN}2r#RogB!Qqxn zVi{M0gKB7@(;n~uiJfN>(;)FBcw2w}&;vz$S#BbEwN-XL{AzIHWD=M1^W|oT_YZ4M z(S9wz@2WOpW0|B0T=5t>)Xg?s>tSWYcx_(B;6$cW8@ckW^yiu0ZG`?EPu?o=eYon( z#pm$gRWWL&9_BdWOZ!|Y+oNE$?Lp%Gm*k*D)=b^k4EACf*5cY3xzJ`yu?yx1y94nB zCSLFqTVJ#ZYNo$G^1xxK`B}zbPd{{pRRLBY-ki~s@)K@J$ ze%_hWm}MszzuOPd;B9m0> zx`cNoYVbO|$Gh2DlxZ-$G+X{D^vtQohEwL4$@L8sq zV~@VnhXhUVO+w$n{*hADmWXF;#g8Qnh6give;C|o7aE%yXCCB-dNoDtl{~!7%=vt& zC&mG>ScYim28J^kyk9z6`K#X7jU%3$?`In93f2r2_p~AGo=6THHClSjya4hRDhDLp z^I*hB{&cjd{d@wnCi*XPWntUhmrTx`KE}T~Aj&y_e$IjW=hW4D1(T!fCJj`Sn%sX1 z4JhC1ug`YW?)Rmw_=Ks1Z+G7gUHhs%zx#z*(KG{Cy(NaF=xmiS_Kh_&48jxwq?2pZ;QtB*Z{ecm$3>qEEW~;C&0?EpOB) zewbr{H!ibs`Hyn-L0df_0&YTc^@{aXfQhq6gwM`Tzvhz_yTK$+Cpb#?vhO0gm)-DQ zDL}FqX?mo&uY>X@cwMNmCPFv zq$+o-I@B{FjHvVG$|r%t;AyNZ?EZEzerNXr@Cd%@SFaL)Kk^sJ${QlGJ~8m00y)b2?7y-5=ZJDm zT^es{9S->?A^VC{c4reQ)y)gC4-lc=s` zK&(Mo>MFg0tqZpv=$=p78f|K{kn^*>x?zdaUmPp`J(JL#o45q2;2~*l?ptzW^{AvQ zvV4kM{htAa5nt#9zS_U7jWe+S=HV?C)*RvZyf5Zq%!erXB9LGY$h1rD&BXnK=%~Gp zc~y(GXBOM^^`Yd~WU$*A7-lUE&| zZ)!bENj*)2eir^Et6P1NhPJpiA36&apr3K38~3Rl7J8(9dsiZVRF9JN_}}^%G)zVs zrY|s>CF8D;9m~~YaLjw+Ll>(Z@wxxe=ZDmODT&^Er_qLF2jJ(0C(6o6?W9W;?`naL zuA7R=Y7#{>P{9* zmQ-d(({e<4KD+e>`6F<-`*GA@gy@C`r$RA>@@pI8XAHvnPL!Jun`NqAah7Tt^5eQi zKHKfy0~L{7Er+Bz?3|LPX%)oD5}n=$7!{)V`tvMP|E>CqOhP;L`cB?PFu0%Oa3O^F zicu_0d`%2h;X|b~UVMBbcR5YQ!qO@8+c7U=lSnXB%3oN?3=J}Zcw@ZnV$nIw`qh=_L-2`)1LCcRF3 zL637Ot$%E$X6bk0&aqTf%(Ah^VvVKr7MlTfBUAoGMnq27_?xoXOM}Be;j$Ah|AxaEpojE1b z<6*qRL*vS$HwpDL>E`Q(X)i|s&B#Brt(=_Ys&XVZ1-Lb`h&Qxy)T34Qlv4Br1moNL zyMsfGp9%E;QL2idy=jvWZbGpG6(IBHp>^*5_QEK1i1@g}gu6*0xSR1&d79uP-({e& zjNm8-i!y8GQ>Eq9PyS>vN0EsbAIWTlQ&3P4YR1(A3`58?M>c?Shc_Pq&`s3L9vKV~ z^N?`0KHGWNX)~IC{vnuaIFddhTu!lBkD!)+m5Z=pytMky!~ZxVE?vR+)fY>fOAFg# z)12%|SQh*>q0hN!YnIP`nKq$>_}l4(=RA)BOloexpd^B3bB0eDU<}3iLe?rhf*uKjLgqKJ-q5j50)-< zef_UH;yBZ}pd0Tw@N@Ca=NoaHrCrz8NkI2%3hB^=Wrn6UuzDJ~c zFWrGO7|3-yQVtr~M77SiPN6XE7n>Y?Ej<#;9<7u&p!%}8H-qY$=Z5kzi%^+e3_G~Y z3MSho3u`R@i+DPJ$!QYo3*k8&c3a3zLN8Le8~7j!I>_a6*`}aBr;rKs5HLY3gJJs7ZE;PXq#*0&)hrYY8)1bZ2wzIq5m;xyifiw^V1=^7<{;SA0=Za?$y2sIop4ow?Xnl@~9= zl6jXGRH3Z70>hq%h_7q*8oF>oVSEm@Ot72&)$#%)Q`_fqKQeZ0xp8k24kfZi&It!g znJ1g?UNf;>g($0&cY80|_YWHFc?)Kiw<)#iDq4|00yxuej(ll{PARd$L?|{f$q_GgMJZY5OJzWiT7%xINr?zHa2jwB0CZB!Uw$IUlL9@%?TbGj$9Ew+*@!Q7*}RDIS59DFjsRr` zk40_>615F=Z{>?%dHVw)(g{7FYJXVP%nRHz*}S(IBsUBDJNG2Z?Sw^gfD+-fP^W12 zN-(eaCuR}~CPI34ron@=jIGmH45fD!s zNsF68L`u5-p8#iG8bxMTEI%!IG+vTs&cy^>US2XF~2nybS3P% zijZ}cn>Ai_zlAE~)@qv&@9XnIzj+6a4ZXLPV)+IpBkcTTOWR4WMh&`v{kt{z9A}j) zUQ$wPwCo}-v5J#ky)qwoh^>80 zT>&HoxB&+OO|G~{_v-6=)wkcYWIxi6yX?9%lx?K^F9w1Hck7Xlj< zOPtx9nUnp?rjnzCslm=Ol7Fsu6zB`2j^C-dh!^bDlp{wj zbcu8Yr!f+%e9;&2?n)P{{>mD%QJ|aw5 zw(>Ns?Hya|Ro4HoCK+OM;qj|C|H?QYYB-mEbaHeRJ0L4d78TU=?KdxfvQpMY1^n^S zOe^{nPdR0I_NYg(=z{xq@W8u;|Fi_{3+2z)*X1q zZPM7pC}R`rWQ*e#Q&9nXtk)6bqw|Gx0wiY2R^?OY~ z^h)4yuRWiWQ=d?SKhx~5@<+iG(kBGGf^23);gDv@bnb!OF>UOw9c=biG zjX&P|On@4462fEAjg7y%)>N*gE(B8ln+k=D6u0~dr>HIpsFb+BDG>O+#wV}HCr!4r zs6smA$&WAZk3B}M-!-RyF95wtBDK0C86!=G0qx1;kvE2{Tvuow z!$DZcAd0}7%k{nQl{wh$c(uE=|KcQprJAY?j_U3Qu7b_425PR)siEgK@G5pU>OP&E zBe38>M*5LrQ7M)lD=pF9D)fPLnC0#9+A941;W{NNAK)VIvMI-uCq&>W z{wFeNzV%Iq&~AAss73OU5RG{dSt(rlU$jDm-z2*sax%I$CjB$Ev{#X#zf?~&rZjy$ z9&irT=5JX{FiUcw+RU&`rx`J4QYM2>Nfg%@IVy)uwoj@fT%oFTv5*FxF9XBM$U6oC zr?L90O_EP)4c0(~f)*#z1C$2Lo|GQ6Hf-ssM29!CZ>f;Dks~%Kq3YtZOnyrGzGw9n z`kjIZnr{{3tj#%(mwIG{U*fzp|CXo;1061GUD8^6G|3B7Ul^QDf4M|ItT-ZTe0Dp& z!u91^?w|AaIzsceMKs&e)<^9A0aNWOuNif1+Tw2#vJ7{pOxJqNL@$NeKL-BfEZSm5gYUtr#sf((rNxk z*>GXo8{>ef!W7cnwOwNPdYooR2_!xdXT1|hVk%6Km_F3qp*29qZddmO3fzLd4uujM zuus%_pam|>1b3SK$l`zJhjFCGQX<|7LQ_;3LPS@sGWV_euISUq99%taK1ndiw00sT(BB=i0 zzLoE4ThE+ccA9S|UCbfcX8&{AmPbaIim};~2-5kzO?dDUsdeD_41hgvR5|s4;rtFm z{N60Yt~qYVxwDDb+B`-AL;<7t-ChV0hdeI9>qnk8A8t7RPX@+ z*A+Ya>nwBXY?v)d_JR?JBe3ql8xD1FcicCrQy0Oz9C{~RgbY%D zbN8O`@2GQ1!hG=m8^_;?BrA0*wJL28%hq*azlt{X=9OGX&%9uh`s3BL zsndtqZDOkNU)d|;ViXS;*%8QWxyt1VUdUG=HYlzSZxj!a?B@Vp|52>9qn){q8%>C^ z<7Gkrp#Q_^_Wqk^U#`7Ro}jdUW3Bg2r@{3R==${C;THlzg<8fewFNFw7#e_;@UN5b z9xp5`lrEM7mVREAITO(7^)A91BUkfsfoQHQSS8)Smg9O(Pe6frFziE5ofl16bRfqo z-P2xWvI8xld2s+Tlamr4V56gG^yt>T>w_}F*+4&nR(9XlKXHC~UfQsdU<$cl=a(4k z!5PI4Jf_{|JMcfJg=~DpQ@NYn!QImcFH>5Kd^7SulgrDTvRrh}c7iw0PsPl1)x%3f z$AQV+bMq*;$oFI=)rt@t5ciSCTtI^j@{KX`#gxEfBL#pn{vE5CbO`I~>$;tp&hZT$ z;{-O^uTtCA1~u_==`UY9hi$gmZ6q2P>d;mB^opFE=;f!+Qop$`&rY7nJ6??zTE0K#qWm7?giU9AKCGdiE%&8tu!9ul_M z2$wfm9SPH;rc|pbo$okCoZOZT_I~6-+6U8RDXLhpB19=HbAJ6DT9E2$vI2JQzOA^+ zxFYE3t?q;U>Mp{Z{%n1OpOJE)zr`vcj}a&eB%+=F8^G?zPqz{C^!;~^-*WEzgcIS@ha(u!BS?;&9iTz@MI2jW?PC zN->hhGSmgG{0vdOkHhLZpPC%9qfV(_#XSN;cLuA-Zp;)sJdl%!`QC(iuyp38@_zrC z>x&5f?Il|h42+9fbMvq-`!kGDA<28_tsk|1HhN6RRMaoA1_@@#<)}ogeLQCW{hO1g z-odr0s72#nyFY68OVU-*HbC&@2I8-(oAJn2)Le*9K->#j*>@h55B>cpLZ9SWHoLTF zw#P7@_pdhhO9%v_MLAp6kllwO-DEXw>UBRCX!^fNHoL=6 z^XBZ~Z~S3q3&seBRfb*Vh8(5hGA=(H`tRn3T<7A4Eo|E^0Q(XAS@qx*4xJ02GvQ}T z_})Og9}XA=;U63ZAw8hGCE&mHuKTX!NIR!Yo%4(+1QoO52isYBkG|}y&nO>%mu{2F zcdh>%uq#`BN;)qh_WW!O_eETpHtdMM_EAq>G z{NA^wy9ml1=g+gvR2(wUzw}%Kee}AXK9+sONqsDmj(>^8Icr|En}-%0GMByfL(I*<)IDBzR0aaKvbN{Gl>`wjw|2bG?Mm?G6(s zbJChyRQmNn?otl|ksIY4N{X(j#KgS*8)5ox+N$K1$3~|{!b%8YM2{vdH|@YL>+YDO zB+qf+QJ0J08~37UlD-?@zP`Zw?kjr_U1Ng=G;hXGtY*s}e^I^b%sYGeok}!{Q~$P@ z_}x2@)iK1^5;`lRt*e;RY%gAg^gVVD;SN%3XbowP`pAQ(j}t}gc`FBKwkiG^^hDSs!n!>Y!{T!>K6@go1`r606@KVmDV& zKCv8}TvUIKPO5pc=`yI7O0(k_oA-KHXzq4H_DOK|IZv4%1bAg9O0e_YYV!ZPvWSeh z0Yv)x3qLYzR;}f0exKOpFJjM{yz`5*k@QI~P9uD4!uMUhM7Q(fxIVbAk1`E}N}XN zw+k#385KmnS+4NhWGC(|>W7mjXd2!CF{(`S9xVQTNgEM13s)}9Y+|T9y^*XADF()n zfdwXJ?3bK40*F%e`QAY}O!*(LsB%zw&s;aJ(}7cc3-u9vhd1P(1$5IncmaX6vO9`_ zq4f?4i3RxIZ7XrO3H+%G?#kn`>oE9mZttnnO1c=N-oKX`ZK=}ouiRXW$AmbVY!PxN zZI~_718@zIePlBJ?EFJX$Z5P3I=or}PA$|yU#t1u>ZCOi@edbV5%Y6rQ>xH?e ze*BvjrUNO`nk~N2uuV4a<8$wKCCI!VNV8QbD%XR@I4XhTASLh+9Siu9W9hmFm}?B~ zslgN>E@N;R9wBQm{7w=&2k^NH##h5J2EzEUs$)WHjma!&zZU}c8JLhBk*e1y+xF-TsYM_w*T>N&Bxmq^veF``J9(G4~xI3A3q-lNXP!3td2-MOG{7V;KG!IuN$`90Hs^s*f zV^E;g*O)YMw^|JerEXc%eu}O6s!VDo?aVn9)DlPtU%EE~CfNWf#b$8Y`k&Gl0qsUV z#27qAPiWmzlr$K7#bQH_4`SuEUVHdBKnLX2BMXJ=kjvx!wp*APAyqg6j zvV^(@P|gQb;0(}=Pm8yVTV z_ZvL|7*4Wn=kqKdS|z}`3%?mn4vgnEhH>mN)-VlOlF`04ba(%H5HQtNHTlrIH;#Vc zj)mtoNUWi) zFBF*n9FrK`tPa#Yw|@L^YMR8#gq1U=?m$+UVT=d z`F$1@k#-MnZu*|-hT*5+t{EU=Y6jL~wf7OZPa?#v6@k5NBsXgCSw1|aTm0tzJ49U( z)qse_^W8R0p2pr=X>99S20BCwcBcVb&WGz~i_7BDy&z5MOo;|tD zLyn2$!OJ@<<+Zq~psKOKf;WIMu_M8cYXBrFR{HG(*Jc|12cqN!LE(NS)YXe^vhMzE zU9{ zx0@i{9Vjb^4o*$RrT@WpIm`X2Wt)+giBb*zuyZN!J_py8 z3b1r>ov3mQ!kzmCcNw5B@ypDuSJb%wYyu7&Lw0{JUD=*;`R`(Z4LM9qw=`Cqm@aSk z@j8D0TVosMstr#aGVK?94KzYUi1EdK@GA%$r-H8aYu&ZGOa)F10Q?1T*%z|sfqx6E zd0e)@PW!n~5?Fg4ecR5{fRoPK4P38QR00d`i#!Frl$*?eMba@Hz;<%)ySdFRMM~aP7cpuLnk&>(~t6&IaInJr)R?_EawIj$5g0 zxX?F9BX!so{(Su`HLVR&dLjnJQL7t6NrYc1Lk=Gr41dfnbB?CJJDx%{gzGaE>gc#wOIW7z@h7j#0mgp6KlPEFu&emIr)fy9VIRazdBjVhUkplKqJl|3g8BCPw*FEQHF!3m*qR0F{*dhq~^;( zzayxePg%dd-IqU=FpjEKDbANO%7|T6 zw8MXDl{NpNAY#=tSF}?zkm)bDBf^ArfCCxI6P9)8sbm+kr~6l0ciT*9kg2o}K-~o0 zGY2Et_@`dX>@Iw%r9!3-F$-y@e$chwZL8FH?pQ4K5~|=3Kn-(Ud2wA_;Lr%PMaU%*9|Xe_ z11gvrjElMh=}#=_T`QMw9^bGO+FWH|Wp}~^WVUMt#T)?6_k*47|GFM?d*8@#d$~CE z^1x}gk zSho!d$BpC{=E-;YUVpDapK#%H0RY$UwvE>m;@S+v{eUMa2dp&)53|8hjYyA8`~ufF zbsK)4>r8tIAE|ONhwrGl%&^1$J;eWjWh4Jxxs`s{Q~r~C^CY{eqhcxSJ`C)+nAt0Q zY(0sN5P5*>Y;5*i*N#o{8;Re0tUo=n!3FI@hFmBDYZoEsDg?992?`DLer?2cZYbh) zaje)WF1#~F05kO)7<;jVcH}}Ma4JBgwFeHVayYDVgsSd=c4Zzn?#kk~YC?9C@Q_I; zW(2R}aoxV*0N#iKZ+KioVAlq?89&@duFHQ2+PF4`7wzsxoEt+PTHYRyrnW}DI3p_N zp_)q6j{ZXjjY5Jz)eK6C+1y@P)pXyyls0~3;qJVr>-e}vjNV_dbq#XlP$8+%r@$kk z+_ka5k)+M_&%%isB8rIk7n~aE=^U@C>zf?4-F1@W%V4z4Q2ox;wksUs{fjQ&Uq3Q681psYd-Qh5 z`{Tz(vv--r^81#R5tC#2G5+i7k<59lwiMYpYGmeyzm^5_mA#%DN13n|e7?yNYJd?8 zhX$_6U^VJZ@B`k5R-kJk@h@LShkmVfyK1})32IyeUXMI2Iyz-TSa)k?Rxbg|Lw7RL zNCjia-c*Ubu?o{P&tVJ8?r0xo`zz+pqVa##0ZUqjwvqTd*DME}iY&TNT`$L+Ff=`H z(p{0*qbE1w^i%E{fcCB5W^8-wzQ3G5vgO1U*W<)~t-i0$w}|Mf3KQgP-iM`;V}%Wf%> z#?Kka)C&hgfA5ynyjL%ydC;b0WfwE`6zdQ<;hX>Mp~y`CmJ)A9->9^zL5r7}i}Dz?4g_OkcVSh>Z^Vrs1!qNA6ysj#8 z^=4*GLfEo*84G?Hpbz#hVeJE1|MJGpRkYFul-;hj@Xn*+l1pwb_F1Pn$nTrXYwD7% zFxyFHEw>fg8qF-rH2df!qJHZ^3|oROogA|iKThXdp6kL3PMDwd9$sQ$7+)BGkA&|* z7BQu;a|ifVDi{L_!P;F3aiJ2ELe}nHGfsdv6J!NrIt34PRj&I&dYs{?UHGyy{x`6O zz((ONx$qmQ9ZZp%z1;?JK>xj)|+ zawYeW8l(~)ek4K84fe4v2IPamQgrwPE_9j!{s4x;Urzz+mGJ#cY>vtW1imMZJ%wF| zA7X_(LS~&?u8&o8RQ96QaDZJM(OH*Dit;PxMf?ct1b$7p8?tR(cL_BZa@~kstqD0~ zzW#QIPcuLUm|=$!;}GOB&Emb1VI6IHY*hUXj;~$kD`aH~08vC-7vf)wzR$~%(06Ov z6fV1ph`w2Y9E^M!E-z*1w-rBoYw$9M$^jyHJhSa0AHGeP=)pqpW!E+;r!jWeO}i_T zC0r%$2C$`b>uXQ&U|2<4Ab!Ph{>|y?czg228K}3jq-3Yx>Fq zk<-#6lWOsZ=QjW6?y{7FP`UAZAp08B>NZ%|;BQv1m%2 zi|YU=pjD)?cN(1D`tN)Yppq?k%+txbZR9j^*Tco+7#5^SVJPKD_LsS)>0$p4kxZ_Xjr4<5Df7 z<>orABXe=ccKboS$|WDWPceK zh8cTa;72j)_xLtwfixm*PtRCI^f)ReC#;yOrQ1X>2HB%chA7-gxv^YbQ@>v~;)%L* zA{bjdsu9IQND%Z%5My1r$ajuNyq_W=aqy-*!KmS8(}u%_D6Ra5XORj`{!@acbg%gU z=y$rGynpX%@|Q&$S~4aEIdwp26R2{3G*F|uG-}4YzMm|NKTJ-VRUO-VGar1WDv{m0 zSL?|7;{{0zs#8))`u>_YkA-ifJE63tPkVzLv1K2arpMgXJW%3nDaXVLmtTf^i8z^t zh^X2XEJ#N$wPiK=)?;kKCg=>{!9r?)P3MfiUdDZ4lS!Qql&-~*m3-V^C)8H7mSgA} zXSo>e?xK}?^AfsW4>~c0SAtS#BGfeB=p-{#Rq0PuSTfW8Tall4#@nmr4T$Hv0)cCwI!% z!=r#~4~|z*)fk&~eeeXI^sJ#{y6xGxi*WpKp^!&t#_An4*DT1aL8 z0;>W)vavhu0k-1sONY2zz`Yv2txJUs?|Q+7Tj|8FQsBRMV8g@%SraCgjvzQY_!SBs z+S#@V0ak0!LkQdn7it;^KG6gorRPrVuI9d{(=E;f(%uZqhv>et zFp`vpXu^v{Q)Y+4LuFbz^FP+g8I+*)(=$1{sIUKUUAL;NA)&}jEXNYg5#JsZ(qR#@ zD}L<@5bU;7_>F07+!FS$-BlUBeCe15j``e$@2`p~fd~GbcD;B^C7cOHO$@(u z;X)|vb`dV|pdCyFu(AW+H7Z!iY7*pBvNOFZ1O9qo?BJ`@gl9(&cwCLcVK#wF2(-Kh zE;J)4zh1~T)=O%dZBPD3uf4whI&70U;;`zW!Tf4ThG2Vb~T?^6+cLka74K zhsw5J$Q6EV395%pJcmXvVNyeoMb!AhBSMXyFf3EV^Yc86+x-nbvzVmDQ;Sm2jI z;C(L4qQUiVIG(<3{aeyy#9~ENbY!Flz_fe!MC>~u`Li#z@g^mW5uLk|Dac~<9Uvv2d~8)8160TZkG{>0|)uL z-I?G4wY>n*fL!(P-H)h_s`@)yswSq?v2rV9P3PuDW+FoS%O;2|g8-4>*vXmT)nCXI zvb&E821Uvgi+7G~mmQQpXH|(q=XCrLyR zaLROki`41ndgmQF5@=%Iz$A~P_)Xe&$^#!t!TryQ`me{b)LD<7tg%g~zXrwxMpz_h zFjeeO46|4{Um%18R3KX{EclQDEC)APIN5_EhkGP&d;O8<09(PBt|dBtD4)hnZIaCw zH)7xP7Uqk%Ssx?^&fdFN>FDnX-+LI9GJE9if*MLO(TC>rcN#BRi&*bDXasdXw#UyF3r zql3vQ+>HXI#~QB$0Q#S4@TyC(uK3wN>-{(B%&HMrLV(;Hx z>$}!U{vVD$u=2g|oOHq<_mHQMz1V zD*i*0Zji=tnKGWCb6pnS%XyU85y~0L8n>zmgGd{?ErMI#Op(3Vd>20gAlrg}Z@tGn z_yWYIIO6w1dC?Uo;f&5*GO?^p(0ngGRfI23?auw~uUL%yNybzbyOt9igZ&Ey;$8N5E7laHdPGqBx>4!y{*9tEpM|B&#}ADMk6$a* zz#eqjULl=QE06P_uWxwaBStr&{RrSaw2E)J*x0k`prBU2C_^wW3Vo}W*%)6(VwHCC z_!Wxsxn+H(XQfe?w--IluXWZU{O>B$Fq+PyUL%0wX^dH;val(&)axZWaOmoG{Bh;X zwOdIh!o+i$c4xqxggAZW#EiaKpZ5>Qi;%+LR5((k(lzJc>NzLdEmf3Ba>^A2@}km_vE=6*6)pGDD{Drq04{)3kV^w4>*Do@5QRVNaY1M7`T znMDP1hSB5YURD}a4Du;8sk~r@ai*+b1VK-Nm7fwIVaO--La$z;fT8G*$yA6?cp}+w zLh3nDLBd#9Ig*osdQpaU$XrRd*Z!5EcZf-5-IY+V$wlh}(W-9g^g$Now};IiZ9L%m zV>BsIHGlKM-Z4Ie&F&9FdrhH#26rG1Mp~%+I{5GJ#4(ujq_0V?PIa*fRCfxNZV8f}nili! zDZqH)4CZfGjJvta8_)5fCDIs+;V8in5NZuj!diZ8PKJe-L(a=VKX({`s2DP`Hy(eY zkv(5OiES;!3X9LAbfn~tp4bhxa(HP*o+T5&DK5GIOs|VlaxKtlBDX>r%kez?Z%-ew z{vqGv&RQ58bq?n1@SoE&y*4O(-eNi8`h{jV6G!ia%C{x ztvBvqE3$nU%}jHx*jrxCL>@C`wO74}>~Mn9(Gzue)9DyvW5(|jY#zq_uU3!=i?%(# zc!Mr1XbA}z$YiW^J?9+T@tT$+9Ev#Rz^;%CjfivfC zHm{_$48bQ0pJPQIyhF(Y$rl>jLm*tE3Cjjg$BezR%5NeVFcY8YNKQGh8wm#yGNn|y zh2qDlZ|)X$zcp{6+uf`Y=TD!8J=gDt+qB>;G$eHRBlTLYxa|wA&xtQAzkQOoETki# zI-kQAt(&R;3C3nBVdHnGMJioHt-;HAMXLge(KWzhefOgC~?Lt z@|MVMBu>p@8!!Z4M;F`o3%&H=CyT+KW!XwZJMQI~t@3wdSo*T;YJ~0s41XLp5rg@V zlq%R|Hj9Jf#K_k~VK zR$&vcO+dF?*lla$o4IRw7yL5S;$#k4TbA@VzWP$p8a2uMjlPf+g=e|X0Am6B#A7u? z6*WZ~%R5tbGA?|(gZhBd=m)!OaxcwfuA)H7VjvM!`zoEykpqm-@AB^}+}vb-|KiNx z;DLRQPdR&;cK*m+e_W?i4q3duc9lSf*t-yemN4U4Xi{|V^3v91?oO*%SbpTY{6lXG z#*zWA>h_(FSGjs%jIMEi?l4h}w@3Su%S1~UL1{c4Lj@ZIR86*do;af1DaYJiR>u|l zADU9>JiLbcqX=Mu#T>P99JHODn&^cF(G1*QL2(X;m5kC-#Usy>1HXUXYqn2n_dF{M zn$VFPYRYp`o@QcN(IOkjm!U5i`Zhxx+Dy&$I_S#rOU`S)6!fR5BTAHzj#qR4@z@WR zwC+x_+dY!j0(=DR644hcnWRKV>D~u(v4`T}%mr_WT7e)KAokLk>)mfb@!wx9DWsY5 zeMJW~-tHi!^Wm;43RIRIG!~F7QW@+)or=BoOTj+!P6laO zWa9y2Hexs!z&H#pDcq2m?YY*Dpl^asDt3Vbhi8q!Wk(_Vvx>R6#ob9gUX|`7si`zw zLta=ZVHskuB=sKokQaBIwmjwmJemD{@_3#LKOOrziO&S4EUk!rJb0PDHIE5M#YNXK zI;9*)^nE61tEOYr@ur6_G$TesSd_%x?^Mob6+J^GYx|K){BSH_9QRacvG@Ro1K{IB(5IQRngWR8U`H%1&+)$KdhUDI*PUD>NH zLhEK>L+$QRuDMQnkJrND;frL!AIIVTCl~`aV{?ZGgj^jbx&x@g93r$d2rFZ61#I_68+1LZqP1nzRK5J537)45 z-;JM`AnZSaR4N&fgN6G+NXeyD%^MljG5d_;{w( z8#3Ji7P)62rPsMUmuRXQG0@7XZYr!D-(AsLrK@;=SlG?1SuPGZw zY5Bvk@0-$O2@fjXz@_q#eO5nN(EmiwR{q{#aB0~?9b;^~RP_)iDQQXqrsWi{t? z9p_16G~MWZ2eV_)yW|Gg1Ui)Q--2M{WUYU)fX@$la@YTkP7-o(o6-6M_Ouk_?Be}% zc{A0OQjJW83#lmVC*vWb1RZwcizKSfIY^sC>&otbQXJAcA`)(+T8SL85BP1fd($6OHhM=#&SJ^~q1sSl~zG+GXEEwI3z!WF9fukaolSS>)eO=(u4yanWlz z2Abs3reg*Jiguk7HQrA&;Paxniz(YejN}|E$`l5y$=x-XB#R@S@AJ^+$G@+PB~B3s z-<~PW`0s!epe{4>j%(H{MRdXMHatmJlfI5Tykck)m|>K0#oijtS}s=bL(FM<;|K?2n@p8(uB} zZc{cSUNmbG%%=X1Bh^{eBHN+%75Mi^%f5BGC9WM+4|h{9GMGzH#^MzTxr!6+Uyitn zPm(~Te;hcTkPHBPxsg0$mt;?u$Q-62C*{98tC;-hVBDTDf1>5V;3s&d?%daRmK~lHY0o*A2Vf)wJnD6}xUqPF_zqGtQE`G@$+t|91 z3eyf~hFn+oMX&nBKN+@ert#qT)JV%yZ7^Ox(cwg$m~kvI#|xUzQqX33mMIk@u-|6R z=#5=RCG#S?_3CQ>7Ms9;XfbQ@4G#zIF?RCn)6(EMQ(Ut?wp5%yd67D~($z89_3O-> zBSD15w+tyQNX65|bDn3mX!nFRK3Q{rV3gRweB@}u|8ykcGAEXOr8r(?Lux84Los;s zAjttK2eEjiwpI8)g%NP8sNFM8H)3{`ud+DV;# zv=ue!@aYW^-wO(V-zTO=a!^ka7MQdx++@PQS7at1ep~s@UZi0;q=C-L*K+QOh<%Mk%7omKdURU&W|pzG&-ppADAjLAI)pjA4~I3A_jtta*_W1A zq`~lOB7;Bk#@_?*Nyu_#6GA{{7zoYHB z4^-Fvp-7yw%zTCtkhyr8pibHGSiJjRBFj*|4dc>eFZ=Rn?eC#ntVvn{vEOb5&Oq`)`n(+Xaq%Jkcy{=`r zKSn+U>`c8=rACY}lS)$}eDzc_W+hE}SKds~svf&dY3z;-ws?k0;J*w_P*V0G&^3}0S`*#WR11;}Wnx|ZtU(xp z#fcM}EZ?o4!t#oXDkBd2$#JK-4G@}QN~;SIhJC#r;))qCqPBaJJjOz6+z|mFjxTPe z8alKxDswMYwy0`jrbxYtR|`Ce-e(QWRITSjP+Dl@YL#mMe?Pxabm<*$Xe^uIz0|-7 zHYFXq9a78bufo`vBV&`kh_x1dM3Yi??4U}JQ%3eJlc@eYm7~?qYfF2_)n*IZ~PJuIU z;5|KIfe2Pp)IhkM!gO$yEF#f9gTo*vszX>WKBmK|orsH^=^Il0zHq-M$C3BKPag}nK=P$$; zp854~;_`LJS#MJp)G#wR^%xTF5b1Hp`!#$Oh}q1hSb z%raHCUM@nN0b!v7TFkK@QpM#VtxcUH|4qp-<4^efRJ{hJ9LQupNsV~UYp9q|a_Fa0 z#GWO%zoz#iKsj8t9B0(Hh@DpTnX@I1qVptts3HL@aQ!ANV&JNN66Oy;i=o=Y&L0{K zMETD^D>3>16!?{At}pp^A{ufhYF`~R^h-MXynL5|thzU=Ke_n2et1<*&Zh9)fgzc% zWOXZ^_B*oH+H#@vswM6h_IXXG_`@7?h30j(62_{hEgN~f-T=^jpD0e#eHrzsoWN68 zYBggo#s#=TbU(yx8$fQ3HJR*7yo9NUOpGxj!AkbVMpL3oVo6phR4v|?}>c}lNa zMW-{A3rlaE!mGu~&1?*qhEo7(G|wpRRl%LXZ$jG0w$-OB)r0>39Lm@KIF!1mc0N9+ zc^$0O<+vT`;5_{mTRf4=G)0`gsEKwXWL`NN9jQn)#}`x0JL5lzOM8c&2*mu%S5YTTA_)49g7= z_m{*jj2l=<`AY;BlR&Tz)QgF03xfT&*ezL-zTCBz|6)~{TG1jjQke96WWi>quGDWF zHH{N}+WeJ@>(DvXhqf0U%{elHWj9DCjS8>f!;A$TlG}IrCE{{UL$}2kM@RjrJswWW zmW0;o=gPu@-P{@$u(_NY>a7lSt8k+!t44X$xVATD(=ic!Pj4q~TjBwE7Z zt0|p4Hzx0jeieDORMl#fh+MdVM%?*1{_mqqw?1kQK zX)1oFd?oQo@6vrd4-SB^2Rb?<6oV4c4`uV`s_B;Wulav`%)VAV4McPf<#&zF7TLw#i7;_@sq$ zvVtZ_Vl^1%X;itfR#e(2@|X6X3d(YV2HiN2{?n~&wa;rs7tdT=M@j!UOH}j(rcd8M z<5Z_?DfZlv5F#h&@28Ec zQskbaQ)>fs!^Rx;Y(TA2Q6W_)FCP{fKE&8k^t^-xWgdgzF9bqI=Ny$Dw}1&kyvJBI zY+E>^cba+TwqL}If2(j1HDR4^o})n9F8r|ug0l1yeJM$O-`7SCO$yxU3Z`S1#l8ws zt2MOfm$=dma!6)S2_fCTh&&yB%DUd@ZdG4%gqg}Z0eslpou+p=Wj{EeVD(hF;u-!c z(?J*`l!yrN^jsD7W$uT1HM8ff;hlu(eVQ(R);Pn~Y|-=L>4<4~QHm+|0;Q6N@}?*X zp*(6={-~so0-y?0Y1wxWZpGme#NsWon6+Ik9%`S8uuqC-?~vwF#Emc@Cg7V5O^x8B z%XmLp)4MUX^DAz__Bi>b#4=QRuf+3MQWnOs#B-B~hj03WJV}-u<$OIt&jgsVb!jM% z1qd5uK5d5jZe{kt7t9+&r&>Ctfd=X|2DGhyV;n#Z*zsetf*YGx>@n}QWZVMy)G#vy z6aci7?GqyW^rjH0_|U^x?fU>Ahi5LH#z}J>JYS6<>B59gw z{1L%js!0_{+QA0tLsS}Z102eIj|;$-`|AoJ*ywwn5t6+6{*`*m{zEMk#k8O7j)*R& z)x(-`fc2$*ESH;jE-Baa@2VQeU`u>ClyzezgMkFl&#$9a;VLG8nJ;7~%8E39hy)qt zkPX;e0T;0{un?A1;{DA$KM0qUZ*%fXM*%S6N45?a7r(%)$`z%0Y@F@4&pZA4R67&$ zOVzUK!y!_#wy4NV@x8E1U+en&@e{oeF0<~$Mas_mtWN(+sjN~&thNyV_G1ps{zHYw zM@^hY#*but*iS zv~wG<}>>%n8~XZAihAqEzq?c zHpWIym4q4IFowiGaYj0r%_0u>8s_kKmziE0(hsrLfJpgCu0vQ}VH9g#j>@7hd*OQP zBLazzpdCj23=P8daL>FYq;ycX_eOIBWITj(CsBF?)W>;z#Ep!4VXA;l8|rENmy@|Z zpVvShsw6Ez*0Zko2UB$#KSmghUOOgQl|O|ADYvJF`Vt476=7 zXryl9uuB>H$qg&+ly*)nq+%rhG(>S4*zaoXU!nE?!X$Nkjh=!-P4?vBYqP!}e*b1R z%xi31Oh)K;6zBxfDjcEEvlFu< z1Lo(eJ+JPc{&r&q(*{bKnvoY%HD*@Un%C@ToY&zPG@$g<*-sjTPVwNb0vb)UCc+Q`O0Vq})<)|J6tA@M0 zXox;7wOCD&G-*CKOelB*SI^Z8VP@W;eBF;JIO^o`EMV98vuE#8XX;e-SWZ?tDWWZk zh4lwE1)uZ|x>Ix@1XQQzu(- z3)Vb)Kl&s)aDRcUQH6<&3P#l&-NVyvaPoqepI*}c2^&XNj3zsa zVJCDnW#nPeIpk?WF41~N+U6Gszx`ut5(smT*bk#MA3!~sn3X?Nq==vl`(eB>Dv2x2 zaa199*m7kF0yd@V6r=gBhxx0YVXcH5v2hFLxmU;!fY#%*3*Z$*i68g{4jicPw`-pLSkoz~me8 z@xH`BJG7LXK|!CyydQhXR2-C>OHmyGEmBnkU-eK)eLMWt-X5$!1o~L|gNB!}RP2CM z^*t)8;c?RjhBH~~*+PFAawwGKO3FYxdRjI+1&5{hNTN(?=v&44m)$SK3RR z?H%&ZIo5DZA>1zmB&89)O{J*Lj$hwZBjS~sAVqp#gYQ z^{EDg5ukh%m1e>g z$aGW||I4FpZ{0^Rin1&FogpQ~*(?R_iy_jMi739qe{)p8uX3?D$`O@DXr`}J&Dr-2 z&JEPICW@ga0XXD>#Unof#V{k!CY(YXLrVyfRo4!MN$d){E1;d&>A&$Z^P1%TaRy%f zbnHnDptzwc7ve(j>#`a2bwLbhQ%wt2)fT?<)GEJ4IY@*AbacJ*cXk?XsMu3iSrwH% z7`5@M!|?E>8}?L~XVjKo^i}WTKK^6Nk7v_!L&WdM;=8MiJN~%o$}Dyj;N^ zP$FEz<=%qTfEI>2Q*Wd|Mg1l^L5PGcOY+Gt^d?{$LHuUG2)d%**7&K@vHr6{qEed> z->scj3O!xvU+puPSQz7FpCs2&I|icMlo@{l4d$mf3aUqOq|M`_ zMjnQ@;O>BP(*qGwtq=O9n6kD;&FlV05-RE_(;CG86<`lL3voQTf|s{$3eLA;SL81hW7mF7l?%o0Ce9uV za#2Ig;T%bE7bif;j2!1eT`}a#{c*Gf9j8293Oo>O`(-atp6F(55arn`_7$XAsi*%f zzkDZ~*+T>SZL&lYHSm0_-PpLmR zZ&hxz?>Xv0O8%P)gw4Zxqpj1`BGwd`r8LSK{Cs_d250czCx^u1&O&=4q_~Q{7;;7C zJn;%f?!wr+O-s(YN@P7}0BWyXS_zdLj16D@{e?8i*f>6?K_`Qv{A;D|lmT8IIwyo z`66m+7-o-BPkrF!m9a&C-cH7*QA-FjLQ=G0e-^JMexuz#x)+077-LUO%jC({&qeEx zbkc|ZB-fYWzKv9>@^c|HSf*HADVr|ByMtD-C#R@-;h0>kb6#62-Ji4&@Lz^;wMV-T z9V_WJQ*Ug&NA%8w;kH#3er1j<_@|K_llGtH!by`rS(Zssz4xTVN3U(bvPVG8GUl+Q zHC`qs#Pw!E$)&ukX3_6taQC;m=R{PbiLt42Z$Xbl%1Ls>jU%fR4k5vW;4Zbr?~J#6 z4qh@lvznX7{q-(JHHFD7mVsHN`OF05*HZHSC4w&O``O+8LloKoLKx$g%sl1d4SszO zSL;Ed3pe7RU2ja9|56jN1^8pI#3 zRF^fXiP3;w6FiJGBE{IQaOCPZVV+*!!rw$2Uz*0E6ov493y&+y^^-6Bug^EGA`zs9 zVW*S@X7B>DMcmtTgBR?&0GR6+`+rh$1J@_{*+~Sn4L838)u0N#9B{*k-gPi4JvLb9bX5!g0O@L6mpOawis5Y5tyZ6<^n;zXmls=|1Giw%{K%2x z*M&T@97}4Rk>)1xx`jI6WkE$VD@Dwf16yws78m`t&vP@M#w&`|>9cCT!|99(n8}8{ zOfGmeSasx%$$qk+!?tyWa3Y){JAB%vVu#@Bwwlb>UtWv~ry0FO0GASalV5(jbDp<# zk5ErWfS^N#6fWy(S%KVWz{;zihM9YVm}<6C2ww$` ziERSbtU@~sn()e`wVOe+YP^P~pF^F&%MM0spX6o6gDrmTz^+*}hqx_!XF!R7KNDMm z)jd}M3T2SeRH?>MR1vi|qv3zyoBgMgp{%=r*vILZMFS5WK20(FVd_006KApf0Ly2* zNc-w_l0&nl(&_l*hTI>8pLNYm{0WI!CbIZ`oXx?r@L4&?2zr;FGRyd^{-Xy!*5au= z?A#|^$c?jMe!s-q`x1>6G;q4tUIe7Q;}Ws>Sdq{Rg}S4-GbB&~|2VmRGxHYrHCQ%%xvJr$sCKWR0oi}(wl)l$t~xMNiaTZ# z@GyFcbn{p>#JFBZ2ImSdk9%6N(52c^r&)eT2FMt|;^`DCrd*EU&)=T#Uu*F)%YK2s zTmbMgbdP4@zv$%+CO8 zjll$%4Y;9@#1vJ4la}T=6@qcj{G3l3+>10QU(?c>_iQP(w+dWRNiA|Mh6)H*lEC$@ z8p&{Bjya2a3TZG`ikYFuPd=$s8sSBAMVWdO1|5tQhUk{Ik61NbM-Gdm=_tmgF3(L+ zxn6zUnr~IMsavHU&Q{{cpPmnkdTLnVI#hw5UZR&)wLso@5Bd=k68BA2N1?vmcRsK zev_shw=xwEA?zi?=2Rth4MASbq?b53{PAS2>5;Vc>t&OAIgkk}%FSVxJ(YQmpfeH)PZS1^w^-(LK7rq6RRJuDKFqG$Ssy=>{`_w>U@2k|CbcF$SB)5DlW)?+NLY|3E@lm2ayOKmT?f$nY1k?RO-5 z&_n#idgqIZ4{ZtJLz78|MN1GC5S1IeovGUkHfYL$a4n4ZxBmk)0!JTa0%1e1kBy)n zB_$ZkJG;7`>=|EshG=T0f%Er@eB0m`*FKb7h|SJKz@3!X!=QDfvMtuNQ%dJNC3y8wIz}WL93*amg1IP zgnq)DGv;eXiYqU%Uxvgr|hZmZZ@JgUinCslgeU z_D+rPs%LbiS~*ZxVXkTB@5^4f}$xNSRd^V?Bbr$au7GjadXRJB{Kocn@ za*}}OShT1m>C|-zvK3-nzI-->XM0@L`TD3!O$|FuA2W!r^z&%v_+aXF<9;=pDm)yi zw3~y+q1l|2#$w=-O>`Sm^rZ>aCNDj$o@foy5O!lrF9I6fO0T0F|5e1WDx}MURk7jd ze4_qsQ$BYp9Xyz@UPZSh&}OtE!fJ@WuDBbFt&0R=!!L^oBZFW@L}4N+;%nL)s&GeGv1y2_uJ ziq|8ps*Q->l}MqRg(bThM9bI=;WS-_tktvbe+5UEa1+8RL}W)tLS#v;Q#z@|nw8`? zL?dWrE;XyIsUg#$9~a2n{*~lO>KUC3EokpegEz&VLjX~Wlf*1Xyj``Va%}yOn4nmc zvU-WcCgha>T%&JP0r8l9T6XAlKCKv)YF%KJ(|tDJs${lLY*7eGQh(8xzgmMXM=R*Hcx;$u17>1_T1vX zOmij*ECjUk7R3K?+Z?kMjlH!!)UsbmU1(+rpn%~6$jo3{phb%eYovbj+H)m9OVxk1 zEy2USh^N{X{jYX!3etYOj3WLzkcnXaRRP}fOzS8NF}|NBa*|E~L+|>Wh=B!7ufzz$NtNv8lZiK`UVbUv)vFmqjNec7SmuDd8xE&nFk92jA*;AS%jo_Q6zFg$xbdFdkfpp zZQg~jb3tV2ww+8y2Wv@u7c2^8yM3EOVU@X9r{n+9UqMWUS;&5uOS=+3f=7;R+lUJWnc= zmzuEGgLaduJUYQej=rsxD?gXx)C$VX;kk-}9Da>hflxERLTp0o3THYw0^Z%|_qm!< zln%Qum4Bb*W3&`8sC29;A$ib^`})GAJO}*=Ihiq1dgr&vn!V{G0k2YZ7}Kx}8~ZY+ z2;KW~t174anyAq|HMa2L`dciFEa=AhH??8M*Bg*|SP0^aPU2rQ)yV%`YRYv3IFBnvR?czgxR}sitTCJR+eF|I!IdXdghb}i!c($jR^xxW zQ`7@bCWiLGq~rlWfgiddf}H`^jRpj<1sIh%J8l8-`9zo&eW$QVFP8jwp`seel3C@h zrWQIx`zBy0amcrxH9-Dyh| zOBJVIJ_c|w)_j*A*>6Bw?(qX;A||G#q>4|IxKlx=aks9Mg)9el#KGLgVxRxFLIp2b z6Rvoj4ofnO)kKaDdNALa{S&x>KNikxYMoxcHA29*&7Qqny(c_wk*6LG4cfllj9Bxh zSG;e0!Vn78c?!yo%GbRqdNs>Atc$w%`^(!9c_DNdhC`8*3 z>C*##@-^V=1Ww0jyR|-sajMh+nIN7bl$K0r=+YR;wsv)=e1CwV3;ZY7JW@N>(I#b36Zw1F9u)0 zI$p9z8&&d*9YM$Jm|OP>rbSERN2cQI*bhl_iJ;+6^tBL%cer8W5)XXf=* zvq9oahoTvn$bJEy7q!I3n8&S-^mzK?^D|mdtZ9Fg2aCZKG%+a1@s3V*1l^%+sGxMd zYn5!C@xt^W&e@#%ZeEg)ZoGZBLMsC11Z4Dn8$FiBh zczgB)!oKhJRc(e+1Btt4%T_UEumk1r#LglB>qAd8_uLv4)p4809(>1-@iiPTDJSlC z?xo#Kcb)#&@0k6pEA2z2PI?$ejcOjl)ClvH>-iP*wM%KiUJ98kI3F*T&p_DdG|oY} zZl%5*P<{~t4cMqaiDT&#zwzY{&6eWiDE+)3$@wkheZjV|`^?m+I(@S-`B_-XvMV#KDgNVQylgk!I0b)w zq?e!YgC=?MoI(q*-ymSDoe)XJ;>0=5RIam$SfZ^h<*uxdODo)zRb*nN0MRH*Usq{w zl3d(NzQ`%h3ysPn;=mI`)69Fxfk#CmpY*$$zqNTC{Ngc(XesGeo(l(_cHZdI55d%u zPtX6_?7hSwJT5eJCUBlKC!Q=ecDQ(oPQXPTj1!O6HlyTLpqK}|i}2INp-6FY?$s}- zGOc08x?NvSaeqaK!Z+CG|U5!|s-k6$g|j>PX;*w4mbw7i%T z|4?Kc*EV#ohc!8JmOw4`tS*b;q6<=rnfJhn2ZfoSQ<`uz{|D4Zeu&~8IGt*k(bh{7 z%LTkK@$N%LXQ7n1 zdfHID-Zfgxjlcq*?A2hl_jU|VX0@d63LG;Ni#}X=CsEq>!|`tDd`K!g`%hdG*x9pO zl@9v3tN586MJ8>_Y-z)fLsbJcH|+2I=|2o;m8q(!&e|&L-O@5H_^W>j9$MDB9Jk0Z-kf2X|LVW=Z^&AV5%^Z%%F zxLk@39&6c_VVd)=4IxBT1r{aEG06E?MyoO5vWS>EaH)g@J&z?mmEXe7H}tV~`+S_m zcATG(=M>s1aGQeQ)a42~hUwJ3Cl~s7p3^KjE#DH5KbJphtE;tQX0s7GIm(2&^G3k* z48sZ2#d~%_lB7%;#!!O?Lw8~t<0OpL5wQA^4~&Va%6f)UBwth_GiHx!Ju1@I669a? zk*qxq(Ap`BBkcR9RkA=d3E*nP-L=Rx;z2QZQ`KOeRX(=nEm?KsVsE`2-8JNbdq zMDJCp;Lf18kN^9ooEpsz$$(vwxEsknr+=*RgWDhpL0ZN$;Vh}96-iuMDEV`+2598Z z@=tE|Scl`pjXuSyEJhoQyQ62UtJg(jMGKi7Q#jcRQV^R2?eayeS6LU5EFaCplX@t0 zM9mkMf04=8%|umY(Uid&L@1X{ zHdtd^u*#E;)f;J3!XpOUh1`xumWaw=18F(?>Bwbig|$Jm4X3( z%N=8Zohkogyk2u+?<*~yt##HP`3zOPElDvk6slWGgRBbrMH)7SigtVK_@ld znl2o_Wspvva_bQA?(d7j@v})E?39aaH@>_loQ_sc9HiavgYYm@rJmqb~(i*s zzq$-8wq4w9Z#cLnpcQ2KCan)**9FQZy>8J)~rfruZNgQ`22c zp71L-;B~45dXB)e79zIsC%;-)M@I7_q;2?Gsh~i7sAaVv7y{mFsb1!V)>17dpY-7! zwW2u^wG{#uHhA0MKVvj&6tr2L=X;OKzLG5;GRRW)KA*W|N+~wR}VS ziIRh{P8_2Y4V&%HhpQ{N7|6=u$rp%=HrPRa!Mtg7x*_DhCf7iQQVb42j}{3penJ1L zsvpb&wqbX+|COSeZlu9L`4}E=xrXe_iiFWdw2XwbpW!Yo`e!JWU`cSK)W%V-gw!%$ zkCyaOsH5I*%w9--J85phl~bx1Wz?sIRz~F59whJzYT{H@$Q(5}TV4eWyz@d8+S&96 zEpd%8lpSeR0j7YI8Rk&5cn{xf4X?FY{EDdoJ141;fIRVdJqnor?YPZ@!85>;*2GNq zqB4=%cTY6TbyGUTCrxMX$-1)7HylZyxfFz`7CxP%PMo8vgsBW)bk9>-Q4*H)BWk!c z5c-ghZ_{4j)qUiMHD!~2RB!WFNN0AdKAJ3T)25uf{VIu>A}gB+TPq*;H8i&hou+5- z{5j@yTv-n3X^&yfk!ZQ-8XaqPd-DYr z89A>vQSZwwTVpAyexj21;^5S4RTK9J|7SIu^7$M_x>ugnoO*7*yH4~q6k&ptOa1WC zSB4+fjVZFj{FZ`Kg{Y*et8Lrqe#4%0B}4tI1)!N5drnYm*JcKSSg?*Is~$UV4`kIc zW~U%tJX79zVu<$fx%QmGGI$ghKetf$=Zeh#m$ql*&Jpne=33#7mE|fqd4pf&oDN! zp#RFy99Q^Vw3f9cEpX=5oX{IX&9+#Xe+$aO+!V6hl(Min7DiCZwCoRp9v_RHzN6T| z{))n|msqyD`VEec(m6BW)Rb{aZ*= zixnN`xyPTSiTa?DccFqgreK8!{TRI5kh-h;ZK$MixLXSY_q?e_ppaHS4u}Y+cEFMk zg9{8FRW30#8}j7h$J7YGyypo(wHiFnb`6^I(TU&y3MQRQRGB*q;~##Cn=DB2(q)6~ zu@~mY!hrRG%Cjg_P15Hy_0o?03r6OH(hJ0#Pmp0%w)ujr#9XXE%lPsyNTS>w0$;B`>_R_|)$hF6GP%`sHoPi< zMR}YfP!rr4opz()`0Kxbe$gl}h@AnExZ9Jg`qN!c%ekNKi+=G}4~8Vyiz%PpJ8Tsb zv2AH%_$3EHUXmyt3mQ*et0*2L+HBsUC>{{@@Sd6|v1G&u1yPpUNAYC0^X>Xm$$cNk z??8hpTxl^B7LZhcE@g@(5U|AF2jKy@m|G4Hj)$?Djo|2P+p8J6?j%iXR{{1iFs zV2H&|N)zuRF~ptrw%v|8md_AU$=0wZ&MnIMLMH&lUHtiG8J?4%LY|h;?bb`Y6 z0(t}wIFkUvX=TJw{?e!CXUQo>ajHz=$}IYGWFm>79kqQ3aaTBT34_ePt=dCFAd{LS zX?gZ6p0WDF!?eXzxUBtS!uy8 zIa~Lgr-%*g&Y{((C|((LS5A?3QGspFfb|lu4QY#OFjQw}ag%NmzAltK`B=o^W66F= zW~Z-4{C^#|VwM)4dHrWKpM9bW4T}FiG@WH!RNedaMM^@Dp=&@whL)1<4uPQ?MM6$@o8YoR5^%&tnll zxj;GWE)?p+?l<3BOFZYM%h?D;I2ZHKd!ALBk{`ZuKeed(&^F>WCs1e&b>(?7NuEUg z)OYR>Uv1;d-%NFYA=7skyeMHpKhBY34QxrN1VtN-(%9bcWZ9L| zaja#=gHpgOCsVcFXBxfR)z9-a-pye%ZJN6KU77tfpj1)>z~!o+{}up$Swz36>;|nA z>4(hvNp>XC9rFC259{B{+SvD>4+~?7HhqKZqe=%pUL>do{}uglKs}rN#P$i!ouHf-6&oVg2@X z76m)g>JvooA6?<9*a!22-4i1VO<0Px8D6yC5uk%vx&NHmh>A5u{~PKy6EfOhfRC04 z5jhkaKh2fTy|wYYG&Sd&vE2pv=SMmeSA$AnGt11{G4$-wcsey(P@ExU z+e0aq)HmzoTBkUWFlyf~1&@S~6>mhG6{5hoCjK~r8@-Y;AVOE=hrtNzm1_d`$cLB1 zY+~PGHxZIuIMw%Uj1Sz@QPs&dKp>X<${IgElf;$=B31aALHum_6C!n0Q?c?uj050vO_sE0^seQdEtg?gRx@a;yKxSY=e-9+)VoX$CkX z*g86;^p=<#(8>INZ#Hsv?yh#@XpauowLVdC`jojqu(II}{efom@F~!TdTMd=*Jqm; zWy(n{<;UC8>OM27GASZco|iQeEx(;c1+s4Yj{y0J@#>KKcuv08kyrTfio|Sk3BvY0 z<*r0eY)IX2b1Sltef3+|mLQQ#BnzF6!@2lrrH=VXv>UTCzN~xaPiD7Rg;m9%qU4;I zr{NVLZ-0LHmR<6wuodv3Py6>};EU5Ir*kCFo5w$l877SeBQ8y3AO4jqos-R1a1=5a|QtV~O`ZIoZT$|kI z$UBu!lYG|EDiKaRV82*{xoBM;uC9ntn6^|t9(ePPu5pTPf2pSlHAc)jtk zX-FFWd0Wi$v1ILbPU3jrm_QjTyYWqI7qlYS(ZBm>IJq~XrN@!IeoDFWAsD9o=ko$} zUYx)PwP+DZ(C%daU5BV!4AIxsNT;8y^(^@pX=f`B>$PP zwxv@nY+&A(!Ep%kxWa$Ct~i@IOSuXWpsj)Knf-`dY96bK(i zdJNU4J;P8IF}saN1;h3`9=Tp5vHS2$3C#ZI#!?7nz@uZPyoz6x2Yfa&s((|UcD1zvA#0jeW6R;@zxs7olFws;Ic_}aMTusN&zMH#z>uQ~ z6f`Y&;!6p_&%;g*I}DSHTs2W8Ei_yd>-oVk;(U)rG>Lq1qc~*aI+FXy;l2(+T+DD8 zCOI=kk4nX;Gg@S}r=V^4CN7m3e6*&$1=)K~yd#{lRsTy>g z)?P?ojcOq*AS%Daz)(jl7(S||(&ehz!1jMD^U8UUBxGj3O6x!kAt^ZUbyR#=h4`)X zuYH!4i;PFkllkcfO@$SZqY3)@*Ob4q)bRRB1>T_z;&nh4`D-q9mp^FVoFv@LSOe~f z{Oe+B($Sb@&PoroTmp+s464^o`Fw0sh>BaFy1(8l=Z`n+#%P4=`40(D)8a8~GD<#3Pu}i+(d9?u1>m5;X zu|=A~P-9#a6Eeelh6ThxJA&&HxaPb5N?@ie_4i*~>HHU!`==TG7$w>(o*}u7`|uU` zw*d>GwjhPuM?G#1hFg*WwgGZWhZR2ogtK_I+xC;1G3B#j%DY|rNtbEq1i_6J{(Yz0 zgZB&phdRz=B>h~D*y^3T;9Sai?p@?(}3C!!l9TmIpy?moRJ%E0A){~^)mGx$TF49 zzsx5j12B~<3`eogM}B-aXS5;lkI{Qq3ui5!G-&|4r?I{@A%mVzO!fs?nbBvB2DG9M zgR0acg1?Q-#gAY{YwJAqa$CWBykbaNhup=v+>9uSTxa(ZD5-!vp8Py6D~TAx9PNw_ z#o-u1B*+$_|1-52c=#54A8j3vsuQC}Jj;R>!q-!fQAV)&vVoCQO68F;$$O|p^rKK7 zGP%ATT@pT!M)m!QrkR8@uVSIdy$$P2nc$!_#3xW*EcBlXTeEjK;gb~+cNETjmaio1 zJ)Li?%-O)!8}*+HTeacaJ$_*5{^Bi0OBXK4r~MW+3=C8p6Gd_=dkZ+d#(!A&w#tWU z3PNG78yKV|9rNhJ^5GaKKJIkL7*^)C68KiGXmYc}Zngu1h1wa880n{Q-Ih-z`r4m; z;8wH-wK9UrGK?=Fw7X6&dUxpR6)|RKOSr=eJLid zHRt0>0S@KAD}sw6zl+9s57e4bs|~7TI)oa-E=;K7Q`H&KxY`f)W$u9t${SVg7>zeZ zr&FZbd8W04rY2OiJaSnv?wQ}NllVCDaw1gt_mSt_=N)7El?o1N1UJO-P2=|(-y1=& z^y;Z?EsY@-T5X)Z?O4pFc!FTc!ppyE(fkc3a1eovd1hr#Z9)2Nq8xko4*N-f zR5wLd`?^t8Z-BK1oFL3s4%IgX(&RMipzY76 zrM#0VVj=7({HvC4+hjl}b(OKYw@P887O&z3bK&7{GqM4HFLoSiZRwG=sYWV-Nf-ur zN)0KXh%tSB;=VUe{mG2Bzuu#xVuRJ?weAD%&ETXum84gYXouMv16B{MJ!3nc>49XP z0lt@7Prf6-{|0^vbtuWR6O_15zTa64N=iMwcFBl_>t>ABczed*Q-g23*2AMsU4+Vf zvup1Rsdew=%~*@Yf((>0D6{WP;<66#6LM~WV3C$%L-|q#)L?uDIu6kM%pMH$_rN4l zww`;GrA{K}i~OYz1mFOH&q3fAE4yD1L;do-ZF>%LTE-YId$Le$Cih}|sd)1n%SZ64 zKqs&ccMF+h>*~tKnpj_!2y;PePPt|eU1YdI>G#<#RzitNn&k-RjT=0E3M`-_LfKd{ z9upHv%MPpcZ7)k0erG` zDftSoQ#AVzsj%@cb#B_hdUb$QHjAf;<7sbk$EJ@iBYV)JH?gF?--}Sm$$PYqI2V<@ zpRHQ`#>sj%A`odLvLtMzLHFE3iU|2c&1)#iYrDT?^M00euqPx*J(0hlsovgjWZHe| z|Aq@{?i3CG7W_2BY3YP-CflocL5J6JKeKf)$b?-t>Dr~s87NK)c837dJ<38y?A-gI z!x4fvp{kEZ%hf(cAnHN1?#D?ocfQ@~7TZ;t!T-TLwU^LKX$SXNDgWU}4CQ^4ykcvt z&o|zfA6Z9Uv=(x3-*Ula67pZm1^>bQ{+Yt2rKDKAa=XbZ^kS=@Fl-znIM|*~5jukQnLX_#ZopU=iGEqDz zCcSB?2%d%&hlT(6bLB4ezJ^qi57rWPN(ig{&W~ zd6~9xtMHdB7repB=m}-kj*0+_6E2e4VbXjEYX%2)2&Gejc0-Bluk;lIiFjE34 z?eEL-iNZXB^q;zDoW9R-EXjKW=1NX4#an?D#*=1yPhP|L8O>`zt`u5R=3uY&StGsW zBM1(+)Q=Nd?T1o7)nRT?gFL-K`0+tcd`B>Q{~qQI*GA9L>Zq}gJ)TZ|X_&vjd>vlf ztZveX+1l6xEYNc9Z6MetaRbLb9EQ?TDM!a>9@NOkZcskXZA>(U<{ldnuMtc5l&f*v zAH^KH9NicK>d~4AxZiRib?nhdNElW7yaerfa)-F!TjMaSD@9w(JKf5AHj)G;uBK~g2;clB8^TPH*7UQzjj*MXh9nU%^#~a0J33Fq^wUnh z$}ZUq?Im&1h?J*z_AxYjEq6V8k%O0s{NY4ydepEj<*zsEA!GEeWM|Cy?3nAiV*hWJ z`a)XVJ-RnMMoUOphK?>r(XI zUJa+Id3qwWRpH0&Kc@o>JDei_>SfqQocPtHQ>hTLVacUSst{@cL+vy>;$Zr_giB3a#Q8L!&DvA;j$Px?vdNPoZWMWyQ8q zpPAkp5fbaSQZM_=wS}M0^*WLKFcPEVSnR3cYWqx){Vp{qRvz@08!~d>n>JYyk%PfW z5)y>_6cf2lo;cnD{Ty0Nf;W_9+T71z4&Ro}aLU!Ul_wpJnA@Afj(9%3NZ`=(XHrSe z&d#bNaefv#P|!i=YMb~fQIt`%G1$TGf~3xNncsqW{r^DGOIc4e>Go9S7du`z~X^6XXSiRMj@1 zQN?1uQ}exU-;XSNt7q2NM&ookA-;t7b3_q~aF0prpd{44HiQHM7Y9mwpW z3U6Sh?r^-oW)n2hHylxa3ssDH0pzJys7-O zMJ8^9nAibGR8<4jC@6Uxul;{A{yZ*iJoXePHA|rQ;qH!vIAwLdfYtDrBGW;Y!)~jM z%_~^qVeaoAuvQYVKm+1ZL(-LL$;oo~Bp5e3SK_hpea}Ql6~%yzYjC=XJe7Y6xkBqg z@t6Bng#oVKR{`uAM=80=C7`jC#s5~^0S{JF<<}n_IB)pzlhQ485>9V>AJ|Op1cP)+ zN70;dLb6L70j^|?V{S*r5@P(j@JOQh!3Xi|jOv1^^l$JeKfW2e*8HyVfBg-G;0gpO z*%5~>Y{!X`;1G-4{KE6$P3o85JDB@>L~sNl+3}V3wO^zj13Wi5uEPfJero0QG?W~D z&Jbhxu;dj%&Q8c>mf1f^UYDW;v83N0up4rG{`|Ao89E^7!Y^j~CaZpaAZ{ItE6hDW2lg~n77g&qW)bYni4!7$ZR~}SR212 z-`ASHY1a2xg>KW@4c%3z;3P3FcNY0BK(lIc^Ta<1;5hwwjP@QPUp@smwC5mIs>NEl z&|FueNC)I-ci#(~l2?Aksg*<9FO8Sus7gK^Pr=SJzQ$=(|9u|xh>+&jr+E0#0F51f z#6NaHEDYnxwJ50`X!ANGNeDGRt_%E3d}ND1rf<^cCEQa2P~)58UjK@e&5iqX^72>f z5xMlX^IbZmM6>}NfnNy(7gjxXz8r|0YI|wYv2OgJSa&WW$M5_dc!L@V>ctVkt5l@CV94Z3qo9Uaz#95{Sd4Dc4!pG)Pj z-d5892ZE-T5F#qS!RxZ&3gRtSgf(F^GF^y>Wlv*TGCkb9NETQb*&5j zu2w;7x>R?I>sPwUtG-*3Xx>it5TA6sx1WAD+f1jPlB6b@f)?4O-2}`yI1IQWl9*D8 z4CK&K1l5o1ynzI}@+q`gYqsbomSyR~mKOou&rR);vxVi`p|RW?{T|!}ZpV?oXBQf( zI>e%jijaMo{o29%cG*Q;hkG~PS_c~fU{TVF;JJ%#*TcBC2KR4U7Pg$sVC@34)~iA~ z(G}{)!U(2ia#lgOFjJ~L4Du>4URNPEJQ z1W@3rArv1k-tDIh&Yg_DEngb(tRF%4I$HihHeBsNZ?>?XMbn_f&)%=6 z4U>l+0)n&yC191%ED{bH>Nr%$4x1$DAMLn~yu8yv9&$r2BVG9`YSf0qm($_;d^N#; zDL4~kx#dOXw9m{KiX6B^zZ6p@Y6i+THN5%cG%7S{8xuMgl>)UpaSt1m&Hd+xoS*Zs z7MGry+lF2FtO~0w?A^FmdV6~*`E1(od1)|~klBb)vj^EEa10l`B*T`4%=4w+Xc004 z9m$UFi%RUc`}w}!Dd=i?=S(E?HM_XjZIuNyi~3T(C>3^(ru}Efp6)MNMM$mld93$I zSdU}eT0<-gMJiLGh{{fgo- zRQFYFO?QfLz6!GBwybl%6Opg?-ncV&MtMkFI!>lT^fwAl_$7lN50fI3ak}m97R4vF zDE9_U|K!AjY(cq$$kr(6OHl)-C2^(dk0*uKPgng`uwDgFMw@ZAKPP~H-GKsGGv9=$ zU)FrxhabhjRmUZE^l5b@K%?HCBxn(d(C-t=*s^OKPr^UmP<>9VOQk( z9p|7_x2rxRKq%%9v;XSW)+QN!aV1>H@ik@p6L)M?ZjPe2^5$%9=Fd~CHGxZ(aE|lA z#mXruO-E-LT4=8+tMNgpw*Q}|$NWtsKThpv_kMCq9S#?2pT=_IJe5%81T2^r<<4lV zK=!&)&%9(vU)8kZqZ7Mdx;ST+`PpKeIKkf92M`UdHJj6Nzm3I_6)couD$~UeAhkoq zp~8N@h?Q)h?Ws|er{M4IL@r1%?6SIN8vFBTtp}zy zz6+;ldHt`4Q`t0Qgc@p+0H#9kgOn}#o6uK(d<2U;*ClJUSz%I2<;nv_?wGOXW;ZL| zs)m`CumWyy3Uc*5$5CC%cB|Kgqu2`@{JVS|VaP~pY2g=~EhP5A8P7=I+P&dFk<>yB zdbSJK;22TIm^Q6l1eH!s1gqM<<-6}SFuw0K==9#;eBQR#Z~ieEpez3V3hPu6@8Hp5 z;JrLuJ?(b>$)+N&#-h#JeHN!#&ygj#!_je#4rDibw9Q`c$KFr?dl=z2C$JMXGg84} z`K%wCe;OK2-gO>{MK2uCYtk_sqZ*?G?*dhN#wfgCAnhnZW&Ry@h#FRk3f+r9eTm-M za3^{NzdyM~iVnsBW@9O3zL3)f&$n%7gW_H5bUFH6ggWG_j2!;n1FvfYybL8!Kl0kh z?;D*dYUBkbLC5YF{ohnLd&ee*DETP9=R}uncf_-%XK)2oeI@H=)Om`LUkzo^JJ4{T zG9jsOElk?u!wsBN7A8-rche!YjoNsfneP2?rxuhi%R3~464h(GHey;L`GrI5UNlP+2hebvte`>Tf%C#EVDXvQ!S2i`fSTSF- z4iVypJ{6Qj+}0v$2dyomx`G4k(h#tUeolo6ZL{d3}YE3To1j<^o$px)V}WYuN%x3=&&X(oII zM99*Y)3JdCcL-WCd`JFWsr`qJtK&HLlj5lorTyg-p}g(5X$fj&->to!8qFw;Sdlq! z3r#i9jt?ipyYAdXU~4lx?0xEG%WG)B5H@8~V~c-sT_Zdim*%;AW$w%#PuZ1v(_=^Q zqbIf$2;Dsk)QZxzV%I z$x<^{=UMb?Y_y>~pY8`=Y&qB7f6|}Us2Bm6$ibyluW)qq*Wa+8`3%HN93PB3(Y&>d z;XuTOmt&T|4e#iW)4h0~-3y-88Ksh(M$PJl{Y4phH=P0En9IW_9k%>w_bkUqrPSj1 z4wu;qCU3p8dSeN;iD-m#fVbW!(Hh&o&oQ~H8E(q%o6r_&Hg_*ERd83nE|2I7j7@$03qH*@(049LhI@|NsJNHqV#eAI<40A~)){(> z4zFS2zZIGYw~Zu0N;cWD7{hlzq)Li8ka~g3%0USBu5q(<6`zqsS!`02h+i5Xj5zdeZiRCp zTdgQ7RG$V5N}NPQw|A4pq_JA~$`w?;50ULys#oE1Lv4?$yh!S^tr3(@_2H76ef29W zr}8bZ|3za=0V_M=z=GHrW;l{__R%wi0mqdwLAd>Hw8(u_Yu6OQts3$8_}U#V*Y}z| zkNcZdRVXD=cxTc z2&Pe8#kr5D6w6khN-rqt4H9?N>rdhIeEahewRf?$WMPYwK|9G_>U(miL5G z407@@=28G#AB^36BBBj_wUB70GE_e6T&yZ zQWsFdCy{d#seF$&U-0#^0lWG=d8)1bs9F&kyi>4?TfTD6P0(Av>Z8!ml!S3;*~znw zFEct=h=Ms2=G+Uto2#to6t);42p#1)`#=ld=GEhd_*TiNi7`jJ3&za2z;27pC%MRR zQ)2jbrha-(`qT`me~Jsry=G^Fb_bZXQ38g_<=qGBTu2TCO@4Qthgq+i@(?z$ySb74|_Aq+{axS;WX0CLEo4bkv-9_qbE-#pGrh;5!sgoB->sZimm!m|rZBnXAQXj$<*E&uzVoHaJOGRpqx7FoC{PkR*TDYR* zOTP&#Qayn*iV}prx(k$e3s3yBPs(dSP3%~FZAyV3dhef?N?PYJTouSBq;gp*=_q^4 ziqpsc_RD>n-mI_k>yS4M9(Pd&^4fJWeKFDMhX`EV%b=auAvOZbCgnT z4*{%cMp|x~ z@>*s^LTIw@iTdjkL?Q$+bQ6j&V-1@VBOY|Q7X(C6$4jP7_oO<}RJSLY<@B-Yvx?)S z2P@x`isxaN7o#Av zcTZbKo?wiRc)dCo5!o82++-9D1;kn8(kAM36upB1t0ls!vo>N~j075^+lKbs!P3q2 z2-W)*t(N=d@f0Z1QI^mNm)&-nQx!gMXT&wKCsfAv+|Y;*gBQe8<9ZrgDwUU8Xl9u3 zW?lbPA@2-KsutOuL0)l{$?*g1CJjgFdDRjZuG1>f;R+I7bUTcn#$OGSc@In)^}NuT z34e*{{X~N4*n^#~iXN*4DCxGP;&2E-qyczMrt%|(&O%{C`ciNg+SQXqKg^ULsWb_W za$CxIRc1VKcb%DCaNr2fviyN`5uY5a>1(=-(2q{(3t39E$xDb1EIbWGi>WLB(~+Qh zwo2fJqFv39#~JRmeSI{ciUsXKSzppC_sX{QFET(^Tz`UGF$*nzYDJq0Z6_8kfNJH& z#F@~aYfYZ3(e&7v*WR*1g%b05g-zDmLEm0ynPIN zrfRqv%)9tydTSS1|MQMD+FW(D7t*D{_-dcC_HvqgEmcN@v$#Hu><-G$lVpwA(tm9g zjg#*9PUHN0g3`IEvw*s};UhPOE&b4%@G+pC=KRiRoIv(iAw5Ng-GQ_9e(zpKN<;I3 zf7ST+cihH$4?c{MJA0Ua;<v|RGQJbUL6cLI6`j}~PBs|3oIqTZK8qx81dPBXy(P@& zO!wkVT0TZebC*jMY&Y}ksOrizy-=+u;Glv3HeZK=jcfT9B20!f{rbUIu?MH2GM3=v zr6DMgirfme@*Yg;Rk84T#d;Hc(+w5pyrgvytdc5S%kp|G3<N@1IQhU; zSk-0{hUQW{Qx@bps#|4~{ca7aP5oJE6R@d1{8>Xmu$Qs(cZxf}{i?jOlIoqre+|@WgcLi@-4sIK0I0v!XFpC;YxU4 zH^_fpH3+lcXCOiXbD3(cuW(~~!$&;z0zyKgYG^(&dGE-C|NCgLTqJuEb)a_NEvod3 z`R7M2f%IjR%nRw>!@)g~>7aX4ZC|Q-i5?2 z#pEf>nO>Ged`5x)f;)G6jip+8=$+v5k@>~$19B$F?7eVelN7Oi%|!?;$B z71i9_TFzPl$MQXwoHO3+cEvExj*e1dxYNyk=?YE%s&kn_m1oZcslHZjcUzr_H`|d+ z5?N)ELFFWSZfZSYbi3Y>c5-DE51O_NQU=tQ9dk_x^Pf|)kzU+$+M4<=f|64p;N$KP zi|5?xuglMpYpM)@9ZY)8viPMuqGQh3!Q%{DFUC~(am5}FC?85+PI>ANU)2m+cvHJ{ zIf^}LL7ljt)8LjGsexF5>|4Zaq(fMiQG&PTj`w%n!1F~V_Be@6{ppW((S@HXmks+H$7vy7}sa`E5t1uS;$1N*;50lb@Q z&3{SCN zH;dgVe}z^xNUz40h5q?8e+_*oHmc#Av9xkLwbHo|9Vm7@l0zC$&4SGd{@3 zxd}@y*SHUfO2ZsqGct-V4W5i~r_C=;!vwSf(ZwN@%E4Y5zqRzk7d0hVHYLZpcy!Y@ z?FpH&{-onM+<%zTIUEQ%9s*J6y7yn8R<})3l+SnlL8TbxV_)YG$=0&i1~2&dA}k&x z{0EMj3&JeE`U=^MogtEnG)6h`S_Ma==6vPOs4nvre?9-JDuYln(FMm!POG~UFlZ0J zcJ3AM@*8!y)kT4&2^<(-f*nwg{!qLoWnj%^_C)dz8&HkQtkT}$8>Ab8N`QAS-eD+6 z`?Mndr$+B}-Q49nGLAV(4PK+CEBZ-emfRFlO>ndNw#qI!o(p>Hod~$=hhsnOf%3SM ziJU+qM(q~~6Y|rzsWQLZ1ZpAnW~9^>(;D1Vw|tuXiQPrH&X>`)X6%CnX%Ek&;s zwo;?r2Q1$kyuocJpB9M^KI~T|K&%<^tC23PY~w^7SCWbOtCmJ;anLY{S?)^&!3Jh5 zR_Ar#t(3TP$m3IXe&K=`&?Fn@Tc77IyQlsPrz{nDpZ2N(1R6S#UdFw7>o$85ls?*p zx|;8el~k=!+4nT)8AIu(bff2GwEMJI;PMIsiuLYu8B@!apK!S=d44#);r32Hi6Hi7 zkka^*ZZcnFMe#^hk|WpDmbk2NU&9{Crp zkA(bLQvur0x4qw4o|8|FGnOwUI`B0VoP2rYR(Q*#8^glE{)$x0?H2=xO+uqRQS+4f zBZsYGF4G1FMNTo%H;U&bMZ(TVt@pHZqvNf0$u6p$ntdlX3EUHy5cPo$C4pyc+|!nc zt4f^%{R7=XmvJ2%hB_RJ5qfPr?)Q&`lrl&Qnj!#Z{`u%-{Cf<~%9`e%@9)rlf4(=s zx-Jv&-;a2Gf6|($bmLE)CI@iZ5%#MWC|jpd85Uk8wQ;-7btxPFGwzp90p4lfP|ohx zXWpgCxb_)VXO8%CzI8vcz5ykpusj_-(c&gIZ9 zfmF#C+gj3X(zf!hFX|$aA9r(pMeioQeHk`4BgPg@o(W)3vU_`+Y8<(2iAP_Z775I$zigPms&{M+pTLu7c!20l<9GFJ}^l&Dhi{J86m2lifqUUcvtApT|GY3z%!qjh7P5gQw1{@*-S_YTvV{qpGryr;Y4V2T+-hKKo$#Sm|; z&W)pqSeCzRxzyS*?K5SAj!P}WdU8@og~bw?a)FXBa#xFDu?j~SGZ_eQlDTsVhwVW{ zovf=~eS>klMY)wDsajw{>*`>A-SjI;HDy=|%!WqvGSK0N;PkE!gi655q>gVldCgW2i$lAv z5udc%>zypTJaJ9c&A||xjG`>jB+zDjhC1#PypB7tFWLFzW=zttv{_i`&ghQ1g9L8v z1Lb;II!ay|VT8lis_Nv?#Ttx)TOU|#OzNW$q540dF@`||mc+Y+5*z|c2C?HriQf-Z zf(iP*JE*vqxd39fY}n8e31sWpV`^V82|AHcDan&B-03KuaziyB8Fp-r^L{|W&ByPN;#R>dS9VPcn^W0aW!} z8n=w#I~=x`6w`@V1Sy46y2s6pT7)IfM8K_Pw6=T`Xdr5K8QFx<5qMa9P1R2D!%mRK zp-KYgch2krr3$)xOw~3_1BemmHuOP?@aNioEOyB8_3V281A&9W4Dzr8hz^&0XiT>Q zX)cC=9Xj6H(ZO)o2PxFntoN2ifpI_zqllk8>8RK)toT(efO%q7r0C5ko}MhEG<8}6 z{!8RC5SOc1`D-Gzoe!eyaDM!=?lSAkFt=OM1&V2Nc)-FFkBwO7Sjimox5Mq&ujahqUOTQ@PhDB^EAuwGX4l2iFM+cO=2On*$VA1SM-vUWW?d9miBFy zp=iKI?`iw~!`UUVYuZtcPqRyFOn#=eN6i-ZcvO+*_>MeoO6RslN{Ujt8hpM&vXm>} zlA=43s%pNKnaT=8D|eK!Bre+}(pEY-rfllLiKI{}LA!(WDLf~2I-a{)cQ@tzT|J(j zSP4QmV$(NYIGFx!z-aB1+r)ZV8K^!P{b8sMwxgP7C|9!o_QAR6$Te|BfjeB2h463} zVNk0&p;tze6SXeyy9U)dQz+#Y*cJjHPxmcORRW(37EAsyHK3J5Nr_80`7nA^#E|R2 zaVd4|Y5rjUfuOfxptLM*R-{MRV55h}s%x>`1oUw&Hg&6!WfF!{FWgRBoXy>CV>c|B zSK^tQW)+cK)QS$Yr6_&DzMfFZrS;J7Eb_xRE{UpOL6o(&}*dexBxc1d~vaLnG+9ax+TU4~&7{+(n z+b&wDRFOjP9H}OMqt5u1hmME0@zoJGeaQ@|gcie`@C2&WexBSVjO$3|c#n$^tJW1V zCVuw1Mgi#~m42X!6K@p^WSL9#uLq?qsaRxTO zu2`g`r($~>!))`JcDld15@f!Wnogt!w<%!1EE*Xiu!QJ&GfSv`Jv1?q^bK1Z;Y8B& zRr|t^8-4QGU{ZP~gc`8}>cmp&szkn1VGTZa{f)b_J_kgx`h?nd8~_{4*j`=QYwiR* zvf=G%wZ@myf6L`bnG>B~lrEZc9;QB@YYZ;wdtiZtAqW_l#pMf5GMNV-#V#raqqSJm za5OCUaCTnn>l#a6+pi5Ar3rnr9go=w)$(R)71S6ZsJNY_n_!3ciYHZysS;CP4u~*} z*gjbtc!a5I*}@#7fFh^5W=o>v17zjENdH9RryTvEF|AMg>YpUy^qh}Jzq$%$bd9!k zyt*L7cnJs|Hm@XiQU&Dr!*APp?h6bD{z?4u{uidW!G8k!@~eXXgxA=5Z4(xm+O_$K z2KT09FzG{nJt#%#OVZ2NKW$EelaTRxEyb^-Y>25ncP65v$AId2+%LUpH;;$Dy@y}P z5bZ2XvGR{jepa=;&l?hkpQ+sT&tSGl zF`b`fJK9+$M{&qZ*`K3(TEAOyK5f zYjC`%P#ivTxRQQtpB^Wd)H`#=sZeoRn3Gyg>E zV(4PH-*LSIxz=(&O90M^T|UHLG45l37fSDUeh{mwjRwJYsOUB*!oX8A4N!Zo+iuA$ zndGX--m~!1K9tDq{jZ!WL2Onpxp;3_I8XQ*kK@6*-Xt1f(LwNwxX3?Zbee3B!W|OD zfdeUHH`Xt1aK*E+>qS-&~o)Tns!GSqE?j88g$s>v|S|J)6quKe2oV|xU& z;UwGP>Z$C+w(B-;yuQ2PX_C1I#wLHsL*CTdHUCcrZn5)epj*cI1XGcluk;Ls|R zLxj+m%lQs1|Ijv{?ZP3~&|!Y^E{X&Uz~dTN3l0nWcpcz;o|Xey@l+gA_VMlldTjNv;s*W8GZZZz4 z!T(z1UbxZyEVnQx*%zbrv!zd*XCD$SM2(yE-FAuW-8%BS#STZjRcpO8`C}DU!1_xS z>*3f>@6$0M-&CiEFBX>EYKa(f%wWeawk$-zoPI1a?VZfG`_0+|dGOYoX6DNm*_wKX zAnUg$`zezh{06SImRiM@Pw+SehIQ=C{z4AAPQ%GpS`QNl2^ea;ZA(YDZP^JqI2igB z?K2|`Dw6~yd{ur4)c<|{9;1}Z1yB-M#cX`gcFrn8Z*W8JfUxr623`cPPrQ!! z`HMw-*`w!(DYY5d)-H1sXXv%E<9L|wfZ50YFbQe((m~~F&UQ{V^zF+sFOKb2fD95@LpNz*oHkA|p z!w*JyriC`Ja-!oGzCxe8@lDPly7sH;WmA#rqc{HphA@R)v!9Ht_+LduWXFTpuyUy> z2+@OR*?e`LEZ!&rezhJ;Qfk>)LU!bt8y$u0PdDo6$wSI_Y!Uzm;)ancWDJQYa$&}7 zRr;^e?T0P@PwZcoe`F_=UTrU$3CV?q6(Uw{GZwch%#7Cu=X`aW3Jx)l6y)`z$*<(H z5eNPhHPzQQ924#-*jro?WjT%FE>aExV+Gsn2WFT9GpX1x@I=77ufWmUfRv@fDl$@i z>qKo7z*HYyX2#T6_*bPkwmF3hG8-@$2uSZL+ow=}_$v9-var>Q4r^!YTor zL6^gfV%@q__pNW6Ke-_ml^iTqHQ@F#c(%SoarLgmL)?Fq)NG6Q@rKS*D%@oeF>7~R#mnyk&| zh?8c1UzYin^KckOn-p}eJR7?*dU*V)lw7iGkQ$sxj59aajgHUA5vcFAp5{)XSw7mv z=VRw$tRu0|+eHvl=%2i*zVeen$rF&~b+2ZM)$RFI9IlMq$08U? z{wN1jBioINQX*y`gi-Rz8yMarD0+XuX8@Lzn%SMXJ6i*aa^&nfl(-R!UOp zbN}pIa0|b;QK+5rw#iEVx9DS8zZNH3v<-dixh&hvclJNujcbN|W=lgX^ytaazU zuJbt0>m^Lax~O8EG!8CVy>*(epTqhlz(T>R9y%WvBk{3JAEp{NySiXn2l@Ou;dR00 z30kp~^*pY-*BrDMmcYH-qKLFMWC5e2AV_6%SU9yVw?~;YcY4#x@A3@75(g^;6!ycedt_8OE@v61Hc{`l4 zygeO$pDrfH&}XqqL**vG?LBW*c$y7j-EsNfenJww@`2?jLxv-KN00fTJm4I`LbHB8EH<=cSqk&%FI3`U&dIRFcr-0K4QsSd(H3p??ZTO7irmr$5Xh$NdOTgQ zExxZu1c|{Z^8T6>4X&)|yUp{vNIIYC2SgqJ)iSu;3U8eIu`hJm0lW&i?Cfh4BWRJ_)WI3nUG>w8f$S_<*aup$cula*Q4#ovE0%o zGvKqVa(16Dm6uSowB*b7zV<@8bvojoHLsvhYf34Zd`qg*)~r{eSvpY0yr7au*`2b- zXKDE|vOpw8GKbW&=p6a7a9?jePW_x)XnY9ODU#@4anS50nl<#i&o$QAGIIZ8u&u$_ zE&uKb=!{b%e)@d$-FoMnMqeB(NRz?(82yfvZ_=!40#h|=zuS8je|qh2#eBs2l8h{> zXd%9ao!61iDM^C*ZWJ>mR%gS3%csNY$EG-)CgA=36G6|cqVwdLUFy2Vrr>R}>|M6E z!x4rpwH}0Jy;Qh(!O~E1bi9#kO7-4qMd2L^H3h!48)pHZkDjy_^2VDz=YOzA{>d6Kd)G(-4nd zE6xI78_S++q8a&| z+u+(WL%l?c-GTMoE9lwQom1tuct!L)fJM)`VZpG@^+a07x{s{0z7`+2;>J$zG)ANQ z&y!MnxpAo{m5HzHSTu`Fp~JP^`PYVtIXzdeuc`oZ3~Y2@7)$&6db zZ_N76PDP3P|{-*}npoNF%rhP@5FuhG4zw?GV!Yv6sV(Scew)U2O z(kP+kf4I>jTCX~%i)xqru#668eIb&+TTfbDLSs)+7yzZE|j2h8s zLR5g2)SoYD!8(hl?^rsMBH- ziZgphW`;Q%o$95`mUM}fWjOT5ZFIlTtfrr4cDO`)-PJ4(`glraFA#(qY3%jP{cuf* zk_0R0C)0AMJ7}XAgR=jS4?&9RZkM<(*YyrP=kG|~@uTJhMCF^d2s#eNFJS8bg`O_74Bb0;Kt*e7_-Xu1G-mkq6>X(&brLB*g;VS7d^p|? zc*0YSPgAHv60#O>sd1H=NY59#xS}1D8Woc`nCiK>DSO_MK%YvikKeC%;G&T`_}&|= zy}Qcrw^EwB7TbpGPn;5E;T99C8?=8h)lQb8_~_X3miX)eCbG}zLnm^uz2qrk6Fidt zpIR0+o{!9!6UB%avF!6-y$B@Mef~g?Xpkb_;Vo&#szRBnc4uGmyH!LQA4wIhxk06w zyzEb{3skihfw#`!C1e*KUPKSB(A3Q3~My zeZy}bHJrQU+jcZ~B0Zg?H&UvnGF z0FMY{jxB6bv!Md?5Qaj*&t->Mh?I}t#dRHo9HeUuT4maQJ6}|eOQ~1QQ!9%cWhx?h z;tfcUwp=ksw*qvWSA4*0q3-S}iDeGmrOltZD^$Dw5aypotJzlaQnB{;DodqQOe5g< zQ59IwH%)@VUKXLhr2dBSoE|bIOe*)Kb0z$)T}Mp3DoukTC3ZZMcnG<kH`(qmEEjY-fuR)0g>A8&{QdDwV$n5MtISYc8ov#D#S^GnaJ(OYJu4NSMNpERd7 zyTdS@Fr#u?T(ZK)G|>XZTuO@Co-e$;oD@@$y)W8}Ik@rv(U;dBl%(McUmmUHr)@$o zgGlGR(7R(wLMe6VqARtz9yS~?=yt)C;e5C@dm;Dg&JwV!u8wbu3_44)qSz_9H^LQHk4>=VAF` znCN4GyZ7@RZN@4lwHcY0M48^uA!D2YS~VPK3~(B2WmfD>s9e9Daisj6Em~kZf0fRb z14Dl!U0L(u@&OwaC}YGKQ`Ni%tf*w0Uon#sGP5b2{;GL3Xp0ilaQ*e+bQ+O@!FGoL zo#Kn2w49V;?#h-dJwNn+5js0=@Tfv{J74=E-!g(|Z-C&%_5Q;oHvOevg^&d0Y=97=u{EsW`sp;FF7fo4$LU?G+c8yukPSxUcXDf_gT;=o3`ikTZzXYHjYb#O1HY=uOy|Mx32_5neM-) z1I18Km~N66qm+{#F|K@Zz7eI#A9z1}PHdc4%c22QMc33BIB@N_7JUpVTLJULNB-JNk1$-f|IkSuf$R)H3UEc`Kiim@zg$ zcbR*^3uYxwTyoBIU2Rh9vVD(qThfDN(bSj76m<-Fto^*|0>54!!OwTkH*Sz z@Gkrb8a=KNia+>-alhC&IO_z?&pIVNPdezm`Liq>aq#Ui@q2Q+SggPq@hDaMqVtiD zji~})rcgcxjHjN964`>r{4eVdrY?#6a;~Y!XD#NAr{!yS&!z(%Fl0!9so4j)7c#+N z_rK-3hY8_`M0jQVQYe@Hz59}MIfFW${e-iKh>fE$n#&A>776?qK4~vvkx4;_IHbVf zd0=vFedTaK!Q`^>#Ch4=+gxD?pm0#T05&-64tF;moKF}0^=KOIz#kolNK&Rj$KI_- zhqjlO6D4^(YePziPl#;74mB1Z$EHlQ>wSS+)~a_eu(lUr$Oek?n(3UWqhJg7wBB9p zG1n=}#m1P>SveLr2KQ~+_dqqxt}gYR9&LCw(Y0_BY&SBjv=qifQzE8>3cmnAKn#?m zpP=L?Vpm#xmk&2W5a&eKrWuDZLTF@%V+|I&u@&-p(Nk`p^G%t_tXxkEgXihd87KDW znDhL>W#h~sX%RQJPJ|B6{)Ww|ww!l8BDyu<>Si2H-F<_ds=}Phc)(B1xq8Mp@g_Y- zZazyHrsivR&ipTDJxGzw<-ph+-`NA-;dwiOovjloDqo9oICRX`w?V@9(!uAH&bMhM zw%2pHagTH_sJB$kZfyP7n>u3kjqrVATAo<%)9xS*CAE<<$Of92r~0>xOYa)#?G8Tqd%@@>PT~RN=P`=5!Ep3yMtbJyk@hk zyfFYgjd1zfv_JL0!jCZ7-;aU6xgl=5OEDYKWQ8#H$l&;tr$fhS%X9oGGqvG>>FKc3 zzMawFRWWTY8f|TPio;wO z+BP3~N-iTSX9mpBbvPObPc7R{eGIW``e+0ovla31HV*lM&bP*^aXU~cq{DrUKba{! z!1ddGcQIx?Q}*0LwX|B_v@ad|M^P`#Uhm zrp6H37Nz02@OI^GnxuE!UMrg_I62NFbk}%Z=j>5o+TY7Lw)?{6 zG(eu{V*FVgT~C?Dsf@LnSAw|7Uv4&7%A zucarT-I_CJ(rpcZ@6>f5>gic=7wqz8zJ!?>xQGOh6^!DW&Nbr;2J++v|*Z zL#~b&W3&PGK4EP4pyJ+-;(|YFD}s&Sv**x*pE9?;>3n6ByYJf_b)V!#eFBj3f4EKa zRz5$RUTZ^X+w?@R4F!I9Ft8TN z$FqZhj~Y*0cj^aASM6tp?e>^XdOxX$(F---XJ#JpUHLI7dDCGdF}@%9qv<}zd4Yod z{y3Ase2&9|xQ9-xNs#J?Xi;-ur*^Q{s_$j~z}W7P(N9L7N29f11VeH?@5%z={&BDS ztmHqftz0E**y;Y2wr1Tte27WVjnMM?c|#Wsb1SKQ8Zz9&Jn3wD_YJptSwzs!tvkc@ zar1H~Va{O`3VUvXw$5d-Eb_eq4}NUE%)MLl;KC@fo85BK%U9x_Eyzm@2tK3B5101A z$Ir(bMYIb>Kp7dk$xk$BD--@OOb>4pLcB&bTm$+deC8`Y3I1$swSv~R&v1Pwfl)Wl zLU_-`O-ZYMSSDrqq~36b75-Jh!(VFBoHZ-!rUfBjQ+CW>9MR2-tw5yGLJS>L^`l40 z`g4bVjt(cqtAxamL_(mx*FH`8@^#l8@h4?m;pzPeu&4129%7$@tm`XSvC{@@nl2+P zAJaZE%4pd5yWeprjK{r6PG)}Ppg1n=W`1%lWDwk0;f)p$So z_Y1F2y9+hVBMS$;55#i8aXQ4(@o3&bJEI;gj@_#9Pi)Wm{@8B=nSr00G6Nm9BY*B% z^|D|Br#=h1o3%0kLSNJNE^?>&WtpRiw0KQQV`vKjKFl zZ;kZl7Ao=neWx`idBAxR62#WG?0r#dnvN1P>E0a>PX+~2VhPAGY$_|88aO#w85_&+ zSUVXm?>}Tg3SfAjAkMam8l2mG5-tDa6g)Ri&^q+iz=Wm$b%B)2`1cda!I;#)Z4Q7p zkuIOPQht&lKOxEeXOe}bKT{KWq&H16KdB#bw%myOngIjoxjZ4=ffs$kl^c!_S9duy zGhXuM#hw!+LqRMVkqeLR*-%k?^Jf`d2XtVQX)X>3k*V-g!M?ntgJu6W<40+sP;R*s z4HI#ru|6=2ZgZ@=8-njz;WZ;L`to4TWh~lL-R5mitw(Xm{dZeT<>htd#gh98$U1L7 zUNn{qNKUfQ-66JvbI{_c9It=-X+@g zlt649Vdz_4^p)X7MjI*jWb;Bg~r;?Iud6WBB*w6Q|g5+r< zq>IJZX5uZE-`~Uy)DjN{u*rYo6vXiT!4zinMA{Zp3@_W^L3j6Z#a_R^qs#$-y(~Ff zMzZ^+f@E%)=Y%e0W?-uJ8Tt;TD&@0%Vk-%R_BHRT{65}Qd*r@6+Ve4dt5 zsEf8LE%3hN#Xq4IZWl`8z!qsiI}|SJOttf4`U&2oWH|f?;hG?IJC?M_*U&iL0{rd) zf!HGsf?!sc=0(b54n$jS){;g!C!97OB;wZxGUvnUKzNkftX%AVB7H-Ksp&!l9y#mE z7@UD6aUUI6$sX3H3zAG&xon@uvT8b|rliS}i(!~G7ye9}Z=v}9<**D5A56NbSpG87 z<}Q})dK#dxZ~lfy7K$YjGZQ`>p=GB$qJH>ltTwKLctzFZ0kn8AGDK+C>8t2zFcmL; zi2!C$%dibARSISDi;;)QY?Gd(x;gG&9ub-Iy%7T_jBOFg(a#5g_*lt6(*U&OGPx%N zFx5`(FI0FnUz#DFd_X|T@150}w)V3Nkm|4W98)nR(2xE+0>Rt-)h}`Us;#jaB#kXH zpSd1wOsQ}qJ((dAPr73WNQjRqCNkz=4H<^%jCtwUE*;Gd|Kg*OqjH<&BNj($s0m)@4>Z5?bQCY z--2yPiwbeULU=9z)lyRqD)c>DFO2Q+@<45DDmm2RWuI^?trmaZyG^0&PVMB#gFG`u zQf}W;aENc6a??ZcC8&kp);Un@*v#tusE;qX@rn5^u{__Idgqb_%!Z>(i)`5cH$5Qt z%>Q5%y^7*NT%1hlWplDECe`d8erSnWb3YUkz?VT0oFtHJFLEdgSY}mO8Rkrr=b$Q9VR=4pkXB^XHg1bYn`2GjPJYvNXCdIJwZ#w&Idf=W;PwC zNl3rRlujPg&K(Bu*M^j*-3~T><$~On5#|Md;=sQ1EX<+o{Op>QTb4xgEg@T%RZHL6 zR>F^T+F7H_ljBVGYEmjizmVG}rRL)wm@(}R@PUd$nim_J2_ zh^q7*_R<zr+7Jk-wVE6rDgzr*FJ3myP$O>~Z0RxjG8MsNAe_VjH_ z?W`}Sv7w7!ZL6cXJls<%!B5OPcwI;mo_&$sw7s`HRJf8@<7iUQm+Wz2BB431$ z+RGQeG<^i0r9R09T}fs@)BMS6?DkiN4#PW2e$n(uLP5XCwwr~4C z^mOx$AlYWra=Nod4|*1v&73IL|-PWhodv07O@%b-%K5rJDO5<_gE?t;ja`bP_gWT>3 zv~37*Bh62fI!Xflo6@J@b;W~=i8x4~Vh$rx&A?QWGB-Q;BR?~)&tDau!$knSYD{Il z?30YSL9M~5@(0na@z!hKncG2DWTOaNykz9~&Epo^;8~xFW_`mC@c;G--hM^)U2-0< zxpOeVl{kbrfwd1M{HYrew2kbiP)hM)@K8#NMrKX=dZ>8m(UrBnQ;04lC-S|v?v)S0KNAve#)~0ZI#?}Naw&5_@tVYBd{d4BS96~ zpyPgDQ<=o6V|pnr#dRO&Exj)L99W`j1WBxxv)tj(BXZ&y0Yvl==Z7;6mglwSlmeAa zo*^SK4H9ky`63`!}X>bFb}lBRWHQA7ORm3lO{7v$1l_Gs8omjtDO$an-x_q2=nx3RMl=|7eb? zl(uI>m?#>#b7i)$A?eLo^%%jXTfc(O(}*a>_Mh^gSGAf3u&+ryH6B&;h3BGWTgt@jpf)HsB{ytjreJKnTF zLtw!pSA}`9lGwD(0z`e2(Aws@hl&bAcJ$crV)-G}Bt%}M9S9o!Su$+3%LLm*a&_Jn zdhUD7Rk;bEnRoxiI8u`SUyS4U$*2cCP2R>6y!qzYE(@$u#+O=x<&vp_EKzNfzvxeB zc|jA2FM41d2wPne|JJj)O$ngffBMkwXseGwwS!hhux4TD|4|%gzJkAYrF+&>MBKuz zt(;Tjh1%+8H|NaHV2c>UYswx7!D5-{ z)k2@ zKT~yxGa;lKR^05wqfr#NI!`V{qkTzc)0bs%YoIPXob zpzw>%;P2|#bibMQqJbPgJ(NC4&ujLN9U8?s>UrCju9}Dx1vN1FL~J^vP2jSQW^1{Rp&xGw z|;dsF1(2 zYV~VIgI=Os#@Qq}`#GP|!xCv@_N5GKzm6!=(}fAJE9@dN)mRbj!#GmJvLBHSxM{Dq zEG=?rQO8M6s6sN+(pw^U4$tD)>?-`Md^@(T4OGIEE2rGc0vRzDeuY2Jhf(09s+`+P zRLHj@Nw164|0gQ|iHB0%4x9+_#0g|3AVt2?pp8AeLZ_fk-ff!tU&D2S6sGAlmGCsF zHshs-!3p`?q;S5n1EGE(1TEcUSO&d=L$~1XJ07J>4@lulB8&FE_qknFPE@wK(Yh7tb$POg?fjv z(A8WeAuoV3x&^}UYGT5&StVy44@>sAG%d;`j~+fLHXug+BDX*YHUU{a21svJ6;CeosEEXX20I}+?z;a(=^I7MMQWV zUB<;=&DgjU0E5~6H;FSHfeF6bcycw-EKhmF`Q)d};Kee*%Fnd10+ydGs9v@_nN) zg;08NFY7U?D$pC2L4d-R1ZwviYgo*;8HP72+kvU4E+}pna9g|1Jz3KQeKj7X!VDcm zKp$!uoFa9$dpaCrOu2TID>Y_TR;YsQ*Rv?4qbpbQ9q2||O<-^zQ1SuG} zfP52@-mk2$HAv2;dDVs9aD+UAK0)!Y>-*$HQ*PVZD#gV>>R7s)<*)bQq)p?WZ7+{? zMuQD~V8vAS5yq^)+65vif@ zphutt5d|k1f%7pq^n0ZU^|fU_h;x85*`EK>lXDOcRn`A!{gPjv?IE^-zexP=r|dp> zm&*NgUX16CDX3mSrH@Z$W`$o33c>RM+FZXTBfh+QLN*PCS!Rwu>uoX*PKc7vdR6PP zwEXMYJ(J8%DlLh9;KJ7Z76JoCvzybX#A^atg zmrTuaFHZ&%F4^sjzu;SexP_$=9cuCK9fDLkc8li%<>^t$b?*$^&^DoP(i89Taa)G% zWk9$FDf2|3lnc_nYLG=KKdKSPgDE-QMaLo&lO+2O?|I%lVa8BRquT6L21IMOr~4Wm zlIIaN!3ks*|Cm^QV^9)2ZS97fT@{>Q){SPP25W1238iFc@(0IhKN-Wv*OAXAW{ntq=tOiy4bHDqNMIeI!rV^q_ z%hKkr$|q@W?;M?&*WUJ?vp#uWz}l=B0mXst2ZC-9r(f+S$h=IA5R2B+rKX=lNNlF4 z30+wFYOZ(LxuNnEySIh#2nMh_}@eIrL@*GqnbLYijFN-Uwi&7N8P3Rjw; zo^np0aw5!;pgi&9{w`zx_1&V&s6h3vAE5i=KYDg~5y&^)|E0fa5&U%y=_=R@7@a4$ zx8980rFBG`@!)rPW6@rRw(_u(w2*{LaSwFW%V1u5fUZ8{j#$y5JJiR`mFQS^Qt)k; zOTd`~emTgP8lO8tX133mY(HN+G)9}@$aHk6G3&VqJGJ_NOFx?j!>HL^->GPAgZ)iY z%lI77;y;fo1|co{{N+P;6dEUAL?wJc#p=ZV$v|!2@Ko#2@SQ)51W3<%Qin2yn*@l$ z%SRFTUt-|@A27h55x*+;&tvzc#2HuFuq)7GavcSX>A`OU|3$kQ!K_w@+#cw`Rav%< zrR4a7t8qWy`kY=Ze11PApFdsJF*rZF2Oy-6JmOTkc-~Vy~9RIfuJyS*qu?VHQ zAs`{^J(e%M#9_9E>v0{V>cSRM`#t|``*p8J*w9kU$8-5Gq=KIvaFc8Lkd8aA$`uuS zbj}5F)%eE}v7C@tCnNAdJ23a-i>Ehggpb>ogDo~DpEZH!H&tVeAxRR7*?erToH1J( zyf_HcY&GSqr1AI2gq%2M2uom&74HJB=WjudC>&jGYVY&xS4w(Fi;7yFgEl2ko|hu9 zFv1|J%nUDkc7&zk~?AuBra>Sw!J=^?_g2Z9r5+Hsb0y^I!i1F-6j7?(OKmX5zYv z%&9F`q;2mSDD$r!hxo3ppRRF z{Z5c9n;OP-mSX6+&6a@@Ri5Sow?2pUa_Qs50uJ@Ow09qdK)YS#rp&3S-}b#cCuT{d_j$(OVVtgz^uHfMQ+P$jAX>zGNvnk9vMx1c=2>7+ zPYjkajOFtXH9cELM~Rj%wRIGR1e!1<-cfPc@RxiIT_rK>(vA6Lp3aX3&KWCvYO~e9 z35)8;<)VzUL{*+wI6_hv+dzLdE@&QFJI{3c`qBrejbG$qL z(qaA)gZ@VhyxLAqX!8y1UL}3#4;Od({AY>M=!UL!nJeDhVD4<ilIu zYn%pZ{o;On`6J0-M>F1Ohy?NjibL8Osk@QPb4NIRWsjxQNC&sfK2L(9-`3$>2eKiB zyQ;(}|M!n=!>vRjUwot2boQ+ZTi4-QE;i&&m#?!A76FNd&wkZ;(YjX>K3_zqlDPP> zPPVQqaEHClE&JrYhwqbMeXlAA96Xov@uQMUh34i1sh`d-bs8Itj}Y7RfcB>XQbv6A z`P{TU^Vw6NQyZGc1AELbXZgG^K>NsXXe~cSMFGtD#a&_g7iflR?Xyt$zYh4X36{L+ zV1wG;A*uzB2<=;`We?>M>3B1tn;07$Ew%MVe%*9(w0x7bD|Km2kA~x!du01gbQafWE zO@B2kOulR@KXiFxf@b!L*NOu67s>zb)Ql6j+lRNmYlfe2n^j8%{N$%MpN*2UO`Lx1 z@^U^`wX#_xT#x(y8PL3c{gRq2nyg#3LJ*RoGWt-S>|=m373^ov^G_n(BQK*kIw2QuflE|Sq2VP$ zlKS(&;0Lh?LsfepyI7`wzHEVf`qv)7X2q$44?3IMa!d3Jfolg1ycgw3q^LiaXvy)c zBqm{*Or~+(ZwHd)og;eHZ+T0WTEoiW6X8kri($SULefmTwQ{5`?U8++S#tXX5Azxw zJVrTUx(@t5@o()LbdLDdgm=qoP4yj`Xi)V9&zOO}M9`Op{nj=6G2T-!=Mnwd>oL-P z<~TGBM2M^~a$h8?do?(pPS&Y^a&?No;sz43TOMHSa8Fa@PPEnj$ma8etT@A+o-IfE zgeL#`gz9B9wlZ3%7c78|=V6Yy*Og{>v})biQTBreW8#b-bvKQoOh3np?9Wcs{hhfT znUV3@h%RHyUar7Uq=1C&LqGjRRu&XBl!V4jqhez!{#c#D#r_0smiL^2WSL55GX7uS@A;Mx~@&RW1K zW99R;tXV|q(7=u4D1PC$Bpmh;lv)cZ(LY5jRTbSFFcW&3VY%z#&y5RF25=LEy%eq9 zH&6#2W-mr8O?R7YHY{qi)+sK}4+RchNuv#hDFyE zV=e?VfA*QnA@e*7<@g9nD*>F{K)Yt30pDmFti5*vgVRy}X>cb$RX?pZ+p&)v4o!J! zh`6`NoFH6zLTFDN0TUd36$}spNQb5M`(OKaNdaO&R zo_|6jXVJV83G2v+rEQQv-v`Nt8%TbUb?tsg3VGXY-f*7pah3~(uoyuAVbjCPJq{kL znlLw^_x7Sr#|H`FrOX}$!{d!(oH6&LF$T%H4+CB|)iFR{MCox^PJ4*vKKi8KbZ=oA zMv-?pFR4@i&t5#%_d_jg;YbAave^~y2NF8 z37lB?u>>2#=Kt$%@B`N&N^$1M9L0zo$LY~sgM3ovkyKKh8s9Vv#ioKpNK9Ef`mT{? zp}8K`3rpqpm}df^p(IFF<+=@nDwF%C&v)ZBWBStN!ft*b6@or#IBvDrA=2zYN{VVY+~quiR5bYk^2 zET$%R`|aE{87ujZzEp=M|PB$D&A$yBVE>N@TAgBL&FF8FBqjHz|21znT z;Dit0c2atqtw2J0uVq6LEL<<^EyRGM&beLr*OvN2HO3WmPB^$cEfi6Ofn=@pwjITZ z=2;xU+?c0oA=QrZC9W87cjW=|2O$~$@;${raB-(vxnt7_@kSO|Px?6Iu^fDxN3qb= zutr#4nUV?-e>!@Y`0x2m%=Pg!;`Z{Agc!DAtu6R>8G1IZKU4o^ioSu@-loR|^P3V%2qKYWZ$`Yg-)!XEQiv_2>Fc@L}liGu25 z2hs%NT`;wdMl>dD9OHp#7mVdme5B>*iq}$Pmpj2|d`NJRnjoE&<%FJng~|6Feo7++ zR`G%z(78MHNk^aT|OvEp8Sz zjj3>BOzYa~;3$Uuo=U_qcxDfWY~nB`l@gmr1HtE=g~OVM2>Kb1HVyAddf|*{O(`)mHSTi$%E1zilP%7raxYXLbEeS_ z{_zjU5wP~UlD=SS1Q=WVX5}1$LKxuYYq(X6Px$4cN$48kX2HJeb&`K-7WHkPNXtX8t^{H1P0e!)Gjw2f)2Y<6Zx)^oF6>kM0pYxki>OJ?$w_Z=lu>o z&;*{`~ftADDAp zH^hqHTXt;OjG>kVDhG{}oc-Ok1C9~1uBf^@1*w^Y`cBq9q_+K)pEtxMMPBNSSl+Ts zL0q1++JsF!bjiJ#5>Kxfv@05}NGXmEZ_{^pC_~+2_9nvgDO)X=Jdr?Y{fzaW(~nDI z%5O@O`UPfd=ks7LOMOdfa&jM|PwBOGX+r;8W&mK<7RC~Lpveuhknr_LO)TN7h=rzT zLt7DC%&-K9dYQAh71)U`{8XnG8J3W)-hYp=NdSFq?>!WvB0JgD^=8%MTD#G`&4R}n z)5^QV0ipW4FMQ{V_+`>5@2~TLhNAFiNj2>k_a?jlPvPxfd910RtVTJ4`+6xClVH=+ zB@ZvBAOcuO+P}hST7|AEpm^tiuM`%;JADYE6f6B#H_ZoZkKATCkJH{H`K_WmS69=p znkMC{eyh8@gEL#;xm^!>3+S4b*1|tUNii?j6Ku!g%pw0%ekZVy!lqa~q#ZoBZ#1&V z3`{3gK5tYQa~GDuSpAZl85>G}srwCR%rtp)K;6ZCwGzerHDG{ZhwJ$-CLY_d1;b<$ zozI%tW^4^n!&kwEZ@&qtr`k|{>Hlvy{1zHbSw_i|gEqF*CDB-NU!VO^sgmuDlr6X1 zE}PQ0`c3%XN*vUV#ZYQ29o{q_Mrf0QBn@;Yb=mK=SXp!3WM6);qVX{y95@TXr?w3b zA@=7W#g;sBfqyH1qr)|O<2~JUkNyA6QMZj&cEP&hNyhi}9K48HB6{sx4sNJc{hl_6 zne{_q>#f&Uh`ScGNeF# z8m~uLiq@DGJrd^NP~e6!K)LymAPaAg9dKXYQTo5=zL)eFU{@O$rH@~Tp6LZ`4wvaD ztiL@3D<39x3)e4*4SI2K=)fZa621J@20>h~fjV%7$Ny1I`+m32#9T>;4OsZ}B&zIJ zLO3a#pt4tyefKh4=SN#2TdZ-;CaBsxiZWU%{f|LOu=TZ$O24#&GLNMR0NZd|K(I&E z&prL}I`9(2qCpF;)zw?Id`uS;`p(Ya=^t^^Qt&u8V^*~bX#0w1I_pL5I5nC!^F>7N zWbG5dG-rP?L17eL^))L9Bl9J=S54AfL zm+eRC+z(V!at7;`&82#-l_AGgzdbfZM58+S0LP7|+uZXjqB$If!q8G@2Op`Ur8K;k z{_>oAZL>BF#fr%^8#9A+w|BYZ2UUC{!sW>@SDneu)EC5wj=Sa65%Q_;$d}6=^8>k= zVdFFq4vkkL4$d8-b=1uMr}h%lx6H2DA8~nvCC0BQQ!){P^lPL($_aS>dS?v z1A<+km5LAO?Qr#wSdI3(g~E_KZQG{qK@wj~hHf{peDNrrb8|3F)_h1=x}00foXAnE zo4X?ZvXsbHupKclz};+l7Bc*oyCt)$zwqe4hu*T>7wSe5OmmsMj%Y9G^E2d%);zk4 zZ1cX%r_LU2LaQh1_K!=51q#S7-FK2tYp5B3^Bp4{88ec}l5*3SLDS+fv$`1xwb>OK zxcIZqb)hCOwawm~9n`#EBs=HwU6pzqXndyeHPLZ`WdpTtz200!+Eet4=DOWUDMa!__^J&Ok} zH$g_Ego4*v!(7b_47AZ(fqNnz|ag7BEVr+$_^emclt)v>sg~4mOCo zX~Mte4z0IW*BZlBDVR6SoX5NqdE<`4QaL>FdM;F*6ydn^@&ZG#mlZFM1(N)6n}Bf^>bmt{`Bz*(2iqCtPvI}K`xoyqkr$G~F}Jr~U+g{m zU>P-0J{;(x#DHG|KJqNsS))8Q);d2G(5R9ymEvsp+uFgpfZNrFVF8&JhX)`Z+#@+nV2;^Pb% z(&1%>jx%9}@BSEUq|67rNU(Hj--SMO)YgYiHo}o?a!`QB@FLM#gV?I+Su1C*m-O1`|=^dGOp zrPPH>nW{4;!zqFKY38!vz*&j9Y_n@|6W<}jiXXewS)@2E1`BgX3 z4bP>iVOvNv;^g)nUGr}bMK1r|G8pYK)_m~zu7rum+j4#myCh+h=>6Gg8De$qH~6!m zcPx%dqjXNgJuJ)S*KEYy<@@M@GqeS4!awp@eTb|F1I5VXFh|X{2u#BR^Q)z|4zkmh zdX3yy85}&5E@%=x4VIa65z#@=;f3{Ed3p&AqIg!|TluVko~!GC_L>b>E(}e``%fhYGqqdMF2Ge$q-@W< z)LILY8=n3@H+%*}2u*UsoBm&Jc=vzZ@ZoxUy6sy|^uViIRu6h0fpBx-e&5AZ5GY>o zCb#^Ws+yiBuxc%Pi<;+)VRE138z0TLB7>cOzRdWK%fymX)YD zRu086vX1SL*f0MmlHrz~(`*br47XSpeTv(sv%=CS zPH0+~GzL2+byLS<gLWj z7j&_c1uy2UtlnWT&&&-~cH9r@?X^9cdDK}ef%1lyZ>Q_u1pRflhnQxa78T?mguoC~ ze3<)-Zvs_NR{aX8g|oKU!+zY6=X~&av-|S^?w-8(r3wZEZe$$iL$lVj z$7S~&uaC|=ddcp=U^G%-z7*>3SB_!jIIm;pf!}??-7Cyu0X|D;>YkmBs{Umg;+
      SSs2Iquiy*;~k{&8reAhhT?*#`Rvm>(~FjeN#nBU^kHx*yh1|>BAo) zBthWuX~_6ZKH9f=blUVVb}p{yUdc!8@PlN(bhiPy8!5FXP3x%gh7x6O6xgf$^~(~E zyC7!}P7*O~jWD-Gc^>NF&Pub;S*3O?#?B`{XE|Dx$t-3GV7m`=$5T;<4S?CLm{M!1NtsR_PY1?{pq;GUX3( zff+`5sF%RL*&QJ8bXti50S^U!vN~#98I8zp(Dri72ODVbHn+%8>mH{`_Qv=5 zFTRywn>6PaUg$i!w5(w7$8g!a1*nZfST*I+eDNSo%LwRAqxH!*N6;HCoy!tL8V zKl!Olk{kZRyM)epjxkwXnRp9~PjXK=mRnMcDmd}DILb_^g(EKQiGEt(>iwT5myG$( zWUM_d(8y-6Mnu_)R0y+|%&g<<(Nj49BX{5|&?EM&zxi{qzU5U{FQiyTeqqsNX!iwmsk##Ce zZ+JVu={JHr543tpRZDh<1Vb?ZZ>hr;Kh2n;YN$#C(x$H9Bb;Tumofl%Hmj*|9a~Py zK>i}NUY{tIp6yt%?M&X$jUU}PrmB#LFA?Z%+uDA?mM)F5@&vMWDxl-O7p4>J-ZT*-FFLq=0AV0 zN1R2PIfL5|o*&To?4y*4BFxW=H-zKn4dX+7{ado=>qWWw5Z-Nfo14b5 zqGr4VPf`iLW!bQuRpy32L$^Lsrb*}iSA zArF$ZII4S-!tfCD&Ko^xNS{??O05a%9xu2$yws{A=|iUKXY+~?^18^42a9XLlI;0m zGlQz%^0aa!)iR8$B=J{0US2uSdl&S6f5^o@A;DI?y8!ZDq#=Gg)P+po! z9>cIfU{S>aZ`9XLnBFB$Yr7cY(BdJA$N8U3;Lq>+uU1i&XlHV9quLkjurYR zTKH;NeIT>LEY3bT+9s50kSE#Lv<>^fme!l7;kmlX0qP@x8?+8%2IpF&M$WY>@M(g~tP-RVY@%V*88x5(U^{bda>OfzRsOk5)Z zq^s-ep3Cx#d~%82CO_W)RsqXlJ18dosnkzd|PUB ze^(T-loss*>T>bylCV27O-(vM0dqB{!fJ1bnhHvP#;l`BKGcMUgH9{;N+%E#Kl~$L zlKRC7;v$KSt3U2RDw((zc^FC6C>oFhr_2cUvS2d$vc^>)33!!Z z)e||-xd?GX>%ECdHsvT*o?0b!BOO4bt)X(^glx7c#Epf<8BC&d8E}p8&2G~N^*dfU z4@i2I;TgwN5pkSa1hNeJn3A1bU7SMcu)i|1C1-q_pcaUrur>rL{mdjco)Q|suxUW2QA2=8vEg#hM3HDg_^HmYQ zZqs>yIOvRO4l#s}nm`sHKp${dI_WGVi=%0k^0lMm`RdH{EBMILKJxM=( zlm}L)|IzlyMNEr;DjO40@AjyzJqCGoHJ_xJ{{#_#WnnAuAS%f;qsa2=ALF}2m$ass zjSA}-@GtfxonV}l;LzB3!KC$B%s2crDTW=GdD!ooXY^dUw)1e#&HsT?5uB&`3n&Q| zcV8)nmcrllPO{ut?`XTnmh-8OlgzTiB0H9M2`eJ$X#WE+!}U?+XWk%MHVaOIzw;%3 zp4<_CD=G`(AegtP_gce|8$qjpM zTjKHSgg=bw!`bxrUuX@RS8X)$qK!Y}#+mZmdQWsS?$~9o3p9-zRA)Ziw=6h^Kgnsb z(pHMn?%a9a+PyF&Hb`8!Ku$0*D5e)K!tT8oK~pD_O4p8qxkysQA~-*5Y82TnN`eQX zfGbXWB)WmnXpUBhZcEeRu|f052V#!QdPab{J(Kw(HkJIK-+*F(^G%FSunVM2lC<`Q zt=}oF2!a0A`}Dr+;M45KK<~9zH(xozRCV+16P$i;FiQHOC(l)@MkTqrM(Ub;n^lP1 z{2rM3R6fRYWXb^oz7}jz^JaZdU2vOs6!*bDP3qJo{fdzoGGKW&4##%uCJMzZyUu_b z+e_fjwg5#Peon-94eCu+UUun60|!J*mn_;0bMTH&XB(@7zIL!?nnmm5f-$|7DN zTJ}(Il@!v0VLE%aaD%R5D~A7Z$nsE}lNq3gaV-ysPF#YA`QP#`-lMQ$+CO~sU-x`# zaI2uD?*SqEj4DO2Jd1ZSTGjpqk&a(P?;T?s)IAMli}XuHOrDe8zx~UL#{`Dej-tF$ zHLzs~JKv$yUFFIQV$9H^TL8~Uw^T(AjIweeMwPbSmXl9{Se2L4>xnu-D0cP^<~u@b z1;pT{8RMGz?a)ZAVpx%mD#FJ;vA9DRSclr+9}ofumP>LNYz{Al;GcO0Kb(doejkY{ ze{^Ra#Ms812vc?qKl?@oS4xB0tx%{eN>aidS|2>MI6)^?sE> zolZ@)U@VrG!TGAa<01e*5}we8ifc$|l9aez3~Ww9uUU*lp%h7F%O-ZrZ;?TAaG6mR zaHn9&plDTZ;r<7I>KX;5;}t2*dRkUja7_JugJX5sKjiDmAixJd|A|bwN|SwlaCE~Z zJfg1OmJPX$idz?KPx#X<-&x&{#*pKb4)tFZXpvK593l1`7Xf4$xx*kvBGy?x@q$?CHNI zg>NAx|3bzYvZ1wfduTv!Mo{x_>aoEV z!trv(J@Den-`oUeK0lmKb8yg|r%ZE3lWhVu+X@c6D0v?vt1Wr>5A5gfAa!N6MV|A; ziSBjddCNxuskVz^#(a04s}a+6$Sy}q^7k*1lJ5Hw97^X+`_1!#jW^2)l1jKaaU~oI zD5d_mXzgw=Ll6;4L+7)&cfUjktRX2TN`%fe#_6oj|NW!L0XqPdvt?Upnl7)MFMErV z&QfUXRid|FKYs!b$SVl-6Q=3VWFzVrRRon>gS^iNCscNaE^mo` z>5>D5EX6I{oEnX)Dv`G=MM-zQ+jEH!K?F+1rxkr{ zU-oj^EN!{g=-IT%lLmCtTOSjU$R^DGYk%i=-lrqZc0UadiI4Mm<#nrKrNKos2*`+P zcGs=_oAS+^q5gP%714(U(a@QVxlZLP`KaN5(rNWzNj6mT;TqE}wLU8=yMSbT%etM?!n(z;>f7QCYOwS}f#fh{=-4ev>INaLd9&@NlX8DP_ zaol+^8QuTWWw9I|Che8LaP;ta-T`C`ogCDI)okVb`@EVZ7>p=hOs>-bE=Almf z_F~Em$#+?uz*IiP7{NnR342n#^JGh;sq07pRCeH=S22KU8FF>#QZ1i8N?6S=x%Oj8 z%nl`z7;R_Zzjqh@`?GQ|3RgUG`f&7nBvnpUaB>Tc+ZAQsy`;l&A!;@xeHaD7Eu-KY zd{9cq*O@7~1novO4o!V&LhPVor>Uirm&s!s4DT|#8f(@Ttee&&=FWzQD{qoRS69va zol`13CqvtwjH2k~>)C;^gokdd%YDjrxy^q*R<_REZBhhYE)AM=jbBVVZ$z&fuZaYZl42C+>3Z>8ob5ZY{ zkWn%=r_RdN+|m;93?A^2HPHDRQ`SaB6>mW#rwK2j^eo&+aL@4|EJ?9l(4hU{buc+$ z1IvuQ;U=;BMbK1Rry-T7Vgbv~)>^qxn76@#AYaino`oQuiFmJb253vGQ9yN~nWx%Q z!8*tPjN)h~&_ib4F@`Vg#m`1>T`byTl>FXdB1ju~2|g^h$F2p2M^D?w!2-TwGgY}5 zs~I&aNqTA#l|M97PbVKl!qfXFU(h(S(3nG5xs8{EGdX#lI;$ zs0`!Rnn(8wgcl}-o=;VdsbM9AT~0h~NQt3jY)_>rL45@&cnxn+L5|*ge7EV4(vCwfO zJ%^2=rCYYNp8_LHKi+VL45MBejzqdK$|!995)_$5y_0*a#_Q*gZ!AT;=yvo7dxUdB zfe59VUX2ghUx07F)~U@F5w#pK+{wL)tCTGL69+Mjt%?+D!Wo2!+TNa6kBWt7%2D%A z+{csoB#Y?0-&r|L$gsFP?A`4Ufvo+yXDUBoiuMc@`#%R?R_+-N=I zIly`y)eEud#ReKYCayXo>L!1j1i=ChbUoyRxU@`5X#Rfvytq|*eudiMacRvBksNIt z3(5^BGybbb|2@kOd-_S1iy{tqLX2Uz`bQHne@$7$huj+xL5Pd_HCI&oMS!MoiXbc^u1> z?o1?gckW70!($dR0km936)G^k+F%|CdsdwE{HT?8{)a8-scsQq!WlkAhak!{OP}m< zzxbSB3T26yB#*s(4fAWOw`8~k@_m4krggQk}2e=x)ieCj?x;>+!g>iWua2&@hv>Bef+Z9sE`mF1bqe zg-=m``h474UyyWe2t2QPSz{w?k!|$n{tfW}(FBP=fe(yfDN70R0E@TMdi&QZ zU+tZB8@Vvn>^MG(G_nF5SWL0f#kD_ z|J+o3|G&$E=9G5nCijucPM5;Kl4y3ucZ{k$i@^mhcY15N6TYZJ`28?#fGMR6wVlv)~X z!2@EEa(j<9{Z#S~xF>F@?6%+E1g`MxE0ovVh*b*POt=&SpNn;edOYcrOHlqkNMh@S z83%cKojAHsNK8(iHZb%eL2@^SbG`l1QDO8+uu0A%A&UazfaY|VG};ASNiXA*yR)dF zyxxaIYE)7;Ez*?p4eXdGmj7kYx4#C4Z#Y3%j0ll|dqmMk=-#6L3#)5^&z%3Tc=B8z;OhE-Gu}h*dQ^x{@%C+Sn4LeUagm8Y=9Sebhhow&z2J$Xz+jM5w2; z@%h~W+|)IEe3v1qqmWOPFKl-sj6TMSDmr)BE-wA3r?$5iyVEPT8Pa zX$s$fYeqy`$^QsLim5|OrYial`F&aX^SuiOQ;`e~Ed+Q97>j=VxJudSTK>Y{3a&AV zlKjEjXB;T+!Ele`_`Ji_C!kFMWx(_EKD(M_eur+Q^h=Ywf5k4f4!6ql#8~hnu=VjW zQc*h9hsLzX1v1p`wEfsuPmBDc}eL#o+toq7{ z*S7xj-4rh0Fe1}Zo;lhMW6fh!QGXpt@=FXNSG&#^H+D%E^ZUps?)f)5kf)8DYu@z~ z3Eq<-P{(cp?fIZO`}T#gQ}u^k5C?ngZc8)AW}& zo|wCSHD`78eM?*<-1LE=IEUKM9qB4itqSLFzm#2jdTb5K(&UWVwr`XbiyNyQC za8s9xdE4DE^cRXNLwj(65{J1l3Og$magsNv2>zZ}mq};LbZke{5bWxz8!=zQ7~Kkn z6-(vB{jXA**&j+0uiArLX?=;9i7crVpMOsf%6q zN!=0{&FiW4Di#SbyGmQ8;oU*4tHlLIi$S%Z$M6WL%cXMo8RVTZ+{CBNk9}^u1o>C@ zKRCS{xPhkU2!=V{0GdIv>XSMw@Bd!Dyb42WnAw{L<63Aaqk>z013cVct|J_8Oc;Z9 z4Ugn`gp^;iIN)Af*H4r&i(+C{4T(ZM8*060T%|NTUd%zt1e7V)HO?#lk~9S;e;)@b@bSG&69yt_k_C0fJ(g@~liq+YD|d0PP7O{jt~M*RxKn>M zFQw3?ozP@mUq5?1#rxQkb#0Z)1CvfIz=>io;q};)eBaYdx{xY(sD1W~j`XNb*BYES zR=eo);&fh29wJ@x;p==6C%2yQ+i@>5}-?H)7uJ{lUSKvhn8w@Hjd zKpjOsHpB{u45_%ITE3OBKt3$3dETeN#J)Thh($ONQ^hQP7|%@8zxdU&NG&50%X+qg z;VIoo28$`>F_OZa%bi}B->6Bvwi9ZX zjm3I2=s_}{^nWlp?Cx_EIL^Q%}{M<9-B>`U4()T@SLbR{!Lp+73tRC|bpMoSw+s#HgaXW6E) z=j(F;^b~34-~sQviuupRDk;%G)=# zoe1v(8Xmm58;0AtZtbG$(sB_0nB$zCCg5xxsPy|2*yvW{3|xN(D(dgK|4r3LB(-Jm zW3W$5&U)RK$#nJwA4qMqs)~i_cGu?Ul=5ByKPrP-hS~gg=$%+Ul2_r)mja$d#~Y(s z&-S$>?P(A6AVt7kDi>i}1DJq47x7TFzXQLw*KhnLBJLIA`6A|wyH3sBB7V()HtTKI z;X5T6-vbdEINb9v44LI|D7R~z$y*Z4q7H4l^WV(*w9VAf5`e+anW=9gA;Z?ioQ&|= zA|W9IL(J)R@a_CM%#V6i8KgjEdAa^0>OpP@=+r`oEXRXuA%T)~ncF0YsJN?vpz# znXpaaGX!P9Tk)@NuVv8GZK4f2@1Q0))!quphxmu%$=BKspT#VKRS^imXB?_xp}&?y zt||7jen6PokZ9BC|H^ZeabPE^Xf_@Z)QwId`Ub#4!t zhoS6Z4ZmIv5&nGRN4b;6a$lopZm@G?t$-@Z^@SC^z(yf#xFFtP-L^Sw3(4Qca>G>na>g`?a|Xdm~J zcNOc%6ftueQ}WC+X;q^TlJAsg4Krf7Q*&QQ?mQr`mKOvDm#^{kuz9HcEO#i4lwJX8GzBl0amNQG5tqt=XQ3x@* z1n&l;(Qf&c1@;$7@svdW)ky~x!d?Qn@jc#9FxuGX*tM2`eD;6XxW1XK7z@u?g1WIQ zK?(eeC2F*DR)lM_@ufgS@!J3iR~or)j`aR`KatC*IzD%B0nE!jX;@3iOGi?30h?Bq zN9e-9Q!h=VUp1Rbo@>>5oOJ_3pySe`c5Zb(K)g_T0YNAC<0!#^;y7GUv~ z-=4IkW&a-Ss>MwE(#`a$fqucWrx(bVhO_awmOyH!U^}N*(@}8+$lUC8Rnfdx@iAr` zGGFfzdEDiif=$>ebPCtFv4~+KyJ{9%J)T#7?gjF>Z(~zZ*%8X$_bC1P4F!@FGpZxt z4>S1gh5DLxfBisBM8XeG9XERkIE92V4Sen4(J)K<&4e6QEJxs?xu@d0{2S^uftiNyl36q+dH4I|3+`OkEGF?KP?QJ zHvk}>1gQt7jATn-r~3z0BMzJjM!IEA`Sl!L2FJjyNP{(1uWD^>Hvw=7r}F`Zyzs?i z&XQM#ZOjr_+n1)4UlnS_I5n;#HhqrgMkBzORMH8E?RM6>7=8Q8|e)Poe&Y#Z|Q3nkBBQ z|M0<@vg42UP^D5&i)Zck^TF|~DYK=d|EyC)-GIau{Ya)N%Sgg&tpzY)>3ZcELepHZ z8PEFD9-c@IB)yqh*aQLk>fb8gR%uxsYv2|TaUF0S`oEumDbaNXPtVS z2`h)M7JO&4B>;@@!<78O{qL?|xk%y`m9#S}Vox3PQcGMA-0|lbsgOPDz&L{xN@vdG z6Bcze;}dEq$k6q=X$BUfGLsvbKR$-bw(DG~=8_XNHwUwYzU2b6a2_yB&qSG=abfM1 z&_BvqLAxx1d9v4mc4=UF-V%mc^rlMeatWwPfQ3+Fa zGPP-$$+QM;7*3qlyD6$d5-GRe3+l<5F)$}@I%NiMP%z!m7!XuKKt5gp8q6t52aqt(h9w3itaip zuBqj2i&(O2Zh|XW>7329(!KNtkC-j4?C%%NK#c84iS$Lmk?EZ8k_UI=fa!NV$m*e2 z{b#VocO8<#aKasc9`7fuPzNF|$-3-=6D)|6DO;%;$BjH09U(tzi|opmZ}%e=ubXg5 z-e^`!@DOZG^v1yQ|H{Lna=y(cRCQnHhJ|bIaSh40t`sH1PC3C{1H!98xjehLh*HtJXBMDYA54=H{NtVT5`&8n{1G&mVK6o zP8H5z8DUPTO9ONiLc^f!pQ!a{MQH}Oeps<~ zuP{Su!&|aR)`&Ob5gC`cg{Ms6T{AxQkDu}3VH&{CtY5{L&Al%WD;gdTT~Rr8qPz&8 z2ubyp-wu7Y>AEH;2~gH3Clw^YQsEPQKhL41l>zulGiH(9^l_%2?7M1w_JX$YUROVD za=to{;+=c`;w8Ndr&w)T%2WP%*nd=!`Mq=Z^g2nmb%Zey^<8%d+gyBaDsZLHN zJ)Aa%x_XT7r_1Qrz-<2Jkg7Ag-f^){)fLfo0t4KU>3rXQ1>y&R0S1)Y1=hX8M>XB8 z>8IOIjd%8O^rk`(33LO0G}p6Mb}N<`&Evh#QCL5V3Y7c7_jR2iTfh-@ir}AlW75(K z=UjnLE`ID@Z>mqz_;M|#l%yT+>dCBsfFK{ER5G=LuMr}udqBA;v1<$6?K-#>y4+av z7bciPrDE+{66LG$EQ#Z$u=1d02-MFUaX%x9TA!mQp3yW_6rH}%+W+X`C*R|vPVt}F zgowaLNAZ&c6>cT0FKszAQ`q$D)dYQVKUa)G!(UZrB}=qT&vw)y+*Ok$*Tb+3LWpV) zHhK>F5b5&mM$q-!+7jl(?pM&|+TpeBK4YVZiY3rjoZKp8#Z$-VzKh^yC$=kd-Gcw( zo(N_Sli>I%c+*QeD0u)FR>$~m1J<=RqZ0J^_HX?Cnj>54?Y`}sb#n&a>y@exEc+r@;C664Cn95 z%E!dpC&&giPTt|{7nvM@k-7`|;&R0+kj7Le!eS;q~6jLQ0fy7_E zPf2DgPP?+|-}q+<8|e2u_q~fd+FM_$nFPl>vQ0$9yhyEA@R0YF)G00!>?%_>y-U5> z1L0arkBlkccK{MJ_t?v}M*?wyIP?(cNENxBG!bZNh3dAsw}xZ=;^&^RrqB~EIrg*( z=b+{}GbV%u_V^zyHLVti>XtK>u4uoUl zH+=vr<{e#;0Vc6xJ^S=3>0kJ%U%nRU>UHy9Fda^AnU9Kj`CZQkWy=GHhH#ES^Qb;Z z+jrX(5IZC&qd7!4Jc25Hzm_VZiQPvgsOH?A9&k63m~bC$EdIZmCW0QUVUs_aXh8e>nT4rqXqOw4L(_t!^6II-#b^Z65XCH<}eZesF zEi$Mqj+L&lLwI!^oA90Y`Rl&*uU&F3`UR7{ZOTW61f^I#-|U5mcys@}TC71=nb*8n z(Ug2(oY6ScKkG@_eR@!*fYPghpL+Af09WP^*8qB>UZv5W8?~d$o52a;>+HyF}EwoVmnQ?vz24WhRrX*xEOa-uv#=NUHo$`E(0p$`>8MXekz zu7ZvxJ8xbsn;jx;$f#XTqm5hlXFrxkr8fV2G=%KLDE+BI`;tDxC*Wg_fy=>)q3nTz zQ?0+-4?$nprn?F?@NCB^uotrb1Ihn?8F|+K2O~eNJe~YPVX)teU0N2-RJhR0A`bq> zW1kYF>0;Vl;8}Zn?E6vVD_8a+tw~YRxd`~SG2O}-TzBCSvx?K4Xy8O@Po%6MIp@7|^Ts7rB22>2ypUiZFA4CmV z8%(TGHU&SL|7Y`7-)oV#R=H8d+PQ#osFBVs(giP_Yjg^W_o5{+{?}H>zYZ_e2Dp3~ zOccCYV_86&7vq|h{mVbgo%Im)7UPid6Hj}gSQ;e(?x%_AKDy{=SAU1&aa|idR8IxD z_7u4_-CE$I8xB|+A%z>y$_C(oVm+N4y97*+*3bVPW0@>q}lz}1?D1g;;{8uDY&<3oOa{AWuobT z9PLp;UCa}_mQAzRaG=Hx)Z6?pI)uy6Z!BqYbxljcTMY>J>z%-^+W=OP6Sqh{7c%Er zo}s&-kZW(C)?n|pv?yHI%@@n%V)PpLjw&F zxD{?SZ*aw-xIj20_3GSN1Eh(4+< zR>1cUX_gdm{oaGCQa!ky8_$2`+JbXB?_3`suQdvD-)LNcYtmvOV)^ zyPd*VZmhNedN|UAyc_KC(Kv4qCjSp3*kL-1E|sh(+POZ@=2x? z{+AE!);-I7Mz*{XxIP&qJ^em5IsKyRFDa!)9$ONAF66gn-5Xc(PKng)^F^#X3j9OM zO1*?7m(uODLs%d&FKJwlg-F)2cUEAz>7qf1UkR88+sX-6`o-h<$=9}VRDLlr-rU00+d~esxO!=HoG|x zQEB&Np9ue$7$@i&%sJHzB>oQ$f0D;RFwPY?iAU7jLva+T+$WafWZ(lkDlcpp2FMPggtd&xYRKc; zD!8EzbCbJnZbi{ex<9jg$U2<8r>AR;7;otM8wa0dCwaSqkg!% zzM<0NGL+M;76h!#I|Vg89vRb{Ki1#KGky*6#i&TI`h6X`5)@ro!k2EVqQTXI|b9f2=ufUcxQ@=w*<1qGQE&7^&Oa z+SVB0gn8JD{l@j!$&oL19=9qBqeKu|&dhv#9j4#<%M3UQmM8Cr6>I)+d$c|7E*DVX zR^t7B?bA~oeOndf!YZGSPN|yxJ$>sXY+V)y(ItAt<^hW5Nu+!1t3Z`wHvN&`?six2 z=(*HLK~DCQ%+gLZz`YNTvTZ8j?q$S}IHXpA;GE+TIbZ&Ad@y%%3AgzYEV(i;-1|oZ zQEqi+CH8w}NM9cp;NwpDwEUJ@xwn1dwrBI%<;wC)aEgugoF@MTol(Q_KD|0t`O62R z3oX0$eao$5-S2xzE9x1fG=e%7TwM-C^gQ0y%rbJI&62k6O`>#zKVaD#r6C=+SLQbn z;2$yj#FxD@QPod2y9f1%`7LHk7Sc5BMUqx2*c_6NE3u9cX<3T;1+4ZemY3oa0is6v z!9Zj7Fi=zbOY+@?K{4%HhATX9*iI_83+AuTEr#`1n*DY^$-|$-$tnMDPVPuZO2XZ| z>_WK_#S*xsxr?MhXK<}8-o%5&uDqTthnygxXQC=C-%fvcqjIJbhME2qvGY1o8=I15 z`t899jY5$1q@RAIArq@B;r4dve_PnQ{?o!vC7%mcgANmPIgEe=D(x~lANRuw7{04I zF{38R^qaSNOel^Sn#x}kYg`l(kVpX57xKI!HZ8;Lu9rDjCF|#o2>|I4tw$4olK{(= zamX7L?w+@szV+T?UJ&mJxNhIv^`+t(v{RQBFKU*S|Kv`IL1R-{zH&+K|K!e*<9h=4 z!4C)?k{l#GJBotSnobGffy!OlHbCw%7t}hE^%yj)eY=7?@YNvR<%OVM-PvG z?IWGUn0-G;loO*}*Un#es*&cp`Hmm~(iB$+l?FTe>}u?h9TlIY1LmrP1T z4d{WGNIWrpcA_IGA?8i07#qZ8SLt;Kq^jjob&PiHt=UcNWb}kx4W~BTZ~pyqj`sVE zvUPio(OltQXg29vd8cbn8Ngi8cZYa4Cljvy?pbfJYE5nsIbpR4v47@D5Dl8XkwQA9 zkQ1>|KJD$C@Z@QY;TSElvDst&B-xc25zhMg{h#V5s@UA)*~NZ{n-2Aaf0tMQxlVHO zTtM8?ernwow0Cf~88VOv2Siisaa^jDFItd8+{WXzp{Z0}+Os{#btolY(=goH5GO#b zrgF`=g7Rqpv~n<9c!q_HRz~EO;M=38lGgpMy0vr4N*ol@VJXGPg2md`5b`vQ&*ak5 zIN3%u-jOd7X?KH$8uwnXKmE3-(fcdGfXf{aOTDclW!tQT|3$U{7pwCG`@?X8C#zfB zeda*Ymc)L_R=Lr-2m}dO%?)LpQx?oWet4&}3VdW2`|GRxSz`^8!O5OIEiflnHORpv z_aX%=gEVl5{yrT zWhu>egY1+dUR>;GU#czd7=L77n)hx2)KYA+jYa>O;nTq?N;Vze8tLN zjT|fP3!KNJqd;}^Mr87tS4VKtUDxJlXq7c&%L(fvvVy>f^&~o1@Uu7tEN|`xF+B2O)Fu{5)ydkCVzzFo=qanm z%d4nj40rZ_!;+gBBweFu{9<|*B4}Vmde{HFJ?L1cfI5Q=TL-edebsaOx#M1y-eZvW zp98?I*e@2ov`(C`HHyYPpm98s#MF1cta+7>3czrM-mW)!T80Y^^ia6HN7}o#;Ga== zaQtURlnNP%84#mN=tCeZxe}bDHtOuVbVikM4)1vsLK^DJUK%JNZR91A_D!i;GHcr9 zg@jHs+C`&ZUFEHUmS+=jP)+44;;dD{K986)af>zJLNr`K3ORQv?Pw%s?UKn!@`tdN zLsOyYt$U7Kx#T&>>r`+rXw+Q@49@bLTv#5E|9HE1Bs6G*r*#3~!eL}(8c-Yk(jQL4 zC8Clo9g@xZp_(7G2@+1FPT;Cae3jA|jYi(oW3#65_We|kmP6birO-E#M-rw3E+02C zfwrc*MxgG@eW%00Js;F_=xde{-ms**J~Ay@J|cv^(}#UR`^ju23^G2W2~SxXE(S3H zoZ(2$XI1o;vc)c@|4&oz9nEI^zyEh2HA)d;Q!6n_sS5MsS(K<*S}SHyJFQXUclZ7Nyuau7UrtW)M{@4_+^^^Jx~|8iwmMzhaF|>& ziPgXnor;P4%P^%iwDgHPqJ}N5vsgqL9NWQ6Z*QBI_Y|Bq zPl}6^x4^8av1Z_6`TIT=*zhTpNgm$2!5QK1aA(YEA>00?tmGXCq2GHOsic->Qr+Bu zR*|Q7!V$DEN{z(7jvx4~*!#r&_4vPGztBjAFpGw84}eZH7k41ouha~_=bi{FYYfxY zN&)Gfk|LAQb66!68&cl`{Snl#CVj3hlIG6HYI#ZT%K?PD;zX9ya6dsGt(5WO)u?V} zK2+a0l_WG;vGZ)blu5u0zCgsVczBVCxC?QgG?}`>7A)tDlnP#iN%2>|1|V2WaHYx{ zRGUHByFTaxbVai@W=kM)>9!?{z3*tm!{6B`0 zt(^-9mDAkHiMQK!Vp<)Vw6<=zXa6;v)qiSm*r5~9O|H%Q7e$BUd$Y=Cwe7+`@%|g^ z_v_%Q^u_{wB8r8TDtIiA%C;>cc`cat(1crea8DgPB2j3#-o} zTqJ+)cgV{oy^)MA*8jNsS!m`Eo~ABCFlx`J?7fkL;yXX7tDU2``;n;L3e_QZ03($( zwMAg3Dz3#wzP%8jz9aup-+BMl#7F1_uAZvN9EX{BiC_crt4!q?Zk6Ou|6fb||BIpj zbHJ}?R*qyD>OYD}avQnAe8O^69X|V2%f|varCFbH<@19%fJHm;w!VUf%Wy*plJ_}7 z|3V9kiJrQ!xgO}hkHb)a4wLUrw84^nR*@z`jPQ@g3pep6@L_1VL0rxu&D^@=3KT(}IvAb+iGm7X8 z+ZTpODV4bkLTSD)^ojtyDTyS9Pe&RyKoU$&E}Bwt;kp$jKA9T#`ewfuhUai7k` zG^WKqZd*j2WD_NGe0G3M_$w6#WY}PQk!W#GH){Vzm0pwl-%?_kU?5S!e-?}S^v?)k zv2@o`IENP2Tf^G_F0kE9D042VUX_cx+rU$Zix$fjq+oh5aQC|qrv^q0_ran?KC74O z0ZOVFi`Bl)_&EPfH;c!-LDrQPhdbQ1T-`@mAGxQ!^&A-qELcMhaL<)b>kL{tvgCjyZ9O%=e2VZa@PYma*35HpI>}SGl`IW^6&nR zojLn;EvVs?0chn?>O7AIe-3a|T`GKrCV-%G8Rzs*vTd_j*?;lM&zS`w04w``mJ*(8 zEo>CpPXf44PJY~Oy$NeHXF3B`7RrhDux&7ATNv>qB96ZCjM+V??Lp_CAHfH>prQSl zH)frN3Ua*(4<1U>*$^ zaTzQTYIMi;&1np+fo`WA0qQ%TQ9UnuhS{}rl@ngrJqeLh3VF6ehYuk@)<_GhGp8in zkdilG@;(rKuMU2AOzYUiz#4PQt6J9IEYkiPx=4ZW|JT@Cb_qf!4}}cXU+z3~OU+42 z>)3qS#=l12BJWogsKdw@=2qj~2dV^ZSNKEoqxLbRi1K2~@V!_}Y{(a683f!7_=b!n z%}c|9@Gnwz6DxA8mxEIA_tR+d-)kuCUMdaJ8?WEbuCYaZvH1|*!Y-bsxE!aHKjILTSV=m@t5 ze9+I>0V`(_NY1pW183*HB2&-yidGh~nESN7FGd3&;qtC?ZIt9_`yrHtXKcife#4W= z$5G_jY)=2Zw*8)9G~mqfJDfvlb@A!n*y%U;6*~P)Of8$Xm-_kO)jyerQ7-wV76lt5 zB*y;{MuZHq*x>u1j=v{-b~Y3jw-4Rozr%o~jdP<`E1J+IC}o?!^<${xER?^%E6ftK z_&;NTli1weLfV``r%uU4rU{j;Y(Q6Ws7_MacZKe88%xv9$NP5OcgfvW_qCalifYPY zodUSyi<0q=Fbx)-bB?)1?zf$3!P828tN@2Hg=rtVY!Pko!IynpJL9F+ugq+ZNZGldn%J#c<|){6zw& za5Kl8BVixU`g8&i`{JdRSOW}Tn)yS&y7NIG$^AgyMgvHni>0u&?l!>;k(GiG+M%POeG(*l zyI@t3nl<3?kzB|Qc#;SHJ{;A$1HP$`abh#1;W~|cAEi%jx6;FUJ#al{58&oD;RQlXIl?K*qjG`l>IXss;R-Z7^(1tqtiuf8FM=%2_yTCt{Jk;Y%!~Jku$rup_QPs(mDP-I>ZuVvx8m7^ zUqvTVF2z$usaB=Z3mP-&y&W7EQ0QxQ`U*QTp%v5E6)483?bU7NBzndMuy)*4wd#Hw zC*8zGdQ{{QX7=SYjhCMtrt%)qHr)`Wo~;Y_mGAArge;$)6-W%DZ!@sU_n`!xA-ULw zuhcs170De9-cFgLq0*1m$`&W45qe{4KCveRtLW9w6}snF3a%h!0+|qv`!z-Ne_pL( zd0lTg#y#8`P*qSiI-Mu`EXwFk;+_x(7Q%e?3<-bG#-%7f@B@*Xj4WZPp#;Im%+g^O zQ7x4`Jg9iS1nF9C6L1D;V>e7ca$5&-4ty#dr9v810PsIb)^d|wf*NsadOG-l zD?!L~=xuyN2zv9^(bR|%jo8h0BN|C@IFC${?}ptp>1-aQ)&0!m?c#Ge;jcRZlpP;x z+_P)qHu|cyjemO-Jx|CZ1X{QxJlg3WDHDF$FTqO`A9 zWF`uf?#~>bAT$c8^=I#V!YupOc#P(cx$Zmv0!>%3X|CvlrH^+K4JfOA*neE6GcrEm z(=eiM+U@vM|9eg&>Q$7d{xdB9KAF`tfs+mS-oMdI`%_9s@t~jAFHQ#w@+va=DQgoOXh9z#IQ_|5LWx zU-^u%1M9SP;Op=|no%afYqnlq_lbE$hN-*aOX2m*&VdQ88z>1IfIpHicb5=mvXYXr z`3+dUUC0lUpIZQ%?DZ`M4ST&}K2fv}*0&mGaov1hkt$SSlPR#rPTAo)p<$=GS#U3u z*vyi*(T6`gA&l)PF-AOS-U%J0%+95L9mM+-P}%+YqiJl$ZTRM_jg%wPwWy4m#i2Qn z#1GyFzf2$6<+43x#ZFRB?$j8n2rDY!sF$q5Ob+^eB1<$LEiJJ#1TuZ2+@Pk4S-5`n zhK+y37hPH}$21jrW5m#9(io$W3qERPY&=2{cfnO7Ef+p#N@tj~Qulivbq5-O^el_* zNOjWlA_;2n7?%2kL0K(B;bQu7XB8&SIRB2mm1bM0YnIF@76^s*rCiAXJCQmzi7I!| z&cPdT%nx-iD1ie|x)b4=X{7Tz8>S{{?}K(|{SPpKGDqPwvMfus$noj%ZO;lhiD4aQ<6iEwGM|Jyo(|ZX{BS5JOHQU1m!czjuQs2R*mXPCRmWshp*K zm;!>nme|d5x%#|_TjaZ_tT>9zJGh$o;m&%oxh0um=v|5xT8g!ZI?tVfo%Am4-ZW+s z$8&f)el_8e9Q#N5)o(Eg^w8Ca4Fe|IG;|HnaiNZbJsh5-7U;?l#z!ygi!QduY*h*x z;aMK1T}kc25cQnQ#TF|BprU)JRo7Tfo!Ur($nNre3hoCnDF3Q(3u>$@@&U&-=kuF? z6c_FYT9^wVYko!RvUR_SPRCEWkJPjkhiWjWht`$wYs|o)5FX6>O7S?)u3ty5y0BP0 zRpH6isz$`4f8m$tT?o<)zu0)czAbgIv6~n7nA|fvUTj%2gR)DCjS5-ha;ZLdV&h(l z)a*WoB59p&4v7S~U~fcoxu2>ojE$GA&sr+>)6xi3+DkG1K5YM&NvD2rLK;aK-ON*k zn^X7lWOShkD@$oSiKy6zI#Gc6-NSX9Hs@fobM%8%7sMv+Rm#Z7k~~H)#|F!mZZ>sM z?A}@tZkw*7@4KIHU=I5Dx_*?^&tcN~wo@W=7_+_@}oc4t-XhGBqA>riLPJWdDfw>HLvfhXNq*sWNg}ugS3i z%nL;z?CIwcyZ`9zBBM~TNtOnGoq#x_n|j`r%rMILjFHAJgchO6j^$`?r|V6JS`4P8 zhTt37=8-v*6$ux-s$Xag&%B>$BHp&8lqZ@S{aw2m_jsQpM04STZ&C|Dfwuz*0~Oj1 z`rs7Z>drhgZOie_I#7s9T2dk#&e9kPc4O!FB78J?c3&3r*fJGel(CbKFeoduc1skY zQO+H8F``KxRa5}{@Jiwi4;c{_u|SW{nmz+Vh%mpXwq&a}CxgbwR9vlXkPjnEXCJTK zz5mnMBjq9wgh%D|lS8KN>_Re_Sn|OiqH`@<9g%!A7Ojw#fe&yWFGL?s3~TdK2QV!snB`=n zs4BBj^nzeJv7haF!C2z2h|Q^_U+#3d)WCW4rTEQN_tZfadM#Jci_q0~_n0oPMhL*< zg-mEodyL`yY-*M*Jo3KLV=bD=J=YkR=L=cuhTqN)2+nhXi`HTB45UB zk&=$3i_K;C?U;QJU+BjV50e~x6ukU4h7E1Ryq(g=zgcl-^<$l-$N2`zq-z_z_lUlG zKX8W;hT12Nxx8;Ku+!$LuDt7mMcr0l%FJW7!||oGfE(bO3cew;fABSnjB}3o-Dh%N zkg7Z4%kM;SA-|TR@>eHu&O5Mm`jmT*FakJC^Oaq9XD{Iz%-=kF|JsR@1c>WzWl~)z z)9At-yc(k!4OUK0GsvEBiSvP2Y?ji~jj7xEKB*&+$?PUa4{$VN8`~38C@d-4A5WZ# zL7FbOxEmHv%x%#R8K>!e@4ZKU=4bhKna2)I|4A9W_1R9yxm+-$#pU)sXUKVO3IcMz z6Hx*hClZCHBX=6TJwE&fXmXOOP25`qI=eJ6=sqJi_Keo}AevrPY8wPCHc0|<-rHSy zbdXM^Nez4bzr52b$^cKEp-i;)0OWnf(0%0T_N|-98=|@Yq4b{!KRo(m?gH_S@94fD z;6Q=gfsVSawg;H?{xvPd>$dZs?XvpHzOYe!0J7&}uUBeLdW4En{dTI{c-<9tEb|yg z+QBZc4+BJ&RzB?-?Yq5LQ4#eG>Hf|p5Ving8Sp3m=M;$twK8;pLb-o11=(T|Wj~W|eB$R*cEXM9S5nrw)GIL6#&#!f2k! zNBplOn1O0i$ndtV^b_Yp4HT~T>ffG)9D9AlDd&5xRnW&--z?~|dN@4e+Px?|mIATs zxXplMIQHQFydUfIxMdEPn!Fb4=8v;tmtZk^^x@wr%*L~6Gda*`g!>D{> zMGk!d<3!Y_Bj&+1XBGvlyt;R2r`YgV2P0CLS*My;$r~f;%RLTbaPosiynnTmlJbV6 zDn;$4-XQ|aKWIIjI@VWvgaCt$mlILg)N}4%Pe!e4uC`sTto7%=6V`kyEoC)_*29@- z#w)RB%2c1@`31d;i*?MH&kyV5yll-LvS9a?ZctuKwA*7{f2|1X6{3B0LHI}I=fHH! zZ#3Mg z!;Lc8n9hLD{@Bn*&Q&Sn3nvS`p1m=~S%pnn>HNrdtlK~YWyOWX44eX_U z3sl5jV2&@J^B0p{oeHkbCvx^x<{W9A#}FPH8G>U5e?&=SHGw5;(F)Tv7Xd5xO})?9 zzDCAQgFbrf3J^7PXrUqW^PT3`ZLL_GLJ0gP>Jr1iaPh-Nxn~rEP(3nRqa)wGcM~X6 z$-2KQtt^+bZH(kZzw`@m&KLJ+a0ifAJIvL7H~YhAgP45Ge>8L6zcoyZ zsCetfjZ@p_-w)Ga3^b1V-VU^-S2_gkjs2%BJwT#S1ZYct;V4e|u3W6s=`|IHByQcY zuF(AEXy54NFSrm45tA%ol-jgoE;|(KCvnoR%dQBc+|+iSgb+RzJ*6nYGGzyrNZ}L% znFUVkcnC34zTtAJ41L&c<~UIGw))MGX1S+vwOlv#2i%HdjO3UbO`uMZineDb z+P=>0c3lXuGFy^|n|0i64q3rH#hbSKv`?fVbvbNN*WSj>TxBq}5YzA0q^|!0%>RhQ z4}7b1b^(Rrf8+l}*s-tGFoy-4K!!apeNzkO?@n;Qgcmp@Um$~G@9$m75_f2m7mxK` z*6O2Xy3pAjUHfKVK0u`K8%aeGFXo{JHL_5l=~bjoaD}U+D!K;yb*H=)Z--_0>^4i= zN<`(TO|as@YljU10)BNyjNqj@IjE1=aFhu|$Y!l5^cP$ntI`Ozy+j>)Utan*u$(FF ztYCY!Yl<1^Jdde{Bz`Y|R=+WGd`5aC^kxih%#8(amHr}Er5X;w&aX}gtwM_=vRLy$e9BpVcsEuMY9cQ?zV^Bhz+kpe8seJ0B~FG+lHr&}X@Xg87EQbmdFS5E)%A~>9=+AUb3GEzbs2I&ojAT zMF(|wphbU9W4iUzUc*9QFw(%G;m4Rk(!xW^N@K?pEZ1PtHwHg&##X_auVZ${0lLMG=SEFU;x6@Jf;fXejjWGeYoq6X} z(IT}lY9ma?Xno#Yg364CD{6nV;G4mt?6vvq?1$I)nqNBRrl`Qolkjf@=do#isrxc9 z^D>k*2gczk`!9hQsM4%-pD`8E#ZrvIs*tu49p8%b?*Mv0-r*6Y2628e%~~_b{xoJ5 zTXD0^J-3t)vFl4EprVKW72<7A`|}fPf1@k9#k>hz554Yk#HcjhWYtHG477PSZ{`_x z);7%tE*D3&%4fph7T5{MEghuUP7m`qNu9bt(}?cC{f$$l6$dgKCffjiu@)W#2gTRV zIeFu6YdcG-?qYQH&6CpI2ld_&@4!G7nfHcQ1VkQODuHFB3+VEq6P&_Ve)r{@k}JAX zl>G^>-8Md#FdN0@Yqg=*JtFqVCWusl3wZ$iJ>}l<(#j1-Y*L?qBq5Y&YSSF#zthq7 zn<*@ri^_l1i$k-WSP>Iyy~hzHW!6au0GT^ zoTcsJ`zdC@VQK`x=<4KyDhJbc8P2O8X1!leJ21ESNb72K5-?X&CP!uC-_bm@vXs|+ ztDAZe(BKa`WJZpmI(b*3p}l}vV*XO!tZebf zERl4)n1G)wJVV6#I#<9Nf5+#>+LF3F&2C`d;#TrFUUFN`SL%Un1$VZJev$4sPlD_wzc!Yh>1Q zF6_B?goIKo-_0Oj7pD4@55vT$+?F#FuOy;ug z-ppzujY(?lBG!)KI`zHg{_v|pcaNiLqkk4)SLIg4OB=*gzt#e^P(rL%3JmvN670m8 z`=YuA8^7!q_UQ|Ux)l~AkqI*jx~h(vcn~tiY~4?I`r&m2We*k9CE$7FvoEB6xG8Vq zo%?|TibgyP_*Mu_$LsR;UW5s}mmN9<65gNqpAqw$`Q;f-{ZvpscH@6R=RK46^x6T6W>}^yxQy&igG^Hv`bG_0+b%;*30Y_+nld`|hDQ zHtgO0)F?{=e(9KiBZOH^JV;`#=SvA4-Yb%Z@C@N`^zzctV$tcT3aRUiHHoi3;()q{ zm%Ib7c?AE*hX1F>xBUyg|53p{N0$uKn#>dazHlRhiWZFbv;nU@kBhNR$Tf4Mf=$D(0k)F$oM8FbW@vl`?HQk=MZY4TC~z7u_J6T@JlnMH z7Ibf@md#d+@|(3(8rbR4={yj9H}=+tXtCy}5g`Q<)ef^6{>WJxY!+C4F5oG$PWgoV zy-%++RYXJ&I8vuR3b#`5lE){~+R}05t0sOkf3w>LAmQKr4+%fkGR~KPdqxJjG5{&Q zN(sO-1Tem-uqmIbF63vpYFs}Y-|{AGz`FX7Jc^oq5vw}9qR+6LveDnzKE?A~DS0L9 zVe_6TvmnVZItm@y}F`JJFG8mMekOx$77vuAj&kG`t#Va&8Eq(U6m9+huA! zoA@T5pnbauC2}?)SfuMD%QVr@t2!wl4;j1AgSScx`6j>5`Cwl z^1^}#%A>QYKZ54Q$r0s{j)wZLUxzIG;Ca*@=J?{QKP{{D?3XI8)$}Od0ubP1yXRv2 z2~-zGrl==rkF>)-76qu%&c>>|#V_+V;Gr*9=N)rFje@bdVWtm@*mjP%Y)TngQe(&T1-f}u!CynWwH?TqtY~elT6tfM6lq(5YuvrBO=iJvj(be!%IE@0o z8}c<0+oPpoQ3Zdmt3&V6?_W9`-x=}NQ%lFt?zRp7C)zu$*wo58FW}tzqQrFL;5g6g z+uNC{-1QDCgVU!p z1)V*wr(WLG|Me|bFr~u3|zGkva4% z`-uhFT3vP5{x_)7F%J7_9U^EwzDEZn>kAf_Hh}>QCW+%N_(^f8^?_d|?Yza-Dd~)* zBw>}Z&;+}P*Cd=%Js7$r`zvT*rUKnCcQv?~lVv&bB=?$MeA{E6z;I3I5&Uv+R85oHhWx?OuIV#`N5q_6U6q6 z{=2VKP9WeL^-CCFZG6oA7f#QX+zg{rzaSSuNIQESWvoQ0!( zm7tX{2qtRjzae=4RVL1yCw|D^=wr04e%wxL2ra1H zI^_?}t^ic}v0^RNM4l?S!1~7X>~@hsor_}n!)EV2a1}HCXHTWGf zmt7zUe`D0Mn(3(LS4aUZJc@2>N=HLQ;6 z$+_6jAQl@0hCC)X6kN^T#5!+vY;0~xJiYp|wW0UrmS1g`mXAavwvU-=nQuzz^Hc@s zY3PLB8rwsq+||W_L~s4l5u#%9MF!`Wg8&O%%5!7o&Na~TW;hXaI&f1^;Y6$10Gd8E z@QkmPK?o;yvJK;3;M0G)({CLyf?b#`={eqi&1KWPYg6Cs5uc=DpTr(TQ0@>4j>6|+ z5Jj&|&pz20aUpEm4|3>*&RQ+vmqt;-MCzKAsF6YOz?<1z7omSW?z}D3TKM?J88P-S z_OltW>*HL1yV;-U#RXOTEkC6?*;iwX+_rC;;_^6inPVchL>JLFkmWs7o7mrOC#?6l z;1T{H<`UYI$Hxck8DzTbT!eK?lkMofZ~4FQGu z8jM-sI4g{hUvE~h7wcS9xfj!s+VUZB?n1p!qe^WWfhykswPho3Q@h) z&^~qH0s}@*OWkzhnu??n0Xq!+zF^TZdS4NldJn7fk^VfU%tA3U4c!#D8e?7^SN^{^ zyyNbLIv=2}U8i8YQ~sH+1jke`eR`tcXTKr7gr?or|BCfg7o{gtpiBK?JbO&1m2ml8 zPI-jBcke2vMM6yEqZRr#ymHoQ+Q5FcE~FLz$Nw}~2g^Ws#gQ5?I*>7F?dm?aoc8t0 z-Wy{OEe!coOXV1-JPfMc+5_32YGKj$rvv@l_=mzK84u){Nf(QT#avF8gc|;7^)DxB z4ch+Y;nmB=#u=2je`u}@1|4b_weCA=EVsV=wFZL3k|X!3@$Y`tHh@NG1E{=GA2u;H z*>GbM<_7yg; zY*;sXO@;OG9Ny_ES@8H445`FX4__>DNW9>pY{b>AOrsn>cL)Q0oPMFDF9ZE)Bd;y@ zL}`(d*0m(ogbubh+~`qaL{nDbC+M+I%4dxdv5g(^cM1GIBMh|CB~TY>-ByJ5Nj?oltivl{9l*mnuJyZ$@P;1Ao(P?kl$31X1ujqCN!PpRj-Fqu0o zICQ^5p43jSQN%u3>12R|Qnjb!kg_f|@~}K{S}Q3pPV>}kMT^>W%IbFXb2`}|NAD32HTl_o>wkLFq|HhA~wXORZw|+bwct@&O3lp&8b@WA_z(U~v83(wifUDrPGz5E&<}Oy|$#{ID5`ki$vra2jY!hFgh-C89P1q1uGqX+`@oe&`6v*a$NjsZ~UE z49I>*sLH#O$6uYgDZ4Um&;oz=27g=Rg9MGj_n|J`!_pQNr9978t2_uLDF-_X6@7!! zaZRm$E$Cg0)Hp1G9?~03Vb)u-B?ZYh%G94WOk^yRF86di$?~eKCW_a#fTj zUjWXiiKS?mZEy<0KOxK@s9z%<9OAsGD+_GWEp5r5phfA0mOwo>0kgVs59sFuC zJvJ^(dZV13dvPQyl9ZgDV3e(o1eacuz2_&}U{NEx+M4UYD8-45NRDPiBIZhV(93Oq zZ?M=45a!6YuJ&zEF^`vA>S*d`{5%)MUivry+r@^Q?PlMrhEf2f@SeO1%<}mewX`Ek z;0^6ln1!8ndSYC*fzTRW4mbPlvv=Y&9Z4f;;Ht*zF9r|VjNzZ)SD^itVi2^=FDliN z36Vr$=UX(HZ6Se2it@Ih=YDUW^~vgv2&@8uchbDay(?RZ?Z+YB9?jhnbzNIB?_;r1 zac{RjhhX!+gjEa&CF$dlO>k5)p6S{q@I$6`&Q(&F@pYJy-qL5)05jR8l5 zWm6S>ymC`8tg(Pe^|4b+`|FowPqxVO{xm{?kE;Dluiqkl5aQrgvr@Py&6h@rar=rB zeHjN_FCTne5bPn2%+6__v#ujq4OQ+vW`*2{*D)Q-N`KGyo7|a2e7L;TH7sX`jcCg% zQ>=Rc@YfL*91JHEMg0(H?aMzm&3l-5*fQD&85_L=7wF1vj`YP9H&w}@KAb%v?8hWv z$=%#(jTSLhkD5B1#Ia%(rIG~WhrID~Cns{ByLtop+IbI6Ifkxga$PB@YphfaNIj*0 z)$Ieg?ha~QXZ)XHQZLUCC(a4j&4P4~*R=GvS^uuio)Kow2lN@1*q12_IShA}tn0l2 zQ+&RGAu=lJY~E6c@4&b$MY79l$D`wl!!7sVLk3F>k7_n#3!0pYNWI8qsGwHWdI;Am zERtB;(T&?+_%gupz#jzd++qId$!G_*<26E&5-a3f(+;P)Sm4v@e{W;0+DRYZ81P!6 z^jiTOq-^{K0Fljn9r6REim+@FYZ|S)93}CTLg-=x^GrjL8M}~?nL{Noh~uJ={hSAa zLx}XhFN#bt%ER1&cOR8yzxcw8H+t&jn+CmX`QBstG`Fj^QS{*P*aBVfs<|7u$Vnom zDLM8e_nEkm42}=NK*pL7VZrO1Tdq_F_!V!)6XG<>{&Y-Gmq4}<_)fCTK+`k9C^ckN z9116tb-3^p_6hD8Fd*3lU}-efolEc1PeA z5Ou%FQv?+idji%u3PF+X=PBv2nBHuT0uB1?4=5bL)Jx_1h-N40)Te5nz!h4jp2DAK z2p{HB_kyY$u(OSr^#$FlD;n5yQ}OoJ>*Z@k&3lUaE*rDl>ow25K4j>VXv(^mEk4!W z{X(N?ekY>4MYia-#x1{#@Ip1j(USR_u>qnLe^^pn6!HRPmJ)+U#07TPWgu+?(vMYA z9n5kM+iMX&hk=-+w+&=)V^I}<@`u%ZN^@{>`2LAK>}cH9Z(a%T#i{(kBbApi+Y}D< zoeO+{#4G$lnka)6o4wEaD;Lt`1T&t!%(B`t2@x%W)3{1lj`1%Dsr%LEKVB>FXjlwQ zVR64&nerXhPV@tVXl`A1*nD}_$0A!#H613Q;PY(5puN^5sINf-O54!rD~6a5)?_SJ zJV06zvE+nnn|3xKI;ORkD3b>i2Er5dXzkbFiFm`Ky}YWAxv` zLBknfQ$mda4r6iOe&FIN_wHU|lFl+>Y#e@ojk1o)N4JN~J$-lgXX7MSEPp`zw;H9I z5r@EQmfb971M;YFCshklM90IINQAf13=L~5wa?YJ?_uxgOB+}|l)0q>Kl!8M@cX(~ zlEtei^+0rp0twGxPYN{p?!?#Gk@cg0C7cXwgi)hj1kwFc&m>%0)BIs&zgW>$9)l`2 zDgN$96FuYXGtJ$7Tk(K=ah{=_e~rQ8^6&eb|IOyZh6h)z&ZC$ZY`M;ee5#}Bn5Nq< zTgK899GH5#(;EjozeqdwfWgNVewu64IeDt}5IhWBy_^}qYxsR8MX&97t-C?C>si6B zFPYfW)GQxYOTe#o*e1|>K8=zv!oD}wD0rMnsCQ}W89HCN=FVUZ0jI(AL{OHN| zEHy$#2!bB7IkQ!XmA93mi{-5_rK7heWxwy8023D&V7yK)x$hMvoS|DV|sN#yi=-gB|A66L?F*C#};HI>}>CGKy8S zKW5MAUoIXtY_{Sm1wq%7nj57zw{O;us8a$#y8I1=?)DP@#f4J&at18FNLNt&s_NaO zg@f(*FGE!K02+lyCIB9dm}Z`tO%ne>vy{&88%+@)nrkSIz~1+h$x7sP_WwR%Tive< z_yg+QvzSWW@hrcX7U|cHm`m)6PozA1VZbkHTP113G(()=>{var n={2543:function(n,t,r){var e; +!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.lodash=t():n.lodash=t()}(this,(()=>(()=>{var n={2543(n,t,r){var e; /** * @license * Lodash @@ -6,4 +6,4 @@ * Released under MIT license * Based on Underscore.js 1.8.3 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */n=r.nmd(n),function(){var u,i="Expected a function",o="__lodash_hash_undefined__",f="__lodash_placeholder__",a=16,c=32,l=64,s=128,h=256,p=1/0,v=9007199254740991,_=NaN,g=4294967295,y=[["ary",s],["bind",1],["bindKey",2],["curry",8],["curryRight",a],["flip",512],["partial",c],["partialRight",l],["rearg",h]],d="[object Arguments]",b="[object Array]",w="[object Boolean]",m="[object Date]",x="[object Error]",j="[object Function]",A="[object GeneratorFunction]",k="[object Map]",O="[object Number]",I="[object Object]",R="[object Promise]",z="[object RegExp]",E="[object Set]",S="[object String]",W="[object Symbol]",L="[object WeakMap]",C="[object ArrayBuffer]",T="[object DataView]",U="[object Float32Array]",B="[object Float64Array]",$="[object Int8Array]",D="[object Int16Array]",F="[object Int32Array]",M="[object Uint8Array]",N="[object Uint8ClampedArray]",P="[object Uint16Array]",q="[object Uint32Array]",Z=/\b__p \+= '';/g,K=/\b(__p \+=) '' \+/g,V=/(__e\(.*?\)|\b__t\)) \+\n'';/g,G=/&(?:amp|lt|gt|quot|#39);/g,H=/[&<>"']/g,J=RegExp(G.source),Y=RegExp(H.source),Q=/<%-([\s\S]+?)%>/g,X=/<%([\s\S]+?)%>/g,nn=/<%=([\s\S]+?)%>/g,tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,rn=/^\w*$/,en=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,un=/[\\^$.*+?()[\]{}|]/g,on=RegExp(un.source),fn=/^\s+/,an=/\s/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,ln=/\{\n\/\* \[wrapped with (.+)\] \*/,sn=/,? & /,hn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,pn=/[()=,{}\[\]\/\s]/,vn=/\\(\\)?/g,_n=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,gn=/\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,dn=/^0b[01]+$/i,bn=/^\[object .+?Constructor\]$/,wn=/^0o[0-7]+$/i,mn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,An=/['\n\r\u2028\u2029\\]/g,kn="\\ud800-\\udfff",On="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",In="\\u2700-\\u27bf",Rn="a-z\\xdf-\\xf6\\xf8-\\xff",zn="A-Z\\xc0-\\xd6\\xd8-\\xde",En="\\ufe0e\\ufe0f",Sn="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Wn="['’]",Ln="["+kn+"]",Cn="["+Sn+"]",Tn="["+On+"]",Un="\\d+",Bn="["+In+"]",$n="["+Rn+"]",Dn="[^"+kn+Sn+Un+In+Rn+zn+"]",Fn="\\ud83c[\\udffb-\\udfff]",Mn="[^"+kn+"]",Nn="(?:\\ud83c[\\udde6-\\uddff]){2}",Pn="[\\ud800-\\udbff][\\udc00-\\udfff]",qn="["+zn+"]",Zn="\\u200d",Kn="(?:"+$n+"|"+Dn+")",Vn="(?:"+qn+"|"+Dn+")",Gn="(?:['’](?:d|ll|m|re|s|t|ve))?",Hn="(?:['’](?:D|LL|M|RE|S|T|VE))?",Jn="(?:"+Tn+"|"+Fn+")"+"?",Yn="["+En+"]?",Qn=Yn+Jn+("(?:"+Zn+"(?:"+[Mn,Nn,Pn].join("|")+")"+Yn+Jn+")*"),Xn="(?:"+[Bn,Nn,Pn].join("|")+")"+Qn,nt="(?:"+[Mn+Tn+"?",Tn,Nn,Pn,Ln].join("|")+")",tt=RegExp(Wn,"g"),rt=RegExp(Tn,"g"),et=RegExp(Fn+"(?="+Fn+")|"+nt+Qn,"g"),ut=RegExp([qn+"?"+$n+"+"+Gn+"(?="+[Cn,qn,"$"].join("|")+")",Vn+"+"+Hn+"(?="+[Cn,qn+Kn,"$"].join("|")+")",qn+"?"+Kn+"+"+Gn,qn+"+"+Hn,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Un,Xn].join("|"),"g"),it=RegExp("["+Zn+kn+On+En+"]"),ot=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,ft=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],at=-1,ct={};ct[U]=ct[B]=ct[$]=ct[D]=ct[F]=ct[M]=ct[N]=ct[P]=ct[q]=!0,ct[d]=ct[b]=ct[C]=ct[w]=ct[T]=ct[m]=ct[x]=ct[j]=ct[k]=ct[O]=ct[I]=ct[z]=ct[E]=ct[S]=ct[L]=!1;var lt={};lt[d]=lt[b]=lt[C]=lt[T]=lt[w]=lt[m]=lt[U]=lt[B]=lt[$]=lt[D]=lt[F]=lt[k]=lt[O]=lt[I]=lt[z]=lt[E]=lt[S]=lt[W]=lt[M]=lt[N]=lt[P]=lt[q]=!0,lt[x]=lt[j]=lt[L]=!1;var st={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ht=parseFloat,pt=parseInt,vt="object"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,_t="object"==typeof self&&self&&self.Object===Object&&self,gt=vt||_t||Function("return this")(),yt=t&&!t.nodeType&&t,dt=yt&&n&&!n.nodeType&&n,bt=dt&&dt.exports===yt,wt=bt&&vt.process,mt=function(){try{var n=dt&&dt.require&&dt.require("util").types;return n||wt&&wt.binding&&wt.binding("util")}catch(n){}}(),xt=mt&&mt.isArrayBuffer,jt=mt&&mt.isDate,At=mt&&mt.isMap,kt=mt&&mt.isRegExp,Ot=mt&&mt.isSet,It=mt&&mt.isTypedArray;function Rt(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function zt(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function Tt(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function ur(n,t){for(var r=n.length;r--&&qt(t,n[r],0)>-1;);return r}var ir=Ht({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"}),or=Ht({"&":"&","<":"<",">":">",'"':""","'":"'"});function fr(n){return"\\"+st[n]}function ar(n){return it.test(n)}function cr(n){var t=-1,r=Array(n.size);return n.forEach((function(n,e){r[++t]=[e,n]})),r}function lr(n,t){return function(r){return n(t(r))}}function sr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r",""":'"',"'":"'"});var dr=function n(t){var r,e=(t=null==t?gt:dr.defaults(gt.Object(),t,dr.pick(gt,ft))).Array,an=t.Date,kn=t.Error,On=t.Function,In=t.Math,Rn=t.Object,zn=t.RegExp,En=t.String,Sn=t.TypeError,Wn=e.prototype,Ln=On.prototype,Cn=Rn.prototype,Tn=t["__core-js_shared__"],Un=Ln.toString,Bn=Cn.hasOwnProperty,$n=0,Dn=(r=/[^.]+$/.exec(Tn&&Tn.keys&&Tn.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"",Fn=Cn.toString,Mn=Un.call(Rn),Nn=gt._,Pn=zn("^"+Un.call(Bn).replace(un,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),qn=bt?t.Buffer:u,Zn=t.Symbol,Kn=t.Uint8Array,Vn=qn?qn.allocUnsafe:u,Gn=lr(Rn.getPrototypeOf,Rn),Hn=Rn.create,Jn=Cn.propertyIsEnumerable,Yn=Wn.splice,Qn=Zn?Zn.isConcatSpreadable:u,Xn=Zn?Zn.iterator:u,nt=Zn?Zn.toStringTag:u,et=function(){try{var n=hi(Rn,"defineProperty");return n({},"",{}),n}catch(n){}}(),it=t.clearTimeout!==gt.clearTimeout&&t.clearTimeout,st=an&&an.now!==gt.Date.now&&an.now,vt=t.setTimeout!==gt.setTimeout&&t.setTimeout,_t=In.ceil,yt=In.floor,dt=Rn.getOwnPropertySymbols,wt=qn?qn.isBuffer:u,mt=t.isFinite,Mt=Wn.join,Ht=lr(Rn.keys,Rn),br=In.max,wr=In.min,mr=an.now,xr=t.parseInt,jr=In.random,Ar=Wn.reverse,kr=hi(t,"DataView"),Or=hi(t,"Map"),Ir=hi(t,"Promise"),Rr=hi(t,"Set"),zr=hi(t,"WeakMap"),Er=hi(Rn,"create"),Sr=zr&&new zr,Wr={},Lr=$i(kr),Cr=$i(Or),Tr=$i(Ir),Ur=$i(Rr),Br=$i(zr),$r=Zn?Zn.prototype:u,Dr=$r?$r.valueOf:u,Fr=$r?$r.toString:u;function Mr(n){if(rf(n)&&!Zo(n)&&!(n instanceof Zr)){if(n instanceof qr)return n;if(Bn.call(n,"__wrapped__"))return Di(n)}return new qr(n)}var Nr=function(){function n(){}return function(t){if(!tf(t))return{};if(Hn)return Hn(t);n.prototype=t;var r=new n;return n.prototype=u,r}}();function Pr(){}function qr(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=u}function Zr(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=g,this.__views__=[]}function Kr(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function ce(n,t,r,e,i,o){var f,a=1&t,c=2&t,l=4&t;if(r&&(f=i?r(n,e,i,o):r(n)),f!==u)return f;if(!tf(n))return n;var s=Zo(n);if(s){if(f=function(n){var t=n.length,r=new n.constructor(t);t&&"string"==typeof n[0]&&Bn.call(n,"index")&&(r.index=n.index,r.input=n.input);return r}(n),!a)return Eu(n,f)}else{var h=_i(n),p=h==j||h==A;if(Ho(n))return Au(n,a);if(h==I||h==d||p&&!i){if(f=c||p?{}:yi(n),!a)return c?function(n,t){return Su(n,vi(n),t)}(n,function(n,t){return n&&Su(t,Cf(t),n)}(f,n)):function(n,t){return Su(n,pi(n),t)}(n,ie(f,n))}else{if(!lt[h])return i?n:{};f=function(n,t,r){var e=n.constructor;switch(t){case C:return ku(n);case w:case m:return new e(+n);case T:return function(n,t){var r=t?ku(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}(n,r);case U:case B:case $:case D:case F:case M:case N:case P:case q:return Ou(n,r);case k:return new e;case O:case S:return new e(n);case z:return function(n){var t=new n.constructor(n.source,gn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case E:return new e;case W:return u=n,Dr?Rn(Dr.call(u)):{}}var u}(n,h,a)}}o||(o=new Jr);var v=o.get(n);if(v)return v;o.set(n,f),af(n)?n.forEach((function(e){f.add(ce(e,t,r,e,n,o))})):ef(n)&&n.forEach((function(e,u){f.set(u,ce(e,t,r,u,n,o))}));var _=s?u:(l?c?ii:ui:c?Cf:Lf)(n);return Et(_||n,(function(e,u){_&&(e=n[u=e]),re(f,u,ce(e,t,r,u,n,o))})),f}function le(n,t,r){var e=r.length;if(null==n)return!e;for(n=Rn(n);e--;){var i=r[e],o=t[i],f=n[i];if(f===u&&!(i in n)||!o(f))return!1}return!0}function se(n,t,r){if("function"!=typeof n)throw new Sn(i);return Si((function(){n.apply(u,r)}),t)}function he(n,t,r,e){var u=-1,i=Ct,o=!0,f=n.length,a=[],c=t.length;if(!f)return a;r&&(t=Ut(t,nr(r))),e?(i=Tt,o=!1):t.length>=200&&(i=rr,o=!1,t=new Hr(t));n:for(;++u-1},Vr.prototype.set=function(n,t){var r=this.__data__,e=ee(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},Gr.prototype.clear=function(){this.size=0,this.__data__={hash:new Kr,map:new(Or||Vr),string:new Kr}},Gr.prototype.delete=function(n){var t=li(this,n).delete(n);return this.size-=t?1:0,t},Gr.prototype.get=function(n){return li(this,n).get(n)},Gr.prototype.has=function(n){return li(this,n).has(n)},Gr.prototype.set=function(n,t){var r=li(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Hr.prototype.add=Hr.prototype.push=function(n){return this.__data__.set(n,o),this},Hr.prototype.has=function(n){return this.__data__.has(n)},Jr.prototype.clear=function(){this.__data__=new Vr,this.size=0},Jr.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},Jr.prototype.get=function(n){return this.__data__.get(n)},Jr.prototype.has=function(n){return this.__data__.has(n)},Jr.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Vr){var e=r.__data__;if(!Or||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Gr(e)}return r.set(n,t),this.size=r.size,this};var pe=Cu(me),ve=Cu(xe,!0);function _e(n,t){var r=!0;return pe(n,(function(n,e,u){return r=!!t(n,e,u)})),r}function ge(n,t,r){for(var e=-1,i=n.length;++e0&&r(f)?t>1?de(f,t-1,r,e,u):Bt(u,f):e||(u[u.length]=f)}return u}var be=Tu(),we=Tu(!0);function me(n,t){return n&&be(n,t,Lf)}function xe(n,t){return n&&we(n,t,Lf)}function je(n,t){return Lt(t,(function(t){return Qo(n[t])}))}function Ae(n,t){for(var r=0,e=(t=wu(t,n)).length;null!=n&&rt}function Re(n,t){return null!=n&&Bn.call(n,t)}function ze(n,t){return null!=n&&t in Rn(n)}function Ee(n,t,r){for(var i=r?Tt:Ct,o=n[0].length,f=n.length,a=f,c=e(f),l=1/0,s=[];a--;){var h=n[a];a&&t&&(h=Ut(h,nr(t))),l=wr(h.length,l),c[a]=!r&&(t||o>=120&&h.length>=120)?new Hr(a&&h):u}h=n[0];var p=-1,v=c[0];n:for(;++p=f?a:a*("desc"==r[e]?-1:1)}return n.index-t.index}(n,t,r)}))}function Ke(n,t,r){for(var e=-1,u=t.length,i={};++e-1;)f!==n&&Yn.call(f,a,1),Yn.call(n,a,1);return n}function Ge(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;bi(u)?Yn.call(n,u,1):hu(n,u)}}return n}function He(n,t){return n+yt(jr()*(t-n+1))}function Je(n,t){var r="";if(!n||t<1||t>v)return r;do{t%2&&(r+=n),(t=yt(t/2))&&(n+=n)}while(t);return r}function Ye(n,t){return Wi(Ii(n,t,ia),n+"")}function Qe(n){return Qr(Nf(n))}function Xe(n,t){var r=Nf(n);return Ti(r,ae(t,0,r.length))}function nu(n,t,r,e){if(!tf(n))return n;for(var i=-1,o=(t=wu(t,n)).length,f=o-1,a=n;null!=a&&++ii?0:i+t),(r=r>i?i:r)<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=e(i);++u>>1,o=n[i];null!==o&&!lf(o)&&(r?o<=t:o=200){var c=t?null:Ju(n);if(c)return hr(c);o=!1,u=rr,a=new Hr}else a=t?[]:f;n:for(;++e=e?n:uu(n,t,r)}var ju=it||function(n){return gt.clearTimeout(n)};function Au(n,t){if(t)return n.slice();var r=n.length,e=Vn?Vn(r):new n.constructor(r);return n.copy(e),e}function ku(n){var t=new n.constructor(n.byteLength);return new Kn(t).set(new Kn(n)),t}function Ou(n,t){var r=t?ku(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function Iu(n,t){if(n!==t){var r=n!==u,e=null===n,i=n==n,o=lf(n),f=t!==u,a=null===t,c=t==t,l=lf(t);if(!a&&!l&&!o&&n>t||o&&f&&c&&!a&&!l||e&&f&&c||!r&&c||!i)return 1;if(!e&&!o&&!l&&n1?r[i-1]:u,f=i>2?r[2]:u;for(o=n.length>3&&"function"==typeof o?(i--,o):u,f&&wi(r[0],r[1],f)&&(o=i<3?u:o,i=1),t=Rn(t);++e-1?i[o?t[f]:f]:u}}function Fu(n){return ei((function(t){var r=t.length,e=r,o=qr.prototype.thru;for(n&&t.reverse();e--;){var f=t[e];if("function"!=typeof f)throw new Sn(i);if(o&&!a&&"wrapper"==fi(f))var a=new qr([],!0)}for(e=a?e:r;++e1&&w.reverse(),p&&la))return!1;var l=o.get(n),s=o.get(t);if(l&&s)return l==t&&s==n;var h=-1,p=!0,v=2&r?new Hr:u;for(o.set(n,t),o.set(t,n);++h-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(cn,"{\n/* [wrapped with "+t+"] */\n")}(e,function(n,t){return Et(y,(function(r){var e="_."+r[0];t&r[1]&&!Ct(n,e)&&n.push(e)})),n.sort()}(function(n){var t=n.match(ln);return t?t[1].split(sn):[]}(e),r)))}function Ci(n){var t=0,r=0;return function(){var e=mr(),i=16-(e-r);if(r=e,i>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(u,arguments)}}function Ti(n,t){var r=-1,e=n.length,i=e-1;for(t=t===u?e:t;++r1?n[t-1]:u;return r="function"==typeof r?(n.pop(),r):u,io(n,r)}));function ho(n){var t=Mr(n);return t.__chain__=!0,t}function po(n,t){return t(n)}var vo=ei((function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,i=function(t){return fe(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Zr&&bi(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:po,args:[i],thisArg:u}),new qr(e,this.__chain__).thru((function(n){return t&&!n.length&&n.push(u),n}))):this.thru(i)}));var _o=Wu((function(n,t,r){Bn.call(n,r)?++n[r]:oe(n,r,1)}));var go=Du(Pi),yo=Du(qi);function bo(n,t){return(Zo(n)?Et:pe)(n,ci(t,3))}function wo(n,t){return(Zo(n)?St:ve)(n,ci(t,3))}var mo=Wu((function(n,t,r){Bn.call(n,r)?n[r].push(t):oe(n,r,[t])}));var xo=Ye((function(n,t,r){var u=-1,i="function"==typeof t,o=Vo(n)?e(n.length):[];return pe(n,(function(n){o[++u]=i?Rt(t,n,r):Se(n,t,r)})),o})),jo=Wu((function(n,t,r){oe(n,r,t)}));function Ao(n,t){return(Zo(n)?Ut:Fe)(n,ci(t,3))}var ko=Wu((function(n,t,r){n[r?0:1].push(t)}),(function(){return[[],[]]}));var Oo=Ye((function(n,t){if(null==n)return[];var r=t.length;return r>1&&wi(n,t[0],t[1])?t=[]:r>2&&wi(t[0],t[1],t[2])&&(t=[t[0]]),Ze(n,de(t,1),[])})),Io=st||function(){return gt.Date.now()};function Ro(n,t,r){return t=r?u:t,t=n&&null==t?n.length:t,Qu(n,s,u,u,u,u,t)}function zo(n,t){var r;if("function"!=typeof t)throw new Sn(i);return n=gf(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=u),r}}var Eo=Ye((function(n,t,r){var e=1;if(r.length){var u=sr(r,ai(Eo));e|=c}return Qu(n,e,t,r,u)})),So=Ye((function(n,t,r){var e=3;if(r.length){var u=sr(r,ai(So));e|=c}return Qu(t,e,n,r,u)}));function Wo(n,t,r){var e,o,f,a,c,l,s=0,h=!1,p=!1,v=!0;if("function"!=typeof n)throw new Sn(i);function _(t){var r=e,i=o;return e=o=u,s=t,a=n.apply(i,r)}function g(n){var r=n-l;return l===u||r>=t||r<0||p&&n-s>=f}function y(){var n=Io();if(g(n))return d(n);c=Si(y,function(n){var r=t-(n-l);return p?wr(r,f-(n-s)):r}(n))}function d(n){return c=u,v&&e?_(n):(e=o=u,a)}function b(){var n=Io(),r=g(n);if(e=arguments,o=this,l=n,r){if(c===u)return function(n){return s=n,c=Si(y,t),h?_(n):a}(l);if(p)return ju(c),c=Si(y,t),_(l)}return c===u&&(c=Si(y,t)),a}return t=df(t)||0,tf(r)&&(h=!!r.leading,f=(p="maxWait"in r)?br(df(r.maxWait)||0,t):f,v="trailing"in r?!!r.trailing:v),b.cancel=function(){c!==u&&ju(c),s=0,e=l=o=c=u},b.flush=function(){return c===u?a:d(Io())},b}var Lo=Ye((function(n,t){return se(n,1,t)})),Co=Ye((function(n,t,r){return se(n,df(t)||0,r)}));function To(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new Sn(i);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(To.Cache||Gr),r}function Uo(n){if("function"!=typeof n)throw new Sn(i);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}To.Cache=Gr;var Bo=mu((function(n,t){var r=(t=1==t.length&&Zo(t[0])?Ut(t[0],nr(ci())):Ut(de(t,1),nr(ci()))).length;return Ye((function(e){for(var u=-1,i=wr(e.length,r);++u=t})),qo=We(function(){return arguments}())?We:function(n){return rf(n)&&Bn.call(n,"callee")&&!Jn.call(n,"callee")},Zo=e.isArray,Ko=xt?nr(xt):function(n){return rf(n)&&Oe(n)==C};function Vo(n){return null!=n&&nf(n.length)&&!Qo(n)}function Go(n){return rf(n)&&Vo(n)}var Ho=wt||da,Jo=jt?nr(jt):function(n){return rf(n)&&Oe(n)==m};function Yo(n){if(!rf(n))return!1;var t=Oe(n);return t==x||"[object DOMException]"==t||"string"==typeof n.message&&"string"==typeof n.name&&!of(n)}function Qo(n){if(!tf(n))return!1;var t=Oe(n);return t==j||t==A||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Xo(n){return"number"==typeof n&&n==gf(n)}function nf(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=v}function tf(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function rf(n){return null!=n&&"object"==typeof n}var ef=At?nr(At):function(n){return rf(n)&&_i(n)==k};function uf(n){return"number"==typeof n||rf(n)&&Oe(n)==O}function of(n){if(!rf(n)||Oe(n)!=I)return!1;var t=Gn(n);if(null===t)return!0;var r=Bn.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&Un.call(r)==Mn}var ff=kt?nr(kt):function(n){return rf(n)&&Oe(n)==z};var af=Ot?nr(Ot):function(n){return rf(n)&&_i(n)==E};function cf(n){return"string"==typeof n||!Zo(n)&&rf(n)&&Oe(n)==S}function lf(n){return"symbol"==typeof n||rf(n)&&Oe(n)==W}var sf=It?nr(It):function(n){return rf(n)&&nf(n.length)&&!!ct[Oe(n)]};var hf=Vu(De),pf=Vu((function(n,t){return n<=t}));function vf(n){if(!n)return[];if(Vo(n))return cf(n)?_r(n):Eu(n);if(Xn&&n[Xn])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Xn]());var t=_i(n);return(t==k?cr:t==E?hr:Nf)(n)}function _f(n){return n?(n=df(n))===p||n===-1/0?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function gf(n){var t=_f(n),r=t%1;return t==t?r?t-r:t:0}function yf(n){return n?ae(gf(n),0,g):0}function df(n){if("number"==typeof n)return n;if(lf(n))return _;if(tf(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=tf(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=Xt(n);var r=dn.test(n);return r||wn.test(n)?pt(n.slice(2),r?2:8):yn.test(n)?_:+n}function bf(n){return Su(n,Cf(n))}function wf(n){return null==n?"":lu(n)}var mf=Lu((function(n,t){if(Ai(t)||Vo(t))Su(t,Lf(t),n);else for(var r in t)Bn.call(t,r)&&re(n,r,t[r])})),xf=Lu((function(n,t){Su(t,Cf(t),n)})),jf=Lu((function(n,t,r,e){Su(t,Cf(t),n,e)})),Af=Lu((function(n,t,r,e){Su(t,Lf(t),n,e)})),kf=ei(fe);var Of=Ye((function(n,t){n=Rn(n);var r=-1,e=t.length,i=e>2?t[2]:u;for(i&&wi(t[0],t[1],i)&&(e=1);++r1),t})),Su(n,ii(n),r),e&&(r=ce(r,7,ti));for(var u=t.length;u--;)hu(r,t[u]);return r}));var $f=ei((function(n,t){return null==n?{}:function(n,t){return Ke(n,t,(function(t,r){return zf(n,r)}))}(n,t)}));function Df(n,t){if(null==n)return{};var r=Ut(ii(n),(function(n){return[n]}));return t=ci(t),Ke(n,r,(function(n,r){return t(n,r[0])}))}var Ff=Yu(Lf),Mf=Yu(Cf);function Nf(n){return null==n?[]:tr(n,Lf(n))}var Pf=Bu((function(n,t,r){return t=t.toLowerCase(),n+(r?qf(t):t)}));function qf(n){return Qf(wf(n).toLowerCase())}function Zf(n){return(n=wf(n))&&n.replace(xn,ir).replace(rt,"")}var Kf=Bu((function(n,t,r){return n+(r?"-":"")+t.toLowerCase()})),Vf=Bu((function(n,t,r){return n+(r?" ":"")+t.toLowerCase()})),Gf=Uu("toLowerCase");var Hf=Bu((function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}));var Jf=Bu((function(n,t,r){return n+(r?" ":"")+Qf(t)}));var Yf=Bu((function(n,t,r){return n+(r?" ":"")+t.toUpperCase()})),Qf=Uu("toUpperCase");function Xf(n,t,r){return n=wf(n),(t=r?u:t)===u?function(n){return ot.test(n)}(n)?function(n){return n.match(ut)||[]}(n):function(n){return n.match(hn)||[]}(n):n.match(t)||[]}var na=Ye((function(n,t){try{return Rt(n,u,t)}catch(n){return Yo(n)?n:new kn(n)}})),ta=ei((function(n,t){return Et(t,(function(t){t=Bi(t),oe(n,t,Eo(n[t],n))})),n}));function ra(n){return function(){return n}}var ea=Fu(),ua=Fu(!0);function ia(n){return n}function oa(n){return Ue("function"==typeof n?n:ce(n,1))}var fa=Ye((function(n,t){return function(r){return Se(r,n,t)}})),aa=Ye((function(n,t){return function(r){return Se(n,r,t)}}));function ca(n,t,r){var e=Lf(t),u=je(t,e);null!=r||tf(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=je(t,Lf(t)));var i=!(tf(r)&&"chain"in r&&!r.chain),o=Qo(n);return Et(u,(function(r){var e=t[r];n[r]=e,o&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=Eu(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,Bt([this.value()],arguments))})})),n}function la(){}var sa=qu(Ut),ha=qu(Wt),pa=qu(Ft);function va(n){return mi(n)?Gt(Bi(n)):function(n){return function(t){return Ae(t,n)}}(n)}var _a=Ku(),ga=Ku(!0);function ya(){return[]}function da(){return!1}var ba=Pu((function(n,t){return n+t}),0),wa=Hu("ceil"),ma=Pu((function(n,t){return n/t}),1),xa=Hu("floor");var ja,Aa=Pu((function(n,t){return n*t}),1),ka=Hu("round"),Oa=Pu((function(n,t){return n-t}),0);return Mr.after=function(n,t){if("function"!=typeof t)throw new Sn(i);return n=gf(n),function(){if(--n<1)return t.apply(this,arguments)}},Mr.ary=Ro,Mr.assign=mf,Mr.assignIn=xf,Mr.assignInWith=jf,Mr.assignWith=Af,Mr.at=kf,Mr.before=zo,Mr.bind=Eo,Mr.bindAll=ta,Mr.bindKey=So,Mr.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Zo(n)?n:[n]},Mr.chain=ho,Mr.chunk=function(n,t,r){t=(r?wi(n,t,r):t===u)?1:br(gf(t),0);var i=null==n?0:n.length;if(!i||t<1)return[];for(var o=0,f=0,a=e(_t(i/t));oi?0:i+r),(e=e===u||e>i?i:gf(e))<0&&(e+=i),e=r>e?0:yf(e);r>>0)?(n=wf(n))&&("string"==typeof t||null!=t&&!ff(t))&&!(t=lu(t))&&ar(n)?xu(_r(n),0,r):n.split(t,r):[]},Mr.spread=function(n,t){if("function"!=typeof n)throw new Sn(i);return t=null==t?0:br(gf(t),0),Ye((function(r){var e=r[t],u=xu(r,0,t);return e&&Bt(u,e),Rt(n,this,u)}))},Mr.tail=function(n){var t=null==n?0:n.length;return t?uu(n,1,t):[]},Mr.take=function(n,t,r){return n&&n.length?uu(n,0,(t=r||t===u?1:gf(t))<0?0:t):[]},Mr.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?uu(n,(t=e-(t=r||t===u?1:gf(t)))<0?0:t,e):[]},Mr.takeRightWhile=function(n,t){return n&&n.length?vu(n,ci(t,3),!1,!0):[]},Mr.takeWhile=function(n,t){return n&&n.length?vu(n,ci(t,3)):[]},Mr.tap=function(n,t){return t(n),n},Mr.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new Sn(i);return tf(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Wo(n,t,{leading:e,maxWait:t,trailing:u})},Mr.thru=po,Mr.toArray=vf,Mr.toPairs=Ff,Mr.toPairsIn=Mf,Mr.toPath=function(n){return Zo(n)?Ut(n,Bi):lf(n)?[n]:Eu(Ui(wf(n)))},Mr.toPlainObject=bf,Mr.transform=function(n,t,r){var e=Zo(n),u=e||Ho(n)||sf(n);if(t=ci(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:tf(n)&&Qo(i)?Nr(Gn(n)):{}}return(u?Et:me)(n,(function(n,e,u){return t(r,n,e,u)})),r},Mr.unary=function(n){return Ro(n,1)},Mr.union=to,Mr.unionBy=ro,Mr.unionWith=eo,Mr.uniq=function(n){return n&&n.length?su(n):[]},Mr.uniqBy=function(n,t){return n&&n.length?su(n,ci(t,2)):[]},Mr.uniqWith=function(n,t){return t="function"==typeof t?t:u,n&&n.length?su(n,u,t):[]},Mr.unset=function(n,t){return null==n||hu(n,t)},Mr.unzip=uo,Mr.unzipWith=io,Mr.update=function(n,t,r){return null==n?n:pu(n,t,bu(r))},Mr.updateWith=function(n,t,r,e){return e="function"==typeof e?e:u,null==n?n:pu(n,t,bu(r),e)},Mr.values=Nf,Mr.valuesIn=function(n){return null==n?[]:tr(n,Cf(n))},Mr.without=oo,Mr.words=Xf,Mr.wrap=function(n,t){return $o(bu(t),n)},Mr.xor=fo,Mr.xorBy=ao,Mr.xorWith=co,Mr.zip=lo,Mr.zipObject=function(n,t){return yu(n||[],t||[],re)},Mr.zipObjectDeep=function(n,t){return yu(n||[],t||[],nu)},Mr.zipWith=so,Mr.entries=Ff,Mr.entriesIn=Mf,Mr.extend=xf,Mr.extendWith=jf,ca(Mr,Mr),Mr.add=ba,Mr.attempt=na,Mr.camelCase=Pf,Mr.capitalize=qf,Mr.ceil=wa,Mr.clamp=function(n,t,r){return r===u&&(r=t,t=u),r!==u&&(r=(r=df(r))==r?r:0),t!==u&&(t=(t=df(t))==t?t:0),ae(df(n),t,r)},Mr.clone=function(n){return ce(n,4)},Mr.cloneDeep=function(n){return ce(n,5)},Mr.cloneDeepWith=function(n,t){return ce(n,5,t="function"==typeof t?t:u)},Mr.cloneWith=function(n,t){return ce(n,4,t="function"==typeof t?t:u)},Mr.conformsTo=function(n,t){return null==t||le(n,t,Lf(t))},Mr.deburr=Zf,Mr.defaultTo=function(n,t){return null==n||n!=n?t:n},Mr.divide=ma,Mr.endsWith=function(n,t,r){n=wf(n),t=lu(t);var e=n.length,i=r=r===u?e:ae(gf(r),0,e);return(r-=t.length)>=0&&n.slice(r,i)==t},Mr.eq=Mo,Mr.escape=function(n){return(n=wf(n))&&Y.test(n)?n.replace(H,or):n},Mr.escapeRegExp=function(n){return(n=wf(n))&&on.test(n)?n.replace(un,"\\$&"):n},Mr.every=function(n,t,r){var e=Zo(n)?Wt:_e;return r&&wi(n,t,r)&&(t=u),e(n,ci(t,3))},Mr.find=go,Mr.findIndex=Pi,Mr.findKey=function(n,t){return Nt(n,ci(t,3),me)},Mr.findLast=yo,Mr.findLastIndex=qi,Mr.findLastKey=function(n,t){return Nt(n,ci(t,3),xe)},Mr.floor=xa,Mr.forEach=bo,Mr.forEachRight=wo,Mr.forIn=function(n,t){return null==n?n:be(n,ci(t,3),Cf)},Mr.forInRight=function(n,t){return null==n?n:we(n,ci(t,3),Cf)},Mr.forOwn=function(n,t){return n&&me(n,ci(t,3))},Mr.forOwnRight=function(n,t){return n&&xe(n,ci(t,3))},Mr.get=Rf,Mr.gt=No,Mr.gte=Po,Mr.has=function(n,t){return null!=n&&gi(n,t,Re)},Mr.hasIn=zf,Mr.head=Ki,Mr.identity=ia,Mr.includes=function(n,t,r,e){n=Vo(n)?n:Nf(n),r=r&&!e?gf(r):0;var u=n.length;return r<0&&(r=br(u+r,0)),cf(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&qt(n,t,r)>-1},Mr.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:gf(r);return u<0&&(u=br(e+u,0)),qt(n,t,u)},Mr.inRange=function(n,t,r){return t=_f(t),r===u?(r=t,t=0):r=_f(r),function(n,t,r){return n>=wr(t,r)&&n=-9007199254740991&&n<=v},Mr.isSet=af,Mr.isString=cf,Mr.isSymbol=lf,Mr.isTypedArray=sf,Mr.isUndefined=function(n){return n===u},Mr.isWeakMap=function(n){return rf(n)&&_i(n)==L},Mr.isWeakSet=function(n){return rf(n)&&"[object WeakSet]"==Oe(n)},Mr.join=function(n,t){return null==n?"":Mt.call(n,t)},Mr.kebabCase=Kf,Mr.last=Ji,Mr.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var i=e;return r!==u&&(i=(i=gf(r))<0?br(e+i,0):wr(i,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,i):Pt(n,Kt,i,!0)},Mr.lowerCase=Vf,Mr.lowerFirst=Gf,Mr.lt=hf,Mr.lte=pf,Mr.max=function(n){return n&&n.length?ge(n,ia,Ie):u},Mr.maxBy=function(n,t){return n&&n.length?ge(n,ci(t,2),Ie):u},Mr.mean=function(n){return Vt(n,ia)},Mr.meanBy=function(n,t){return Vt(n,ci(t,2))},Mr.min=function(n){return n&&n.length?ge(n,ia,De):u},Mr.minBy=function(n,t){return n&&n.length?ge(n,ci(t,2),De):u},Mr.stubArray=ya,Mr.stubFalse=da,Mr.stubObject=function(){return{}},Mr.stubString=function(){return""},Mr.stubTrue=function(){return!0},Mr.multiply=Aa,Mr.nth=function(n,t){return n&&n.length?qe(n,gf(t)):u},Mr.noConflict=function(){return gt._===this&&(gt._=Nn),this},Mr.noop=la,Mr.now=Io,Mr.pad=function(n,t,r){n=wf(n);var e=(t=gf(t))?vr(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return Zu(yt(u),r)+n+Zu(_t(u),r)},Mr.padEnd=function(n,t,r){n=wf(n);var e=(t=gf(t))?vr(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var i=jr();return wr(n+i*(t-n+ht("1e-"+((i+"").length-1))),t)}return He(n,t)},Mr.reduce=function(n,t,r){var e=Zo(n)?$t:Jt,u=arguments.length<3;return e(n,ci(t,4),r,u,pe)},Mr.reduceRight=function(n,t,r){var e=Zo(n)?Dt:Jt,u=arguments.length<3;return e(n,ci(t,4),r,u,ve)},Mr.repeat=function(n,t,r){return t=(r?wi(n,t,r):t===u)?1:gf(t),Je(wf(n),t)},Mr.replace=function(){var n=arguments,t=wf(n[0]);return n.length<3?t:t.replace(n[1],n[2])},Mr.result=function(n,t,r){var e=-1,i=(t=wu(t,n)).length;for(i||(i=1,n=u);++ev)return[];var r=g,e=wr(n,g);t=ci(t),n-=g;for(var u=Qt(e,t);++r=o)return n;var a=r-vr(e);if(a<1)return e;var c=f?xu(f,0,a).join(""):n.slice(0,a);if(i===u)return c+e;if(f&&(a+=c.length-a),ff(i)){if(n.slice(a).search(i)){var l,s=c;for(i.global||(i=zn(i.source,wf(gn.exec(i))+"g")),i.lastIndex=0;l=i.exec(s);)var h=l.index;c=c.slice(0,h===u?a:h)}}else if(n.indexOf(lu(i),a)!=a){var p=c.lastIndexOf(i);p>-1&&(c=c.slice(0,p))}return c+e},Mr.unescape=function(n){return(n=wf(n))&&J.test(n)?n.replace(G,yr):n},Mr.uniqueId=function(n){var t=++$n;return wf(n)+t},Mr.upperCase=Yf,Mr.upperFirst=Qf,Mr.each=bo,Mr.eachRight=wo,Mr.first=Ki,ca(Mr,(ja={},me(Mr,(function(n,t){Bn.call(Mr.prototype,t)||(ja[t]=n)})),ja),{chain:!1}),Mr.VERSION="4.17.21",Et(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(n){Mr[n].placeholder=Mr})),Et(["drop","take"],(function(n,t){Zr.prototype[n]=function(r){r=r===u?1:br(gf(r),0);var e=this.__filtered__&&!t?new Zr(this):this.clone();return e.__filtered__?e.__takeCount__=wr(r,e.__takeCount__):e.__views__.push({size:wr(r,g),type:n+(e.__dir__<0?"Right":"")}),e},Zr.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}})),Et(["filter","map","takeWhile"],(function(n,t){var r=t+1,e=1==r||3==r;Zr.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:ci(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}})),Et(["head","last"],(function(n,t){var r="take"+(t?"Right":"");Zr.prototype[n]=function(){return this[r](1).value()[0]}})),Et(["initial","tail"],(function(n,t){var r="drop"+(t?"":"Right");Zr.prototype[n]=function(){return this.__filtered__?new Zr(this):this[r](1)}})),Zr.prototype.compact=function(){return this.filter(ia)},Zr.prototype.find=function(n){return this.filter(n).head()},Zr.prototype.findLast=function(n){return this.reverse().find(n)},Zr.prototype.invokeMap=Ye((function(n,t){return"function"==typeof n?new Zr(this):this.map((function(r){return Se(r,n,t)}))})),Zr.prototype.reject=function(n){return this.filter(Uo(ci(n)))},Zr.prototype.slice=function(n,t){n=gf(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Zr(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==u&&(r=(t=gf(t))<0?r.dropRight(-t):r.take(t-n)),r)},Zr.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Zr.prototype.toArray=function(){return this.take(g)},me(Zr.prototype,(function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),i=Mr[e?"take"+("last"==t?"Right":""):t],o=e||/^find/.test(t);i&&(Mr.prototype[t]=function(){var t=this.__wrapped__,f=e?[1]:arguments,a=t instanceof Zr,c=f[0],l=a||Zo(t),s=function(n){var t=i.apply(Mr,Bt([n],f));return e&&h?t[0]:t};l&&r&&"function"==typeof c&&1!=c.length&&(a=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,_=a&&!p;if(!o&&l){t=_?t:new Zr(this);var g=n.apply(t,f);return g.__actions__.push({func:po,args:[s],thisArg:u}),new qr(g,h)}return v&&_?n.apply(this,f):(g=this.thru(s),v?e?g.value()[0]:g.value():g)})})),Et(["pop","push","shift","sort","splice","unshift"],(function(n){var t=Wn[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);Mr.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Zo(u)?u:[],n)}return this[r]((function(r){return t.apply(Zo(r)?r:[],n)}))}})),me(Zr.prototype,(function(n,t){var r=Mr[t];if(r){var e=r.name+"";Bn.call(Wr,e)||(Wr[e]=[]),Wr[e].push({name:t,func:r})}})),Wr[Mu(u,2).name]=[{name:"wrapper",func:u}],Zr.prototype.clone=function(){var n=new Zr(this.__wrapped__);return n.__actions__=Eu(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Eu(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Eu(this.__views__),n},Zr.prototype.reverse=function(){if(this.__filtered__){var n=new Zr(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},Zr.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=Zo(n),e=t<0,u=r?n.length:0,i=function(n,t,r){var e=-1,u=r.length;for(;++e=this.__values__.length;return{done:n,value:n?u:this.__values__[this.__index__++]}},Mr.prototype.plant=function(n){for(var t,r=this;r instanceof Pr;){var e=Di(r);e.__index__=0,e.__values__=u,t?i.__wrapped__=e:t=e;var i=e;r=r.__wrapped__}return i.__wrapped__=n,t},Mr.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof Zr){var t=n;return this.__actions__.length&&(t=new Zr(this)),(t=t.reverse()).__actions__.push({func:po,args:[no],thisArg:u}),new qr(t,this.__chain__)}return this.thru(no)},Mr.prototype.toJSON=Mr.prototype.valueOf=Mr.prototype.value=function(){return _u(this.__wrapped__,this.__actions__)},Mr.prototype.first=Mr.prototype.head,Xn&&(Mr.prototype[Xn]=function(){return this}),Mr}();gt._=dr,(e=function(){return dr}.call(t,r,t,n))===u||(n.exports=e)}.call(this)},7803:(n,t,r)=>{n.exports=r(2543)}},t={};function r(e){var u=t[e];if(void 0!==u)return u.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return n[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}return r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),r.nmd=n=>(n.paths=[],n.children||(n.children=[]),n),r(7803)})())); \ No newline at end of file + */n=r.nmd(n),function(){var u,i="Expected a function",o="__lodash_hash_undefined__",f="__lodash_placeholder__",a=16,c=32,l=64,s=128,h=256,p=1/0,v=9007199254740991,_=NaN,g=4294967295,y=[["ary",s],["bind",1],["bindKey",2],["curry",8],["curryRight",a],["flip",512],["partial",c],["partialRight",l],["rearg",h]],d="[object Arguments]",b="[object Array]",w="[object Boolean]",m="[object Date]",x="[object Error]",j="[object Function]",A="[object GeneratorFunction]",k="[object Map]",I="[object Number]",O="[object Object]",R="[object Promise]",z="[object RegExp]",E="[object Set]",S="[object String]",W="[object Symbol]",L="[object WeakMap]",C="[object ArrayBuffer]",T="[object DataView]",U="[object Float32Array]",B="[object Float64Array]",$="[object Int8Array]",D="[object Int16Array]",F="[object Int32Array]",M="[object Uint8Array]",N="[object Uint8ClampedArray]",P="[object Uint16Array]",q="[object Uint32Array]",Z=/\b__p \+= '';/g,K=/\b(__p \+=) '' \+/g,V=/(__e\(.*?\)|\b__t\)) \+\n'';/g,G=/&(?:amp|lt|gt|quot|#39);/g,H=/[&<>"']/g,J=RegExp(G.source),Y=RegExp(H.source),Q=/<%-([\s\S]+?)%>/g,X=/<%([\s\S]+?)%>/g,nn=/<%=([\s\S]+?)%>/g,tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,rn=/^\w*$/,en=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,un=/[\\^$.*+?()[\]{}|]/g,on=RegExp(un.source),fn=/^\s+/,an=/\s/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,ln=/\{\n\/\* \[wrapped with (.+)\] \*/,sn=/,? & /,hn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,pn=/[()=,{}\[\]\/\s]/,vn=/\\(\\)?/g,_n=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,gn=/\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,dn=/^0b[01]+$/i,bn=/^\[object .+?Constructor\]$/,wn=/^0o[0-7]+$/i,mn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,An=/['\n\r\u2028\u2029\\]/g,kn="\\ud800-\\udfff",In="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",On="\\u2700-\\u27bf",Rn="a-z\\xdf-\\xf6\\xf8-\\xff",zn="A-Z\\xc0-\\xd6\\xd8-\\xde",En="\\ufe0e\\ufe0f",Sn="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Wn="['’]",Ln="["+kn+"]",Cn="["+Sn+"]",Tn="["+In+"]",Un="\\d+",Bn="["+On+"]",$n="["+Rn+"]",Dn="[^"+kn+Sn+Un+On+Rn+zn+"]",Fn="\\ud83c[\\udffb-\\udfff]",Mn="[^"+kn+"]",Nn="(?:\\ud83c[\\udde6-\\uddff]){2}",Pn="[\\ud800-\\udbff][\\udc00-\\udfff]",qn="["+zn+"]",Zn="\\u200d",Kn="(?:"+$n+"|"+Dn+")",Vn="(?:"+qn+"|"+Dn+")",Gn="(?:['’](?:d|ll|m|re|s|t|ve))?",Hn="(?:['’](?:D|LL|M|RE|S|T|VE))?",Jn="(?:"+Tn+"|"+Fn+")"+"?",Yn="["+En+"]?",Qn=Yn+Jn+("(?:"+Zn+"(?:"+[Mn,Nn,Pn].join("|")+")"+Yn+Jn+")*"),Xn="(?:"+[Bn,Nn,Pn].join("|")+")"+Qn,nt="(?:"+[Mn+Tn+"?",Tn,Nn,Pn,Ln].join("|")+")",tt=RegExp(Wn,"g"),rt=RegExp(Tn,"g"),et=RegExp(Fn+"(?="+Fn+")|"+nt+Qn,"g"),ut=RegExp([qn+"?"+$n+"+"+Gn+"(?="+[Cn,qn,"$"].join("|")+")",Vn+"+"+Hn+"(?="+[Cn,qn+Kn,"$"].join("|")+")",qn+"?"+Kn+"+"+Gn,qn+"+"+Hn,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Un,Xn].join("|"),"g"),it=RegExp("["+Zn+kn+In+En+"]"),ot=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,ft=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],at=-1,ct={};ct[U]=ct[B]=ct[$]=ct[D]=ct[F]=ct[M]=ct[N]=ct[P]=ct[q]=!0,ct[d]=ct[b]=ct[C]=ct[w]=ct[T]=ct[m]=ct[x]=ct[j]=ct[k]=ct[I]=ct[O]=ct[z]=ct[E]=ct[S]=ct[L]=!1;var lt={};lt[d]=lt[b]=lt[C]=lt[T]=lt[w]=lt[m]=lt[U]=lt[B]=lt[$]=lt[D]=lt[F]=lt[k]=lt[I]=lt[O]=lt[z]=lt[E]=lt[S]=lt[W]=lt[M]=lt[N]=lt[P]=lt[q]=!0,lt[x]=lt[j]=lt[L]=!1;var st={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ht=parseFloat,pt=parseInt,vt="object"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,_t="object"==typeof self&&self&&self.Object===Object&&self,gt=vt||_t||Function("return this")(),yt=t&&!t.nodeType&&t,dt=yt&&n&&!n.nodeType&&n,bt=dt&&dt.exports===yt,wt=bt&&vt.process,mt=function(){try{var n=dt&&dt.require&&dt.require("util").types;return n||wt&&wt.binding&&wt.binding("util")}catch(n){}}(),xt=mt&&mt.isArrayBuffer,jt=mt&&mt.isDate,At=mt&&mt.isMap,kt=mt&&mt.isRegExp,It=mt&&mt.isSet,Ot=mt&&mt.isTypedArray;function Rt(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function zt(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function Tt(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function ur(n,t){for(var r=n.length;r--&&qt(t,n[r],0)>-1;);return r}var ir=Ht({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"}),or=Ht({"&":"&","<":"<",">":">",'"':""","'":"'"});function fr(n){return"\\"+st[n]}function ar(n){return it.test(n)}function cr(n){var t=-1,r=Array(n.size);return n.forEach((function(n,e){r[++t]=[e,n]})),r}function lr(n,t){return function(r){return n(t(r))}}function sr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r",""":'"',"'":"'"});var dr=function n(t){var r,e=(t=null==t?gt:dr.defaults(gt.Object(),t,dr.pick(gt,ft))).Array,an=t.Date,kn=t.Error,In=t.Function,On=t.Math,Rn=t.Object,zn=t.RegExp,En=t.String,Sn=t.TypeError,Wn=e.prototype,Ln=In.prototype,Cn=Rn.prototype,Tn=t["__core-js_shared__"],Un=Ln.toString,Bn=Cn.hasOwnProperty,$n=0,Dn=(r=/[^.]+$/.exec(Tn&&Tn.keys&&Tn.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"",Fn=Cn.toString,Mn=Un.call(Rn),Nn=gt._,Pn=zn("^"+Un.call(Bn).replace(un,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),qn=bt?t.Buffer:u,Zn=t.Symbol,Kn=t.Uint8Array,Vn=qn?qn.allocUnsafe:u,Gn=lr(Rn.getPrototypeOf,Rn),Hn=Rn.create,Jn=Cn.propertyIsEnumerable,Yn=Wn.splice,Qn=Zn?Zn.isConcatSpreadable:u,Xn=Zn?Zn.iterator:u,nt=Zn?Zn.toStringTag:u,et=function(){try{var n=hi(Rn,"defineProperty");return n({},"",{}),n}catch(n){}}(),it=t.clearTimeout!==gt.clearTimeout&&t.clearTimeout,st=an&&an.now!==gt.Date.now&&an.now,vt=t.setTimeout!==gt.setTimeout&&t.setTimeout,_t=On.ceil,yt=On.floor,dt=Rn.getOwnPropertySymbols,wt=qn?qn.isBuffer:u,mt=t.isFinite,Mt=Wn.join,Ht=lr(Rn.keys,Rn),br=On.max,wr=On.min,mr=an.now,xr=t.parseInt,jr=On.random,Ar=Wn.reverse,kr=hi(t,"DataView"),Ir=hi(t,"Map"),Or=hi(t,"Promise"),Rr=hi(t,"Set"),zr=hi(t,"WeakMap"),Er=hi(Rn,"create"),Sr=zr&&new zr,Wr={},Lr=$i(kr),Cr=$i(Ir),Tr=$i(Or),Ur=$i(Rr),Br=$i(zr),$r=Zn?Zn.prototype:u,Dr=$r?$r.valueOf:u,Fr=$r?$r.toString:u;function Mr(n){if(rf(n)&&!Zo(n)&&!(n instanceof Zr)){if(n instanceof qr)return n;if(Bn.call(n,"__wrapped__"))return Di(n)}return new qr(n)}var Nr=function(){function n(){}return function(t){if(!tf(t))return{};if(Hn)return Hn(t);n.prototype=t;var r=new n;return n.prototype=u,r}}();function Pr(){}function qr(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=u}function Zr(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=g,this.__views__=[]}function Kr(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function ce(n,t,r,e,i,o){var f,a=1&t,c=2&t,l=4&t;if(r&&(f=i?r(n,e,i,o):r(n)),f!==u)return f;if(!tf(n))return n;var s=Zo(n);if(s){if(f=function(n){var t=n.length,r=new n.constructor(t);t&&"string"==typeof n[0]&&Bn.call(n,"index")&&(r.index=n.index,r.input=n.input);return r}(n),!a)return Eu(n,f)}else{var h=_i(n),p=h==j||h==A;if(Ho(n))return Au(n,a);if(h==O||h==d||p&&!i){if(f=c||p?{}:yi(n),!a)return c?function(n,t){return Su(n,vi(n),t)}(n,function(n,t){return n&&Su(t,Cf(t),n)}(f,n)):function(n,t){return Su(n,pi(n),t)}(n,ie(f,n))}else{if(!lt[h])return i?n:{};f=function(n,t,r){var e=n.constructor;switch(t){case C:return ku(n);case w:case m:return new e(+n);case T:return function(n,t){var r=t?ku(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}(n,r);case U:case B:case $:case D:case F:case M:case N:case P:case q:return Iu(n,r);case k:return new e;case I:case S:return new e(n);case z:return function(n){var t=new n.constructor(n.source,gn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case E:return new e;case W:return u=n,Dr?Rn(Dr.call(u)):{}}var u}(n,h,a)}}o||(o=new Jr);var v=o.get(n);if(v)return v;o.set(n,f),af(n)?n.forEach((function(e){f.add(ce(e,t,r,e,n,o))})):ef(n)&&n.forEach((function(e,u){f.set(u,ce(e,t,r,u,n,o))}));var _=s?u:(l?c?ii:ui:c?Cf:Lf)(n);return Et(_||n,(function(e,u){_&&(e=n[u=e]),re(f,u,ce(e,t,r,u,n,o))})),f}function le(n,t,r){var e=r.length;if(null==n)return!e;for(n=Rn(n);e--;){var i=r[e],o=t[i],f=n[i];if(f===u&&!(i in n)||!o(f))return!1}return!0}function se(n,t,r){if("function"!=typeof n)throw new Sn(i);return Si((function(){n.apply(u,r)}),t)}function he(n,t,r,e){var u=-1,i=Ct,o=!0,f=n.length,a=[],c=t.length;if(!f)return a;r&&(t=Ut(t,nr(r))),e?(i=Tt,o=!1):t.length>=200&&(i=rr,o=!1,t=new Hr(t));n:for(;++u-1},Vr.prototype.set=function(n,t){var r=this.__data__,e=ee(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},Gr.prototype.clear=function(){this.size=0,this.__data__={hash:new Kr,map:new(Ir||Vr),string:new Kr}},Gr.prototype.delete=function(n){var t=li(this,n).delete(n);return this.size-=t?1:0,t},Gr.prototype.get=function(n){return li(this,n).get(n)},Gr.prototype.has=function(n){return li(this,n).has(n)},Gr.prototype.set=function(n,t){var r=li(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Hr.prototype.add=Hr.prototype.push=function(n){return this.__data__.set(n,o),this},Hr.prototype.has=function(n){return this.__data__.has(n)},Jr.prototype.clear=function(){this.__data__=new Vr,this.size=0},Jr.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},Jr.prototype.get=function(n){return this.__data__.get(n)},Jr.prototype.has=function(n){return this.__data__.has(n)},Jr.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Vr){var e=r.__data__;if(!Ir||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Gr(e)}return r.set(n,t),this.size=r.size,this};var pe=Cu(me),ve=Cu(xe,!0);function _e(n,t){var r=!0;return pe(n,(function(n,e,u){return r=!!t(n,e,u)})),r}function ge(n,t,r){for(var e=-1,i=n.length;++e0&&r(f)?t>1?de(f,t-1,r,e,u):Bt(u,f):e||(u[u.length]=f)}return u}var be=Tu(),we=Tu(!0);function me(n,t){return n&&be(n,t,Lf)}function xe(n,t){return n&&we(n,t,Lf)}function je(n,t){return Lt(t,(function(t){return Qo(n[t])}))}function Ae(n,t){for(var r=0,e=(t=wu(t,n)).length;null!=n&&rt}function Re(n,t){return null!=n&&Bn.call(n,t)}function ze(n,t){return null!=n&&t in Rn(n)}function Ee(n,t,r){for(var i=r?Tt:Ct,o=n[0].length,f=n.length,a=f,c=e(f),l=1/0,s=[];a--;){var h=n[a];a&&t&&(h=Ut(h,nr(t))),l=wr(h.length,l),c[a]=!r&&(t||o>=120&&h.length>=120)?new Hr(a&&h):u}h=n[0];var p=-1,v=c[0];n:for(;++p=f?a:a*("desc"==r[e]?-1:1)}return n.index-t.index}(n,t,r)}))}function Ke(n,t,r){for(var e=-1,u=t.length,i={};++e-1;)f!==n&&Yn.call(f,a,1),Yn.call(n,a,1);return n}function Ge(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;bi(u)?Yn.call(n,u,1):hu(n,u)}}return n}function He(n,t){return n+yt(jr()*(t-n+1))}function Je(n,t){var r="";if(!n||t<1||t>v)return r;do{t%2&&(r+=n),(t=yt(t/2))&&(n+=n)}while(t);return r}function Ye(n,t){return Wi(Oi(n,t,ia),n+"")}function Qe(n){return Qr(Nf(n))}function Xe(n,t){var r=Nf(n);return Ti(r,ae(t,0,r.length))}function nu(n,t,r,e){if(!tf(n))return n;for(var i=-1,o=(t=wu(t,n)).length,f=o-1,a=n;null!=a&&++ii?0:i+t),(r=r>i?i:r)<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=e(i);++u>>1,o=n[i];null!==o&&!lf(o)&&(r?o<=t:o=200){var c=t?null:Ju(n);if(c)return hr(c);o=!1,u=rr,a=new Hr}else a=t?[]:f;n:for(;++e=e?n:uu(n,t,r)}var ju=it||function(n){return gt.clearTimeout(n)};function Au(n,t){if(t)return n.slice();var r=n.length,e=Vn?Vn(r):new n.constructor(r);return n.copy(e),e}function ku(n){var t=new n.constructor(n.byteLength);return new Kn(t).set(new Kn(n)),t}function Iu(n,t){var r=t?ku(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function Ou(n,t){if(n!==t){var r=n!==u,e=null===n,i=n==n,o=lf(n),f=t!==u,a=null===t,c=t==t,l=lf(t);if(!a&&!l&&!o&&n>t||o&&f&&c&&!a&&!l||e&&f&&c||!r&&c||!i)return 1;if(!e&&!o&&!l&&n1?r[i-1]:u,f=i>2?r[2]:u;for(o=n.length>3&&"function"==typeof o?(i--,o):u,f&&wi(r[0],r[1],f)&&(o=i<3?u:o,i=1),t=Rn(t);++e-1?i[o?t[f]:f]:u}}function Fu(n){return ei((function(t){var r=t.length,e=r,o=qr.prototype.thru;for(n&&t.reverse();e--;){var f=t[e];if("function"!=typeof f)throw new Sn(i);if(o&&!a&&"wrapper"==fi(f))var a=new qr([],!0)}for(e=a?e:r;++e1&&w.reverse(),p&&la))return!1;var l=o.get(n),s=o.get(t);if(l&&s)return l==t&&s==n;var h=-1,p=!0,v=2&r?new Hr:u;for(o.set(n,t),o.set(t,n);++h-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(cn,"{\n/* [wrapped with "+t+"] */\n")}(e,function(n,t){return Et(y,(function(r){var e="_."+r[0];t&r[1]&&!Ct(n,e)&&n.push(e)})),n.sort()}(function(n){var t=n.match(ln);return t?t[1].split(sn):[]}(e),r)))}function Ci(n){var t=0,r=0;return function(){var e=mr(),i=16-(e-r);if(r=e,i>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(u,arguments)}}function Ti(n,t){var r=-1,e=n.length,i=e-1;for(t=t===u?e:t;++r1?n[t-1]:u;return r="function"==typeof r?(n.pop(),r):u,io(n,r)}));function ho(n){var t=Mr(n);return t.__chain__=!0,t}function po(n,t){return t(n)}var vo=ei((function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,i=function(t){return fe(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Zr&&bi(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:po,args:[i],thisArg:u}),new qr(e,this.__chain__).thru((function(n){return t&&!n.length&&n.push(u),n}))):this.thru(i)}));var _o=Wu((function(n,t,r){Bn.call(n,r)?++n[r]:oe(n,r,1)}));var go=Du(Pi),yo=Du(qi);function bo(n,t){return(Zo(n)?Et:pe)(n,ci(t,3))}function wo(n,t){return(Zo(n)?St:ve)(n,ci(t,3))}var mo=Wu((function(n,t,r){Bn.call(n,r)?n[r].push(t):oe(n,r,[t])}));var xo=Ye((function(n,t,r){var u=-1,i="function"==typeof t,o=Vo(n)?e(n.length):[];return pe(n,(function(n){o[++u]=i?Rt(t,n,r):Se(n,t,r)})),o})),jo=Wu((function(n,t,r){oe(n,r,t)}));function Ao(n,t){return(Zo(n)?Ut:Fe)(n,ci(t,3))}var ko=Wu((function(n,t,r){n[r?0:1].push(t)}),(function(){return[[],[]]}));var Io=Ye((function(n,t){if(null==n)return[];var r=t.length;return r>1&&wi(n,t[0],t[1])?t=[]:r>2&&wi(t[0],t[1],t[2])&&(t=[t[0]]),Ze(n,de(t,1),[])})),Oo=st||function(){return gt.Date.now()};function Ro(n,t,r){return t=r?u:t,t=n&&null==t?n.length:t,Qu(n,s,u,u,u,u,t)}function zo(n,t){var r;if("function"!=typeof t)throw new Sn(i);return n=gf(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=u),r}}var Eo=Ye((function(n,t,r){var e=1;if(r.length){var u=sr(r,ai(Eo));e|=c}return Qu(n,e,t,r,u)})),So=Ye((function(n,t,r){var e=3;if(r.length){var u=sr(r,ai(So));e|=c}return Qu(t,e,n,r,u)}));function Wo(n,t,r){var e,o,f,a,c,l,s=0,h=!1,p=!1,v=!0;if("function"!=typeof n)throw new Sn(i);function _(t){var r=e,i=o;return e=o=u,s=t,a=n.apply(i,r)}function g(n){var r=n-l;return l===u||r>=t||r<0||p&&n-s>=f}function y(){var n=Oo();if(g(n))return d(n);c=Si(y,function(n){var r=t-(n-l);return p?wr(r,f-(n-s)):r}(n))}function d(n){return c=u,v&&e?_(n):(e=o=u,a)}function b(){var n=Oo(),r=g(n);if(e=arguments,o=this,l=n,r){if(c===u)return function(n){return s=n,c=Si(y,t),h?_(n):a}(l);if(p)return ju(c),c=Si(y,t),_(l)}return c===u&&(c=Si(y,t)),a}return t=df(t)||0,tf(r)&&(h=!!r.leading,f=(p="maxWait"in r)?br(df(r.maxWait)||0,t):f,v="trailing"in r?!!r.trailing:v),b.cancel=function(){c!==u&&ju(c),s=0,e=l=o=c=u},b.flush=function(){return c===u?a:d(Oo())},b}var Lo=Ye((function(n,t){return se(n,1,t)})),Co=Ye((function(n,t,r){return se(n,df(t)||0,r)}));function To(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new Sn(i);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(To.Cache||Gr),r}function Uo(n){if("function"!=typeof n)throw new Sn(i);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}To.Cache=Gr;var Bo=mu((function(n,t){var r=(t=1==t.length&&Zo(t[0])?Ut(t[0],nr(ci())):Ut(de(t,1),nr(ci()))).length;return Ye((function(e){for(var u=-1,i=wr(e.length,r);++u=t})),qo=We(function(){return arguments}())?We:function(n){return rf(n)&&Bn.call(n,"callee")&&!Jn.call(n,"callee")},Zo=e.isArray,Ko=xt?nr(xt):function(n){return rf(n)&&Ie(n)==C};function Vo(n){return null!=n&&nf(n.length)&&!Qo(n)}function Go(n){return rf(n)&&Vo(n)}var Ho=wt||da,Jo=jt?nr(jt):function(n){return rf(n)&&Ie(n)==m};function Yo(n){if(!rf(n))return!1;var t=Ie(n);return t==x||"[object DOMException]"==t||"string"==typeof n.message&&"string"==typeof n.name&&!of(n)}function Qo(n){if(!tf(n))return!1;var t=Ie(n);return t==j||t==A||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Xo(n){return"number"==typeof n&&n==gf(n)}function nf(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=v}function tf(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function rf(n){return null!=n&&"object"==typeof n}var ef=At?nr(At):function(n){return rf(n)&&_i(n)==k};function uf(n){return"number"==typeof n||rf(n)&&Ie(n)==I}function of(n){if(!rf(n)||Ie(n)!=O)return!1;var t=Gn(n);if(null===t)return!0;var r=Bn.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&Un.call(r)==Mn}var ff=kt?nr(kt):function(n){return rf(n)&&Ie(n)==z};var af=It?nr(It):function(n){return rf(n)&&_i(n)==E};function cf(n){return"string"==typeof n||!Zo(n)&&rf(n)&&Ie(n)==S}function lf(n){return"symbol"==typeof n||rf(n)&&Ie(n)==W}var sf=Ot?nr(Ot):function(n){return rf(n)&&nf(n.length)&&!!ct[Ie(n)]};var hf=Vu(De),pf=Vu((function(n,t){return n<=t}));function vf(n){if(!n)return[];if(Vo(n))return cf(n)?_r(n):Eu(n);if(Xn&&n[Xn])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Xn]());var t=_i(n);return(t==k?cr:t==E?hr:Nf)(n)}function _f(n){return n?(n=df(n))===p||n===-1/0?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function gf(n){var t=_f(n),r=t%1;return t==t?r?t-r:t:0}function yf(n){return n?ae(gf(n),0,g):0}function df(n){if("number"==typeof n)return n;if(lf(n))return _;if(tf(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=tf(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=Xt(n);var r=dn.test(n);return r||wn.test(n)?pt(n.slice(2),r?2:8):yn.test(n)?_:+n}function bf(n){return Su(n,Cf(n))}function wf(n){return null==n?"":lu(n)}var mf=Lu((function(n,t){if(Ai(t)||Vo(t))Su(t,Lf(t),n);else for(var r in t)Bn.call(t,r)&&re(n,r,t[r])})),xf=Lu((function(n,t){Su(t,Cf(t),n)})),jf=Lu((function(n,t,r,e){Su(t,Cf(t),n,e)})),Af=Lu((function(n,t,r,e){Su(t,Lf(t),n,e)})),kf=ei(fe);var If=Ye((function(n,t){n=Rn(n);var r=-1,e=t.length,i=e>2?t[2]:u;for(i&&wi(t[0],t[1],i)&&(e=1);++r1),t})),Su(n,ii(n),r),e&&(r=ce(r,7,ti));for(var u=t.length;u--;)hu(r,t[u]);return r}));var $f=ei((function(n,t){return null==n?{}:function(n,t){return Ke(n,t,(function(t,r){return zf(n,r)}))}(n,t)}));function Df(n,t){if(null==n)return{};var r=Ut(ii(n),(function(n){return[n]}));return t=ci(t),Ke(n,r,(function(n,r){return t(n,r[0])}))}var Ff=Yu(Lf),Mf=Yu(Cf);function Nf(n){return null==n?[]:tr(n,Lf(n))}var Pf=Bu((function(n,t,r){return t=t.toLowerCase(),n+(r?qf(t):t)}));function qf(n){return Qf(wf(n).toLowerCase())}function Zf(n){return(n=wf(n))&&n.replace(xn,ir).replace(rt,"")}var Kf=Bu((function(n,t,r){return n+(r?"-":"")+t.toLowerCase()})),Vf=Bu((function(n,t,r){return n+(r?" ":"")+t.toLowerCase()})),Gf=Uu("toLowerCase");var Hf=Bu((function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}));var Jf=Bu((function(n,t,r){return n+(r?" ":"")+Qf(t)}));var Yf=Bu((function(n,t,r){return n+(r?" ":"")+t.toUpperCase()})),Qf=Uu("toUpperCase");function Xf(n,t,r){return n=wf(n),(t=r?u:t)===u?function(n){return ot.test(n)}(n)?function(n){return n.match(ut)||[]}(n):function(n){return n.match(hn)||[]}(n):n.match(t)||[]}var na=Ye((function(n,t){try{return Rt(n,u,t)}catch(n){return Yo(n)?n:new kn(n)}})),ta=ei((function(n,t){return Et(t,(function(t){t=Bi(t),oe(n,t,Eo(n[t],n))})),n}));function ra(n){return function(){return n}}var ea=Fu(),ua=Fu(!0);function ia(n){return n}function oa(n){return Ue("function"==typeof n?n:ce(n,1))}var fa=Ye((function(n,t){return function(r){return Se(r,n,t)}})),aa=Ye((function(n,t){return function(r){return Se(n,r,t)}}));function ca(n,t,r){var e=Lf(t),u=je(t,e);null!=r||tf(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=je(t,Lf(t)));var i=!(tf(r)&&"chain"in r&&!r.chain),o=Qo(n);return Et(u,(function(r){var e=t[r];n[r]=e,o&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=Eu(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,Bt([this.value()],arguments))})})),n}function la(){}var sa=qu(Ut),ha=qu(Wt),pa=qu(Ft);function va(n){return mi(n)?Gt(Bi(n)):function(n){return function(t){return Ae(t,n)}}(n)}var _a=Ku(),ga=Ku(!0);function ya(){return[]}function da(){return!1}var ba=Pu((function(n,t){return n+t}),0),wa=Hu("ceil"),ma=Pu((function(n,t){return n/t}),1),xa=Hu("floor");var ja,Aa=Pu((function(n,t){return n*t}),1),ka=Hu("round"),Ia=Pu((function(n,t){return n-t}),0);return Mr.after=function(n,t){if("function"!=typeof t)throw new Sn(i);return n=gf(n),function(){if(--n<1)return t.apply(this,arguments)}},Mr.ary=Ro,Mr.assign=mf,Mr.assignIn=xf,Mr.assignInWith=jf,Mr.assignWith=Af,Mr.at=kf,Mr.before=zo,Mr.bind=Eo,Mr.bindAll=ta,Mr.bindKey=So,Mr.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Zo(n)?n:[n]},Mr.chain=ho,Mr.chunk=function(n,t,r){t=(r?wi(n,t,r):t===u)?1:br(gf(t),0);var i=null==n?0:n.length;if(!i||t<1)return[];for(var o=0,f=0,a=e(_t(i/t));oi?0:i+r),(e=e===u||e>i?i:gf(e))<0&&(e+=i),e=r>e?0:yf(e);r>>0)?(n=wf(n))&&("string"==typeof t||null!=t&&!ff(t))&&!(t=lu(t))&&ar(n)?xu(_r(n),0,r):n.split(t,r):[]},Mr.spread=function(n,t){if("function"!=typeof n)throw new Sn(i);return t=null==t?0:br(gf(t),0),Ye((function(r){var e=r[t],u=xu(r,0,t);return e&&Bt(u,e),Rt(n,this,u)}))},Mr.tail=function(n){var t=null==n?0:n.length;return t?uu(n,1,t):[]},Mr.take=function(n,t,r){return n&&n.length?uu(n,0,(t=r||t===u?1:gf(t))<0?0:t):[]},Mr.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?uu(n,(t=e-(t=r||t===u?1:gf(t)))<0?0:t,e):[]},Mr.takeRightWhile=function(n,t){return n&&n.length?vu(n,ci(t,3),!1,!0):[]},Mr.takeWhile=function(n,t){return n&&n.length?vu(n,ci(t,3)):[]},Mr.tap=function(n,t){return t(n),n},Mr.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new Sn(i);return tf(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Wo(n,t,{leading:e,maxWait:t,trailing:u})},Mr.thru=po,Mr.toArray=vf,Mr.toPairs=Ff,Mr.toPairsIn=Mf,Mr.toPath=function(n){return Zo(n)?Ut(n,Bi):lf(n)?[n]:Eu(Ui(wf(n)))},Mr.toPlainObject=bf,Mr.transform=function(n,t,r){var e=Zo(n),u=e||Ho(n)||sf(n);if(t=ci(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:tf(n)&&Qo(i)?Nr(Gn(n)):{}}return(u?Et:me)(n,(function(n,e,u){return t(r,n,e,u)})),r},Mr.unary=function(n){return Ro(n,1)},Mr.union=to,Mr.unionBy=ro,Mr.unionWith=eo,Mr.uniq=function(n){return n&&n.length?su(n):[]},Mr.uniqBy=function(n,t){return n&&n.length?su(n,ci(t,2)):[]},Mr.uniqWith=function(n,t){return t="function"==typeof t?t:u,n&&n.length?su(n,u,t):[]},Mr.unset=function(n,t){return null==n||hu(n,t)},Mr.unzip=uo,Mr.unzipWith=io,Mr.update=function(n,t,r){return null==n?n:pu(n,t,bu(r))},Mr.updateWith=function(n,t,r,e){return e="function"==typeof e?e:u,null==n?n:pu(n,t,bu(r),e)},Mr.values=Nf,Mr.valuesIn=function(n){return null==n?[]:tr(n,Cf(n))},Mr.without=oo,Mr.words=Xf,Mr.wrap=function(n,t){return $o(bu(t),n)},Mr.xor=fo,Mr.xorBy=ao,Mr.xorWith=co,Mr.zip=lo,Mr.zipObject=function(n,t){return yu(n||[],t||[],re)},Mr.zipObjectDeep=function(n,t){return yu(n||[],t||[],nu)},Mr.zipWith=so,Mr.entries=Ff,Mr.entriesIn=Mf,Mr.extend=xf,Mr.extendWith=jf,ca(Mr,Mr),Mr.add=ba,Mr.attempt=na,Mr.camelCase=Pf,Mr.capitalize=qf,Mr.ceil=wa,Mr.clamp=function(n,t,r){return r===u&&(r=t,t=u),r!==u&&(r=(r=df(r))==r?r:0),t!==u&&(t=(t=df(t))==t?t:0),ae(df(n),t,r)},Mr.clone=function(n){return ce(n,4)},Mr.cloneDeep=function(n){return ce(n,5)},Mr.cloneDeepWith=function(n,t){return ce(n,5,t="function"==typeof t?t:u)},Mr.cloneWith=function(n,t){return ce(n,4,t="function"==typeof t?t:u)},Mr.conformsTo=function(n,t){return null==t||le(n,t,Lf(t))},Mr.deburr=Zf,Mr.defaultTo=function(n,t){return null==n||n!=n?t:n},Mr.divide=ma,Mr.endsWith=function(n,t,r){n=wf(n),t=lu(t);var e=n.length,i=r=r===u?e:ae(gf(r),0,e);return(r-=t.length)>=0&&n.slice(r,i)==t},Mr.eq=Mo,Mr.escape=function(n){return(n=wf(n))&&Y.test(n)?n.replace(H,or):n},Mr.escapeRegExp=function(n){return(n=wf(n))&&on.test(n)?n.replace(un,"\\$&"):n},Mr.every=function(n,t,r){var e=Zo(n)?Wt:_e;return r&&wi(n,t,r)&&(t=u),e(n,ci(t,3))},Mr.find=go,Mr.findIndex=Pi,Mr.findKey=function(n,t){return Nt(n,ci(t,3),me)},Mr.findLast=yo,Mr.findLastIndex=qi,Mr.findLastKey=function(n,t){return Nt(n,ci(t,3),xe)},Mr.floor=xa,Mr.forEach=bo,Mr.forEachRight=wo,Mr.forIn=function(n,t){return null==n?n:be(n,ci(t,3),Cf)},Mr.forInRight=function(n,t){return null==n?n:we(n,ci(t,3),Cf)},Mr.forOwn=function(n,t){return n&&me(n,ci(t,3))},Mr.forOwnRight=function(n,t){return n&&xe(n,ci(t,3))},Mr.get=Rf,Mr.gt=No,Mr.gte=Po,Mr.has=function(n,t){return null!=n&&gi(n,t,Re)},Mr.hasIn=zf,Mr.head=Ki,Mr.identity=ia,Mr.includes=function(n,t,r,e){n=Vo(n)?n:Nf(n),r=r&&!e?gf(r):0;var u=n.length;return r<0&&(r=br(u+r,0)),cf(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&qt(n,t,r)>-1},Mr.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:gf(r);return u<0&&(u=br(e+u,0)),qt(n,t,u)},Mr.inRange=function(n,t,r){return t=_f(t),r===u?(r=t,t=0):r=_f(r),function(n,t,r){return n>=wr(t,r)&&n=-9007199254740991&&n<=v},Mr.isSet=af,Mr.isString=cf,Mr.isSymbol=lf,Mr.isTypedArray=sf,Mr.isUndefined=function(n){return n===u},Mr.isWeakMap=function(n){return rf(n)&&_i(n)==L},Mr.isWeakSet=function(n){return rf(n)&&"[object WeakSet]"==Ie(n)},Mr.join=function(n,t){return null==n?"":Mt.call(n,t)},Mr.kebabCase=Kf,Mr.last=Ji,Mr.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var i=e;return r!==u&&(i=(i=gf(r))<0?br(e+i,0):wr(i,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,i):Pt(n,Kt,i,!0)},Mr.lowerCase=Vf,Mr.lowerFirst=Gf,Mr.lt=hf,Mr.lte=pf,Mr.max=function(n){return n&&n.length?ge(n,ia,Oe):u},Mr.maxBy=function(n,t){return n&&n.length?ge(n,ci(t,2),Oe):u},Mr.mean=function(n){return Vt(n,ia)},Mr.meanBy=function(n,t){return Vt(n,ci(t,2))},Mr.min=function(n){return n&&n.length?ge(n,ia,De):u},Mr.minBy=function(n,t){return n&&n.length?ge(n,ci(t,2),De):u},Mr.stubArray=ya,Mr.stubFalse=da,Mr.stubObject=function(){return{}},Mr.stubString=function(){return""},Mr.stubTrue=function(){return!0},Mr.multiply=Aa,Mr.nth=function(n,t){return n&&n.length?qe(n,gf(t)):u},Mr.noConflict=function(){return gt._===this&&(gt._=Nn),this},Mr.noop=la,Mr.now=Oo,Mr.pad=function(n,t,r){n=wf(n);var e=(t=gf(t))?vr(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return Zu(yt(u),r)+n+Zu(_t(u),r)},Mr.padEnd=function(n,t,r){n=wf(n);var e=(t=gf(t))?vr(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var i=jr();return wr(n+i*(t-n+ht("1e-"+((i+"").length-1))),t)}return He(n,t)},Mr.reduce=function(n,t,r){var e=Zo(n)?$t:Jt,u=arguments.length<3;return e(n,ci(t,4),r,u,pe)},Mr.reduceRight=function(n,t,r){var e=Zo(n)?Dt:Jt,u=arguments.length<3;return e(n,ci(t,4),r,u,ve)},Mr.repeat=function(n,t,r){return t=(r?wi(n,t,r):t===u)?1:gf(t),Je(wf(n),t)},Mr.replace=function(){var n=arguments,t=wf(n[0]);return n.length<3?t:t.replace(n[1],n[2])},Mr.result=function(n,t,r){var e=-1,i=(t=wu(t,n)).length;for(i||(i=1,n=u);++ev)return[];var r=g,e=wr(n,g);t=ci(t),n-=g;for(var u=Qt(e,t);++r=o)return n;var a=r-vr(e);if(a<1)return e;var c=f?xu(f,0,a).join(""):n.slice(0,a);if(i===u)return c+e;if(f&&(a+=c.length-a),ff(i)){if(n.slice(a).search(i)){var l,s=c;for(i.global||(i=zn(i.source,wf(gn.exec(i))+"g")),i.lastIndex=0;l=i.exec(s);)var h=l.index;c=c.slice(0,h===u?a:h)}}else if(n.indexOf(lu(i),a)!=a){var p=c.lastIndexOf(i);p>-1&&(c=c.slice(0,p))}return c+e},Mr.unescape=function(n){return(n=wf(n))&&J.test(n)?n.replace(G,yr):n},Mr.uniqueId=function(n){var t=++$n;return wf(n)+t},Mr.upperCase=Yf,Mr.upperFirst=Qf,Mr.each=bo,Mr.eachRight=wo,Mr.first=Ki,ca(Mr,(ja={},me(Mr,(function(n,t){Bn.call(Mr.prototype,t)||(ja[t]=n)})),ja),{chain:!1}),Mr.VERSION="4.18.1",Et(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(n){Mr[n].placeholder=Mr})),Et(["drop","take"],(function(n,t){Zr.prototype[n]=function(r){r=r===u?1:br(gf(r),0);var e=this.__filtered__&&!t?new Zr(this):this.clone();return e.__filtered__?e.__takeCount__=wr(r,e.__takeCount__):e.__views__.push({size:wr(r,g),type:n+(e.__dir__<0?"Right":"")}),e},Zr.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}})),Et(["filter","map","takeWhile"],(function(n,t){var r=t+1,e=1==r||3==r;Zr.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:ci(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}})),Et(["head","last"],(function(n,t){var r="take"+(t?"Right":"");Zr.prototype[n]=function(){return this[r](1).value()[0]}})),Et(["initial","tail"],(function(n,t){var r="drop"+(t?"":"Right");Zr.prototype[n]=function(){return this.__filtered__?new Zr(this):this[r](1)}})),Zr.prototype.compact=function(){return this.filter(ia)},Zr.prototype.find=function(n){return this.filter(n).head()},Zr.prototype.findLast=function(n){return this.reverse().find(n)},Zr.prototype.invokeMap=Ye((function(n,t){return"function"==typeof n?new Zr(this):this.map((function(r){return Se(r,n,t)}))})),Zr.prototype.reject=function(n){return this.filter(Uo(ci(n)))},Zr.prototype.slice=function(n,t){n=gf(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Zr(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==u&&(r=(t=gf(t))<0?r.dropRight(-t):r.take(t-n)),r)},Zr.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Zr.prototype.toArray=function(){return this.take(g)},me(Zr.prototype,(function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),i=Mr[e?"take"+("last"==t?"Right":""):t],o=e||/^find/.test(t);i&&(Mr.prototype[t]=function(){var t=this.__wrapped__,f=e?[1]:arguments,a=t instanceof Zr,c=f[0],l=a||Zo(t),s=function(n){var t=i.apply(Mr,Bt([n],f));return e&&h?t[0]:t};l&&r&&"function"==typeof c&&1!=c.length&&(a=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,_=a&&!p;if(!o&&l){t=_?t:new Zr(this);var g=n.apply(t,f);return g.__actions__.push({func:po,args:[s],thisArg:u}),new qr(g,h)}return v&&_?n.apply(this,f):(g=this.thru(s),v?e?g.value()[0]:g.value():g)})})),Et(["pop","push","shift","sort","splice","unshift"],(function(n){var t=Wn[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);Mr.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Zo(u)?u:[],n)}return this[r]((function(r){return t.apply(Zo(r)?r:[],n)}))}})),me(Zr.prototype,(function(n,t){var r=Mr[t];if(r){var e=r.name+"";Bn.call(Wr,e)||(Wr[e]=[]),Wr[e].push({name:t,func:r})}})),Wr[Mu(u,2).name]=[{name:"wrapper",func:u}],Zr.prototype.clone=function(){var n=new Zr(this.__wrapped__);return n.__actions__=Eu(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Eu(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Eu(this.__views__),n},Zr.prototype.reverse=function(){if(this.__filtered__){var n=new Zr(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},Zr.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=Zo(n),e=t<0,u=r?n.length:0,i=function(n,t,r){var e=-1,u=r.length;for(;++e=this.__values__.length;return{done:n,value:n?u:this.__values__[this.__index__++]}},Mr.prototype.plant=function(n){for(var t,r=this;r instanceof Pr;){var e=Di(r);e.__index__=0,e.__values__=u,t?i.__wrapped__=e:t=e;var i=e;r=r.__wrapped__}return i.__wrapped__=n,t},Mr.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof Zr){var t=n;return this.__actions__.length&&(t=new Zr(this)),(t=t.reverse()).__actions__.push({func:po,args:[no],thisArg:u}),new qr(t,this.__chain__)}return this.thru(no)},Mr.prototype.toJSON=Mr.prototype.valueOf=Mr.prototype.value=function(){return _u(this.__wrapped__,this.__actions__)},Mr.prototype.first=Mr.prototype.head,Xn&&(Mr.prototype[Xn]=function(){return this}),Mr}();gt._=dr,(e=function(){return dr}.call(t,r,t,n))===u||(n.exports=e)}.call(this)},7803(n,t,r){n.exports=r(2543)}},t={};function r(e){var u=t[e];if(void 0!==u)return u.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return n[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}return r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),r.nmd=n=>(n.paths=[],n.children||(n.children=[]),n),r(7803)})())); \ No newline at end of file diff --git a/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/lodashFp.js b/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/lodashFp.js index 0fe5ac372..241bf33f6 100644 --- a/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/lodashFp.js +++ b/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/lodashFp.js @@ -1,9 +1,5 @@ -!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.lodashFp=t():n.lodashFp=t()}(this,(()=>(()=>{var n={4480:(n,t,r)=>{var e=r(9761).runInContext();n.exports=r(3424)(e,e)},3424:(n,t,r)=>{var e=r(6962),u=r(2874),i=Array.prototype.push;function o(n,t){return 2==t?function(t,r){return n(t,r)}:function(t){return n(t)}}function a(n){for(var t=n?n.length:0,r=Array(t);t--;)r[t]=n[t];return r}function f(n,t){return function(){var r=arguments.length;if(r){for(var e=Array(r);r--;)e[r]=arguments[r];var u=e[0]=t.apply(void 0,e);return n.apply(void 0,e),u}}}n.exports=function n(t,r,c,l){var s="function"==typeof r,h=r===Object(r);if(h&&(l=c,c=r,r=void 0),null==c)throw new TypeError;l||(l={});var p=!("cap"in l)||l.cap,v=!("curry"in l)||l.curry,g=!("fixed"in l)||l.fixed,_=!("immutable"in l)||l.immutable,d=!("rearg"in l)||l.rearg,y=s?c:u,m="curry"in l&&l.curry,b="fixed"in l&&l.fixed,w="rearg"in l&&l.rearg,x=s?c.runInContext():void 0,A=s?c:{ary:t.ary,assign:t.assign,clone:t.clone,curry:t.curry,forEach:t.forEach,isArray:t.isArray,isError:t.isError,isFunction:t.isFunction,isWeakMap:t.isWeakMap,iteratee:t.iteratee,keys:t.keys,rearg:t.rearg,toInteger:t.toInteger,toPath:t.toPath},I=A.ary,W=A.assign,j=A.clone,R=A.curry,k=A.forEach,O=A.isArray,E=A.isError,S=A.isFunction,z=A.isWeakMap,B=A.keys,L=A.rearg,C=A.toInteger,F=A.toPath,T=B(e.aryMethod),D={castArray:function(n){return function(){var t=arguments[0];return O(t)?n(a(t)):n.apply(void 0,arguments)}},iteratee:function(n){return function(){var t=arguments[1],r=n(arguments[0],t),e=r.length;return p&&"number"==typeof t?(t=t>2?t-2:1,e&&e<=t?r:o(r,t)):r}},mixin:function(n){return function(t){var r=this;if(!S(r))return n(r,Object(t));var e=[];return k(B(t),(function(n){S(t[n])&&e.push([n,r.prototype[n]])})),n(r,Object(t)),k(e,(function(n){var t=n[1];S(t)?r.prototype[n[0]]=t:delete r.prototype[n[0]]})),r}},nthArg:function(n){return function(t){var r=t<0?1:C(t)+1;return R(n(t),r)}},rearg:function(n){return function(t,r){var e=r?r.length:0;return R(n(t,r),e)}},runInContext:function(r){return function(e){return n(t,r(e),l)}}};function M(n,t){if(p){var r=e.iterateeRearg[n];if(r)return function(n,t){return N(n,(function(n){var r=t.length;return function(n,t){return 2==t?function(t,r){return n.apply(void 0,arguments)}:function(t){return n.apply(void 0,arguments)}}(L(o(n,r),t),r)}))}(t,r);var u=!s&&e.iterateeAry[n];if(u)return function(n,t){return N(n,(function(n){return"function"==typeof n?o(n,t):n}))}(t,u)}return t}function U(n,t,r){if(g&&(b||!e.skipFixed[n])){var u=e.methodSpread[n],o=u&&u.start;return void 0===o?I(t,r):function(n,t){return function(){for(var r=arguments.length,e=r-1,u=Array(r);r--;)u[r]=arguments[r];var o=u[t],a=u.slice(0,t);return o&&i.apply(a,o),t!=e&&i.apply(a,u.slice(t+1)),n.apply(this,a)}}(t,o)}return t}function P(n,t,r){return d&&r>1&&(w||!e.skipRearg[n])?L(t,e.methodRearg[n]||e.aryRearg[r]):t}function q(n,t){for(var r=-1,e=(t=F(t)).length,u=e-1,i=j(Object(n)),o=i;null!=o&&++r1?R(t,r):t}(0,u=M(i,u),n),!1}})),!u})),u||(u=o),u==t&&(u=m?R(u,1):function(){return t.apply(this,arguments)}),u.convert=$(i,t),u.placeholder=t.placeholder=r,u}if(!h)return K(r,c,y);var Z=c,V=[];return k(T,(function(n){k(e.aryMethod[n],(function(n){var t=Z[e.remap[n]||n];t&&V.push([n,K(n,t,Z)])}))})),k(B(Z),(function(n){var t=Z[n];if("function"==typeof t){for(var r=V.length;r--;)if(V[r][0]==n)return;t.convert=$(n,t),V.push([n,t])}})),k(V,(function(n){Z[n[0]]=n[1]})),Z.convert=function(n){return Z.runInContext.convert(n)(void 0)},Z.placeholder=Z,k(B(Z),(function(n){k(e.realToAlias[n]||[],(function(t){Z[t]=Z[n]}))})),Z}},6962:(n,t)=>{t.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},t.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],4:["fill","setWith","updateWith"]},t.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},t.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},t.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},t.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},t.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},t.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},t.realToAlias=function(){var n=Object.prototype.hasOwnProperty,r=t.aliasToReal,e={};for(var u in r){var i=r[u];n.call(e,i)?e[i].push(u):e[i]=[u]}return e}(),t.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},t.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},t.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},2874:n=>{n.exports={}},9761:function(n,t,r){var e; +!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.lodashFp=t():n.lodashFp=t()}(this,(()=>(()=>{var n={4480(n,t,r){var e=r(9761).runInContext();n.exports=r(3424)(e,e)},3424(n,t,r){var e=r(6962),u=r(2874),i=Array.prototype.push;function o(n,t){return 2==t?function(t,r){return n(t,r)}:function(t){return n(t)}}function a(n){for(var t=n?n.length:0,r=Array(t);t--;)r[t]=n[t];return r}function f(n,t){return function(){var r=arguments.length;if(r){for(var e=Array(r);r--;)e[r]=arguments[r];var u=e[0]=t.apply(void 0,e);return n.apply(void 0,e),u}}}n.exports=function n(t,r,c,l){var s="function"==typeof r,h=r===Object(r);if(h&&(l=c,c=r,r=void 0),null==c)throw new TypeError;l||(l={});var p=!("cap"in l)||l.cap,v=!("curry"in l)||l.curry,g=!("fixed"in l)||l.fixed,_=!("immutable"in l)||l.immutable,d=!("rearg"in l)||l.rearg,y=s?c:u,m="curry"in l&&l.curry,b="fixed"in l&&l.fixed,w="rearg"in l&&l.rearg,x=s?c.runInContext():void 0,A=s?c:{ary:t.ary,assign:t.assign,clone:t.clone,curry:t.curry,forEach:t.forEach,isArray:t.isArray,isError:t.isError,isFunction:t.isFunction,isWeakMap:t.isWeakMap,iteratee:t.iteratee,keys:t.keys,rearg:t.rearg,toInteger:t.toInteger,toPath:t.toPath},I=A.ary,W=A.assign,j=A.clone,R=A.curry,k=A.forEach,O=A.isArray,E=A.isError,z=A.isFunction,S=A.isWeakMap,B=A.keys,L=A.rearg,C=A.toInteger,F=A.toPath,T=B(e.aryMethod),D={castArray:function(n){return function(){var t=arguments[0];return O(t)?n(a(t)):n.apply(void 0,arguments)}},iteratee:function(n){return function(){var t=arguments[1],r=n(arguments[0],t),e=r.length;return p&&"number"==typeof t?(t=t>2?t-2:1,e&&e<=t?r:o(r,t)):r}},mixin:function(n){return function(t){var r=this;if(!z(r))return n(r,Object(t));var e=[];return k(B(t),(function(n){z(t[n])&&e.push([n,r.prototype[n]])})),n(r,Object(t)),k(e,(function(n){var t=n[1];z(t)?r.prototype[n[0]]=t:delete r.prototype[n[0]]})),r}},nthArg:function(n){return function(t){var r=t<0?1:C(t)+1;return R(n(t),r)}},rearg:function(n){return function(t,r){var e=r?r.length:0;return R(n(t,r),e)}},runInContext:function(r){return function(e){return n(t,r(e),l)}}};function M(n,t){if(p){var r=e.iterateeRearg[n];if(r)return function(n,t){return N(n,(function(n){var r=t.length;return function(n,t){return 2==t?function(t,r){return n.apply(void 0,arguments)}:function(t){return n.apply(void 0,arguments)}}(L(o(n,r),t),r)}))}(t,r);var u=!s&&e.iterateeAry[n];if(u)return function(n,t){return N(n,(function(n){return"function"==typeof n?o(n,t):n}))}(t,u)}return t}function U(n,t,r){if(g&&(b||!e.skipFixed[n])){var u=e.methodSpread[n],o=u&&u.start;return void 0===o?I(t,r):function(n,t){return function(){for(var r=arguments.length,e=r-1,u=Array(r);r--;)u[r]=arguments[r];var o=u[t],a=u.slice(0,t);return o&&i.apply(a,o),t!=e&&i.apply(a,u.slice(t+1)),n.apply(this,a)}}(t,o)}return t}function P(n,t,r){return d&&r>1&&(w||!e.skipRearg[n])?L(t,e.methodRearg[n]||e.aryRearg[r]):t}function q(n,t){for(var r=-1,e=(t=F(t)).length,u=e-1,i=j(Object(n)),o=i;null!=o&&++r1?R(t,r):t}(0,u=M(i,u),n),!1}})),!u})),u||(u=o),u==t&&(u=m?R(u,1):function(){return t.apply(this,arguments)}),u.convert=$(i,t),u.placeholder=t.placeholder=r,u}if(!h)return K(r,c,y);var Z=c,V=[];return k(T,(function(n){k(e.aryMethod[n],(function(n){var t=Z[e.remap[n]||n];t&&V.push([n,K(n,t,Z)])}))})),k(B(Z),(function(n){var t=Z[n];if("function"==typeof t){for(var r=V.length;r--;)if(V[r][0]==n)return;t.convert=$(n,t),V.push([n,t])}})),k(V,(function(n){Z[n[0]]=n[1]})),Z.convert=function(n){return Z.runInContext.convert(n)(void 0)},Z.placeholder=Z,k(B(Z),(function(n){k(e.realToAlias[n]||[],(function(t){Z[t]=Z[n]}))})),Z}},6962(n,t){t.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},t.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],4:["fill","setWith","updateWith"]},t.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},t.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},t.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},t.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},t.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},t.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},t.realToAlias=function(){var n=Object.prototype.hasOwnProperty,r=t.aliasToReal,e={};for(var u in r){var i=r[u];n.call(e,i)?e[i].push(u):e[i]=[u]}return e}(),t.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},t.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},t.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},2874(n){n.exports={}},9761(n,t,r){var e; /** * @license - * Lodash - * Copyright OpenJS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */n=r.nmd(n),function(){function u(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function i(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function s(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function L(n,t){for(var r=n.length;r--&&b(t,n[r],0)>-1;);return r}function C(n){return"\\"+tr[n]}function F(n){return Ht.test(n)}function T(n){return Jt.test(n)}function D(n){var t=-1,r=Array(n.size);return n.forEach((function(n,e){r[++t]=[e,n]})),r}function M(n,t){return function(r){return n(t(r))}}function U(n,t){for(var r=-1,e=n.length,u=0,i=[];++r>>1,fn=[["ary",X],["bind",1],["bindKey",2],["curry",8],["curryRight",J],["flip",512],["partial",Y],["partialRight",Q],["rearg",nn]],cn="[object Arguments]",ln="[object Array]",sn="[object Boolean]",hn="[object Date]",pn="[object Error]",vn="[object Function]",gn="[object GeneratorFunction]",_n="[object Map]",dn="[object Number]",yn="[object Object]",mn="[object Promise]",bn="[object RegExp]",wn="[object Set]",xn="[object String]",An="[object Symbol]",In="[object WeakMap]",Wn="[object ArrayBuffer]",jn="[object DataView]",Rn="[object Float32Array]",kn="[object Float64Array]",On="[object Int8Array]",En="[object Int16Array]",Sn="[object Int32Array]",zn="[object Uint8Array]",Bn="[object Uint8ClampedArray]",Ln="[object Uint16Array]",Cn="[object Uint32Array]",Fn=/\b__p \+= '';/g,Tn=/\b(__p \+=) '' \+/g,Dn=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Mn=/&(?:amp|lt|gt|quot|#39);/g,Un=/[&<>"']/g,Pn=RegExp(Mn.source),qn=RegExp(Un.source),$n=/<%-([\s\S]+?)%>/g,Nn=/<%([\s\S]+?)%>/g,Kn=/<%=([\s\S]+?)%>/g,Zn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Vn=/^\w*$/,Gn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Hn=/[\\^$.*+?()[\]{}|]/g,Jn=RegExp(Hn.source),Yn=/^\s+/,Qn=/\s/,Xn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,nt=/\{\n\/\* \[wrapped with (.+)\] \*/,tt=/,? & /,rt=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,et=/[()=,{}\[\]\/\s]/,ut=/\\(\\)?/g,it=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,ot=/\w*$/,at=/^[-+]0x[0-9a-f]+$/i,ft=/^0b[01]+$/i,ct=/^\[object .+?Constructor\]$/,lt=/^0o[0-7]+$/i,st=/^(?:0|[1-9]\d*)$/,ht=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,pt=/($^)/,vt=/['\n\r\u2028\u2029\\]/g,gt="\\ud800-\\udfff",_t="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",dt="\\u2700-\\u27bf",yt="a-z\\xdf-\\xf6\\xf8-\\xff",mt="A-Z\\xc0-\\xd6\\xd8-\\xde",bt="\\ufe0e\\ufe0f",wt="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",xt="['’]",At="["+gt+"]",It="["+wt+"]",Wt="["+_t+"]",jt="\\d+",Rt="["+dt+"]",kt="["+yt+"]",Ot="[^"+gt+wt+jt+dt+yt+mt+"]",Et="\\ud83c[\\udffb-\\udfff]",St="[^"+gt+"]",zt="(?:\\ud83c[\\udde6-\\uddff]){2}",Bt="[\\ud800-\\udbff][\\udc00-\\udfff]",Lt="["+mt+"]",Ct="\\u200d",Ft="(?:"+kt+"|"+Ot+")",Tt="(?:"+Lt+"|"+Ot+")",Dt="(?:['’](?:d|ll|m|re|s|t|ve))?",Mt="(?:['’](?:D|LL|M|RE|S|T|VE))?",Ut="(?:"+Wt+"|"+Et+")"+"?",Pt="["+bt+"]?",qt=Pt+Ut+("(?:"+Ct+"(?:"+[St,zt,Bt].join("|")+")"+Pt+Ut+")*"),$t="(?:"+[Rt,zt,Bt].join("|")+")"+qt,Nt="(?:"+[St+Wt+"?",Wt,zt,Bt,At].join("|")+")",Kt=RegExp(xt,"g"),Zt=RegExp(Wt,"g"),Vt=RegExp(Et+"(?="+Et+")|"+Nt+qt,"g"),Gt=RegExp([Lt+"?"+kt+"+"+Dt+"(?="+[It,Lt,"$"].join("|")+")",Tt+"+"+Mt+"(?="+[It,Lt+Ft,"$"].join("|")+")",Lt+"?"+Ft+"+"+Dt,Lt+"+"+Mt,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",jt,$t].join("|"),"g"),Ht=RegExp("["+Ct+gt+_t+bt+"]"),Jt=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Yt=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Qt=-1,Xt={};Xt[Rn]=Xt[kn]=Xt[On]=Xt[En]=Xt[Sn]=Xt[zn]=Xt[Bn]=Xt[Ln]=Xt[Cn]=!0,Xt[cn]=Xt[ln]=Xt[Wn]=Xt[sn]=Xt[jn]=Xt[hn]=Xt[pn]=Xt[vn]=Xt[_n]=Xt[dn]=Xt[yn]=Xt[bn]=Xt[wn]=Xt[xn]=Xt[In]=!1;var nr={};nr[cn]=nr[ln]=nr[Wn]=nr[jn]=nr[sn]=nr[hn]=nr[Rn]=nr[kn]=nr[On]=nr[En]=nr[Sn]=nr[_n]=nr[dn]=nr[yn]=nr[bn]=nr[wn]=nr[xn]=nr[An]=nr[zn]=nr[Bn]=nr[Ln]=nr[Cn]=!0,nr[pn]=nr[vn]=nr[In]=!1;var tr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},rr=parseFloat,er=parseInt,ur="object"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,ir="object"==typeof self&&self&&self.Object===Object&&self,or=ur||ir||Function("return this")(),ar=t&&!t.nodeType&&t,fr=ar&&n&&!n.nodeType&&n,cr=fr&&fr.exports===ar,lr=cr&&ur.process,sr=function(){try{var n=fr&&fr.require&&fr.require("util").types;return n||lr&&lr.binding&&lr.binding("util")}catch(n){}}(),hr=sr&&sr.isArrayBuffer,pr=sr&&sr.isDate,vr=sr&&sr.isMap,gr=sr&&sr.isRegExp,_r=sr&&sr.isSet,dr=sr&&sr.isTypedArray,yr=I("length"),mr=W({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"}),br=W({"&":"&","<":"<",">":">",'"':""","'":"'"}),wr=W({"&":"&","<":"<",">":">",""":'"',"'":"'"}),xr=function n(t){function r(n){if(Uu(n)&&!Ea(n)&&!(n instanceof Qn)){if(n instanceof W)return n;if(Oi.call(n,"__wrapped__"))return hu(n)}return new W(n)}function e(){}function W(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=Z}function Qn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=un,this.__views__=[]}function rt(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function St(n,t,r,e,u,i){var a,f=1&t,c=2&t,l=4&t;if(r&&(a=u?r(n,e,u,i):r(n)),a!==Z)return a;if(!Mu(n))return n;var s=Ea(n);if(s){if(a=function(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&Oi.call(n,"index")&&(r.index=n.index,r.input=n.input),r}(n),!f)return le(n,a)}else{var h=Uo(n),p=h==vn||h==gn;if(za(n))return ue(n,f);if(h==yn||h==cn||p&&!u){if(a=c||p?{}:Ge(n),!f)return c?function(n,t){return se(n,Mo(n),t)}(n,function(n,t){return n&&se(t,ti(t),n)}(a,n)):function(n,t){return se(n,Do(n),t)}(n,Rt(a,n))}else{if(!nr[h])return u?n:{};a=function(n,t,r){var e=n.constructor;switch(t){case Wn:return ie(n);case sn:case hn:return new e(+n);case jn:return function(n,t){return new n.constructor(t?ie(n.buffer):n.buffer,n.byteOffset,n.byteLength)}(n,r);case Rn:case kn:case On:case En:case Sn:case zn:case Bn:case Ln:case Cn:return oe(n,r);case _n:return new e;case dn:case xn:return new e(n);case bn:return function(n){var t=new n.constructor(n.source,ot.exec(n));return t.lastIndex=n.lastIndex,t}(n);case wn:return new e;case An:return function(n){return Wo?bi(Wo.call(n)):{}}(n)}}(n,h,f)}}i||(i=new yt);var v=i.get(n);if(v)return v;i.set(n,a),Fa(n)?n.forEach((function(e){a.add(St(e,t,r,e,n,i))})):La(n)&&n.forEach((function(e,u){a.set(u,St(e,t,r,u,n,i))}));var g=s?Z:(l?c?Ue:Me:c?ti:ni)(n);return o(g||n,(function(e,u){g&&(e=n[u=e]),It(a,u,St(e,t,r,u,n,i))})),a}function zt(n,t,r){var e=r.length;if(null==n)return!e;for(n=bi(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===Z&&!(u in n)||!i(o))return!1}return!0}function Bt(n,t,r){if("function"!=typeof n)throw new Ai(V);return $o((function(){n.apply(Z,r)}),t)}function Lt(n,t,r,e){var u=-1,i=l,o=!0,a=n.length,f=[],c=t.length;if(!a)return f;r&&(t=h(t,E(r))),e?(i=s,o=!1):t.length>=200&&(i=z,o=!1,t=new dt(t));n:for(;++u0&&r(a)?t>1?Dt(a,t-1,r,e,u):p(u,a):e||(u[u.length]=a)}return u}function Mt(n,t){return n&&Eo(n,t,ni)}function Ut(n,t){return n&&So(n,t,ni)}function Pt(n,t){return c(t,(function(t){return Fu(n[t])}))}function qt(n,t){for(var r=0,e=(t=re(t,n)).length;null!=n&&rt}function Gt(n,t){return null!=n&&Oi.call(n,t)}function Ht(n,t){return null!=n&&t in bi(n)}function Jt(n,t,r){for(var e=r?s:l,u=n[0].length,i=n.length,o=i,a=gi(i),f=1/0,c=[];o--;){var p=n[o];o&&t&&(p=h(p,E(t))),f=io(p.length,f),a[o]=!r&&(t||u>=120&&p.length>=120)?new dt(o&&p):Z}p=n[0];var v=-1,g=a[0];n:for(;++v=a?f:f*("desc"==r[e]?-1:1)}return n.index-t.index}(n,t,r)}))}function Er(n,t,r){for(var e=-1,u=t.length,i={};++e-1;)a!==n&&$i.call(a,f,1),$i.call(n,f,1);return n}function zr(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Je(u)?$i.call(n,u,1):Gr(n,u)}}return n}function Br(n,t){return n+Qi(fo()*(t-n+1))}function Lr(n,t){var r="";if(!n||t<1||t>rn)return r;do{t%2&&(r+=n),(t=Qi(t/2))&&(n+=n)}while(t);return r}function Cr(n,t){return No(eu(n,t,fi),n+"")}function Fr(n){return bt(ei(n))}function Tr(n,t){var r=ei(n);return fu(r,Et(t,0,r.length))}function Dr(n,t,r,e){if(!Mu(n))return n;for(var u=-1,i=(t=re(t,n)).length,o=i-1,a=n;null!=a&&++uu?0:u+t),(r=r>u?u:r)<0&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0;for(var i=gi(u);++e>>1,o=n[i];null!==o&&!Nu(o)&&(r?o<=t:o=200){var c=t?null:Fo(n);if(c)return P(c);o=!1,u=z,f=new dt}else f=t?[]:a;n:for(;++e=e?n:Ur(n,t,r)}function ue(n,t){if(t)return n.slice();var r=n.length,e=Mi?Mi(r):new n.constructor(r);return n.copy(e),e}function ie(n){var t=new n.constructor(n.byteLength);return new Di(t).set(new Di(n)),t}function oe(n,t){return new n.constructor(t?ie(n.buffer):n.buffer,n.byteOffset,n.length)}function ae(n,t){if(n!==t){var r=n!==Z,e=null===n,u=n==n,i=Nu(n),o=t!==Z,a=null===t,f=t==t,c=Nu(t);if(!a&&!c&&!i&&n>t||i&&o&&f&&!a&&!c||e&&o&&f||!r&&f||!u)return 1;if(!e&&!i&&!c&&n1?r[u-1]:Z,o=u>2?r[2]:Z;for(i=n.length>3&&"function"==typeof i?(u--,i):Z,o&&Ye(r[0],r[1],o)&&(i=u<3?Z:i,u=1),t=bi(t);++e-1?u[i?t[o]:o]:Z}}function we(n){return De((function(t){var r=t.length,e=r,u=W.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if("function"!=typeof i)throw new Ai(V);if(u&&!o&&"wrapper"==Pe(i))var o=new W([],!0)}for(e=o?e:r;++e1&&y.reverse(),l&&fa))return!1;var c=i.get(n),l=i.get(t);if(c&&l)return c==t&&l==n;var s=-1,h=!0,p=2&r?new dt:Z;for(i.set(n,t),i.set(t,n);++s-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(Xn,"{\n/* [wrapped with "+t+"] */\n")}(e,su(function(n){var t=n.match(nt);return t?t[1].split(tt):[]}(e),r)))}function au(n){var t=0,r=0;return function(){var e=oo(),u=16-(e-r);if(r=e,u>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(Z,arguments)}}function fu(n,t){var r=-1,e=n.length,u=e-1;for(t=t===Z?e:t;++r0&&(r=t.apply(this,arguments)),n<=1&&(t=Z),r}}function Ou(n,t,r){function e(t){var r=f,e=c;return f=c=Z,v=t,s=n.apply(e,r)}function u(n){var r=n-p;return p===Z||r>=t||r<0||_&&n-v>=l}function i(){var n=ya();return u(n)?o(n):(h=$o(i,function(n){var r=t-(n-p);return _?io(r,l-(n-v)):r}(n)),Z)}function o(n){return h=Z,d&&f?e(n):(f=c=Z,s)}function a(){var n=ya(),r=u(n);if(f=arguments,c=this,p=n,r){if(h===Z)return function(n){return v=n,h=$o(i,t),g?e(n):s}(p);if(_)return Co(h),h=$o(i,t),e(p)}return h===Z&&(h=$o(i,t)),s}var f,c,l,s,h,p,v=0,g=!1,_=!1,d=!0;if("function"!=typeof n)throw new Ai(V);return t=Hu(t)||0,Mu(r)&&(g=!!r.leading,l=(_="maxWait"in r)?uo(Hu(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),a.cancel=function(){h!==Z&&Co(h),v=0,f=p=c=h=Z},a.flush=function(){return h===Z?s:o(ya())},a}function Eu(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new Ai(V);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(Eu.Cache||_t),r}function Su(n){if("function"!=typeof n)throw new Ai(V);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function zu(n,t){return n===t||n!=n&&t!=t}function Bu(n){return null!=n&&Du(n.length)&&!Fu(n)}function Lu(n){return Uu(n)&&Bu(n)}function Cu(n){if(!Uu(n))return!1;var t=Nt(n);return t==pn||"[object DOMException]"==t||"string"==typeof n.message&&"string"==typeof n.name&&!qu(n)}function Fu(n){if(!Mu(n))return!1;var t=Nt(n);return t==vn||t==gn||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Tu(n){return"number"==typeof n&&n==Vu(n)}function Du(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=rn}function Mu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function Uu(n){return null!=n&&"object"==typeof n}function Pu(n){return"number"==typeof n||Uu(n)&&Nt(n)==dn}function qu(n){if(!Uu(n)||Nt(n)!=yn)return!1;var t=Ui(n);if(null===t)return!0;var r=Oi.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&ki.call(r)==Bi}function $u(n){return"string"==typeof n||!Ea(n)&&Uu(n)&&Nt(n)==xn}function Nu(n){return"symbol"==typeof n||Uu(n)&&Nt(n)==An}function Ku(n){if(!n)return[];if(Bu(n))return $u(n)?$(n):le(n);if(Ki&&n[Ki])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Ki]());var t=Uo(n);return(t==_n?D:t==wn?P:ei)(n)}function Zu(n){return n?(n=Hu(n))===tn||n===-tn?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function Vu(n){var t=Zu(n),r=t%1;return t==t?r?t-r:t:0}function Gu(n){return n?Et(Vu(n),0,un):0}function Hu(n){if("number"==typeof n)return n;if(Nu(n))return en;if(Mu(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=Mu(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=O(n);var r=ft.test(n);return r||lt.test(n)?er(n.slice(2),r?2:8):at.test(n)?en:+n}function Ju(n){return se(n,ti(n))}function Yu(n){return null==n?"":Zr(n)}function Qu(n,t,r){var e=null==n?Z:qt(n,t);return e===Z?r:e}function Xu(n,t){return null!=n&&Ve(n,t,Ht)}function ni(n){return Bu(n)?mt(n):sr(n)}function ti(n){return Bu(n)?mt(n,!0):yr(n)}function ri(n,t){if(null==n)return{};var r=h(Ue(n),(function(n){return[n]}));return t=$e(t),Er(n,r,(function(n,r){return t(n,r[0])}))}function ei(n){return null==n?[]:S(n,ni(n))}function ui(n){return lf(Yu(n).toLowerCase())}function ii(n){return(n=Yu(n))&&n.replace(ht,mr).replace(Zt,"")}function oi(n,t,r){return n=Yu(n),(t=r?Z:t)===Z?T(n)?K(n):d(n):n.match(t)||[]}function ai(n){return function(){return n}}function fi(n){return n}function ci(n){return lr("function"==typeof n?n:St(n,1))}function li(n,t,r){var e=ni(t),u=Pt(t,e);null!=r||Mu(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=Pt(t,ni(t)));var i=!(Mu(r)&&"chain"in r&&!r.chain),a=Fu(n);return o(u,(function(r){var e=t[r];n[r]=e,a&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=le(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,p([this.value()],arguments))})})),n}function si(){}function hi(n){return Qe(n)?I(cu(n)):function(n){return function(t){return qt(t,n)}}(n)}function pi(){return[]}function vi(){return!1}var gi=(t=null==t?or:xr.defaults(or.Object(),t,xr.pick(or,Yt))).Array,_i=t.Date,di=t.Error,yi=t.Function,mi=t.Math,bi=t.Object,wi=t.RegExp,xi=t.String,Ai=t.TypeError,Ii=gi.prototype,Wi=yi.prototype,ji=bi.prototype,Ri=t["__core-js_shared__"],ki=Wi.toString,Oi=ji.hasOwnProperty,Ei=0,Si=function(){var n=/[^.]+$/.exec(Ri&&Ri.keys&&Ri.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),zi=ji.toString,Bi=ki.call(bi),Li=or._,Ci=wi("^"+ki.call(Oi).replace(Hn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Fi=cr?t.Buffer:Z,Ti=t.Symbol,Di=t.Uint8Array,Mi=Fi?Fi.allocUnsafe:Z,Ui=M(bi.getPrototypeOf,bi),Pi=bi.create,qi=ji.propertyIsEnumerable,$i=Ii.splice,Ni=Ti?Ti.isConcatSpreadable:Z,Ki=Ti?Ti.iterator:Z,Zi=Ti?Ti.toStringTag:Z,Vi=function(){try{var n=Ze(bi,"defineProperty");return n({},"",{}),n}catch(n){}}(),Gi=t.clearTimeout!==or.clearTimeout&&t.clearTimeout,Hi=_i&&_i.now!==or.Date.now&&_i.now,Ji=t.setTimeout!==or.setTimeout&&t.setTimeout,Yi=mi.ceil,Qi=mi.floor,Xi=bi.getOwnPropertySymbols,no=Fi?Fi.isBuffer:Z,to=t.isFinite,ro=Ii.join,eo=M(bi.keys,bi),uo=mi.max,io=mi.min,oo=_i.now,ao=t.parseInt,fo=mi.random,co=Ii.reverse,lo=Ze(t,"DataView"),so=Ze(t,"Map"),ho=Ze(t,"Promise"),po=Ze(t,"Set"),vo=Ze(t,"WeakMap"),go=Ze(bi,"create"),_o=vo&&new vo,yo={},mo=lu(lo),bo=lu(so),wo=lu(ho),xo=lu(po),Ao=lu(vo),Io=Ti?Ti.prototype:Z,Wo=Io?Io.valueOf:Z,jo=Io?Io.toString:Z,Ro=function(){function n(){}return function(t){if(!Mu(t))return{};if(Pi)return Pi(t);n.prototype=t;var r=new n;return n.prototype=Z,r}}();r.templateSettings={escape:$n,evaluate:Nn,interpolate:Kn,variable:"",imports:{_:r}},r.prototype=e.prototype,r.prototype.constructor=r,W.prototype=Ro(e.prototype),W.prototype.constructor=W,Qn.prototype=Ro(e.prototype),Qn.prototype.constructor=Qn,rt.prototype.clear=function(){this.__data__=go?go(null):{},this.size=0},rt.prototype.delete=function(n){var t=this.has(n)&&delete this.__data__[n];return this.size-=t?1:0,t},rt.prototype.get=function(n){var t=this.__data__;if(go){var r=t[n];return r===G?Z:r}return Oi.call(t,n)?t[n]:Z},rt.prototype.has=function(n){var t=this.__data__;return go?t[n]!==Z:Oi.call(t,n)},rt.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=go&&t===Z?G:t,this},gt.prototype.clear=function(){this.__data__=[],this.size=0},gt.prototype.delete=function(n){var t=this.__data__,r=Wt(t,n);return!(r<0||(r==t.length-1?t.pop():$i.call(t,r,1),--this.size,0))},gt.prototype.get=function(n){var t=this.__data__,r=Wt(t,n);return r<0?Z:t[r][1]},gt.prototype.has=function(n){return Wt(this.__data__,n)>-1},gt.prototype.set=function(n,t){var r=this.__data__,e=Wt(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},_t.prototype.clear=function(){this.size=0,this.__data__={hash:new rt,map:new(so||gt),string:new rt}},_t.prototype.delete=function(n){var t=Ne(this,n).delete(n);return this.size-=t?1:0,t},_t.prototype.get=function(n){return Ne(this,n).get(n)},_t.prototype.has=function(n){return Ne(this,n).has(n)},_t.prototype.set=function(n,t){var r=Ne(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},dt.prototype.add=dt.prototype.push=function(n){return this.__data__.set(n,G),this},dt.prototype.has=function(n){return this.__data__.has(n)},yt.prototype.clear=function(){this.__data__=new gt,this.size=0},yt.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},yt.prototype.get=function(n){return this.__data__.get(n)},yt.prototype.has=function(n){return this.__data__.has(n)},yt.prototype.set=function(n,t){var r=this.__data__;if(r instanceof gt){var e=r.__data__;if(!so||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new _t(e)}return r.set(n,t),this.size=r.size,this};var ko=ve(Mt),Oo=ve(Ut,!0),Eo=ge(),So=ge(!0),zo=_o?function(n,t){return _o.set(n,t),n}:fi,Bo=Vi?function(n,t){return Vi(n,"toString",{configurable:!0,enumerable:!1,value:ai(t),writable:!0})}:fi,Lo=Cr,Co=Gi||function(n){return or.clearTimeout(n)},Fo=po&&1/P(new po([,-0]))[1]==tn?function(n){return new po(n)}:si,To=_o?function(n){return _o.get(n)}:si,Do=Xi?function(n){return null==n?[]:(n=bi(n),c(Xi(n),(function(t){return qi.call(n,t)})))}:pi,Mo=Xi?function(n){for(var t=[];n;)p(t,Do(n)),n=Ui(n);return t}:pi,Uo=Nt;(lo&&Uo(new lo(new ArrayBuffer(1)))!=jn||so&&Uo(new so)!=_n||ho&&Uo(ho.resolve())!=mn||po&&Uo(new po)!=wn||vo&&Uo(new vo)!=In)&&(Uo=function(n){var t=Nt(n),r=t==yn?n.constructor:Z,e=r?lu(r):"";if(e)switch(e){case mo:return jn;case bo:return _n;case wo:return mn;case xo:return wn;case Ao:return In}return t});var Po=Ri?Fu:vi,qo=au(zo),$o=Ji||function(n,t){return or.setTimeout(n,t)},No=au(Bo),Ko=function(n){var t=Eu(n,(function(n){return 500===r.size&&r.clear(),n})),r=t.cache;return t}((function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(Gn,(function(n,r,e,u){t.push(e?u.replace(ut,"$1"):r||n)})),t})),Zo=Cr((function(n,t){return Lu(n)?Lt(n,Dt(t,1,Lu,!0)):[]})),Vo=Cr((function(n,t){var r=du(t);return Lu(r)&&(r=Z),Lu(n)?Lt(n,Dt(t,1,Lu,!0),$e(r,2)):[]})),Go=Cr((function(n,t){var r=du(t);return Lu(r)&&(r=Z),Lu(n)?Lt(n,Dt(t,1,Lu,!0),Z,r):[]})),Ho=Cr((function(n){var t=h(n,ne);return t.length&&t[0]===n[0]?Jt(t):[]})),Jo=Cr((function(n){var t=du(n),r=h(n,ne);return t===du(r)?t=Z:r.pop(),r.length&&r[0]===n[0]?Jt(r,$e(t,2)):[]})),Yo=Cr((function(n){var t=du(n),r=h(n,ne);return(t="function"==typeof t?t:Z)&&r.pop(),r.length&&r[0]===n[0]?Jt(r,Z,t):[]})),Qo=Cr(yu),Xo=De((function(n,t){var r=null==n?0:n.length,e=Ot(n,t);return zr(n,h(t,(function(n){return Je(n,r)?+n:n})).sort(ae)),e})),na=Cr((function(n){return Vr(Dt(n,1,Lu,!0))})),ta=Cr((function(n){var t=du(n);return Lu(t)&&(t=Z),Vr(Dt(n,1,Lu,!0),$e(t,2))})),ra=Cr((function(n){var t=du(n);return t="function"==typeof t?t:Z,Vr(Dt(n,1,Lu,!0),Z,t)})),ea=Cr((function(n,t){return Lu(n)?Lt(n,t):[]})),ua=Cr((function(n){return Qr(c(n,Lu))})),ia=Cr((function(n){var t=du(n);return Lu(t)&&(t=Z),Qr(c(n,Lu),$e(t,2))})),oa=Cr((function(n){var t=du(n);return t="function"==typeof t?t:Z,Qr(c(n,Lu),Z,t)})),aa=Cr(bu),fa=Cr((function(n){var t=n.length,r=t>1?n[t-1]:Z;return r="function"==typeof r?(n.pop(),r):Z,wu(n,r)})),ca=De((function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return Ot(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Qn&&Je(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:Au,args:[u],thisArg:Z}),new W(e,this.__chain__).thru((function(n){return t&&!n.length&&n.push(Z),n}))):this.thru(u)})),la=he((function(n,t,r){Oi.call(n,r)?++n[r]:kt(n,r,1)})),sa=be(pu),ha=be(vu),pa=he((function(n,t,r){Oi.call(n,r)?n[r].push(t):kt(n,r,[t])})),va=Cr((function(n,t,r){var e=-1,i="function"==typeof t,o=Bu(n)?gi(n.length):[];return ko(n,(function(n){o[++e]=i?u(t,n,r):tr(n,t,r)})),o})),ga=he((function(n,t,r){kt(n,r,t)})),_a=he((function(n,t,r){n[r?0:1].push(t)}),(function(){return[[],[]]})),da=Cr((function(n,t){if(null==n)return[];var r=t.length;return r>1&&Ye(n,t[0],t[1])?t=[]:r>2&&Ye(t[0],t[1],t[2])&&(t=[t[0]]),Or(n,Dt(t,1),[])})),ya=Hi||function(){return or.Date.now()},ma=Cr((function(n,t,r){var e=1;if(r.length){var u=U(r,qe(ma));e|=Y}return Be(n,e,t,r,u)})),ba=Cr((function(n,t,r){var e=3;if(r.length){var u=U(r,qe(ba));e|=Y}return Be(t,e,n,r,u)})),wa=Cr((function(n,t){return Bt(n,1,t)})),xa=Cr((function(n,t,r){return Bt(n,Hu(t)||0,r)}));Eu.Cache=_t;var Aa=Lo((function(n,t){var r=(t=1==t.length&&Ea(t[0])?h(t[0],E($e())):h(Dt(t,1),E($e()))).length;return Cr((function(e){for(var i=-1,o=io(e.length,r);++i=t})),Oa=ur(function(){return arguments}())?ur:function(n){return Uu(n)&&Oi.call(n,"callee")&&!qi.call(n,"callee")},Ea=gi.isArray,Sa=hr?E(hr):function(n){return Uu(n)&&Nt(n)==Wn},za=no||vi,Ba=pr?E(pr):function(n){return Uu(n)&&Nt(n)==hn},La=vr?E(vr):function(n){return Uu(n)&&Uo(n)==_n},Ca=gr?E(gr):function(n){return Uu(n)&&Nt(n)==bn},Fa=_r?E(_r):function(n){return Uu(n)&&Uo(n)==wn},Ta=dr?E(dr):function(n){return Uu(n)&&Du(n.length)&&!!Xt[Nt(n)]},Da=Oe(Ar),Ma=Oe((function(n,t){return n<=t})),Ua=pe((function(n,t){if(nu(t)||Bu(t))return se(t,ni(t),n),Z;for(var r in t)Oi.call(t,r)&&It(n,r,t[r])})),Pa=pe((function(n,t){se(t,ti(t),n)})),qa=pe((function(n,t,r,e){se(t,ti(t),n,e)})),$a=pe((function(n,t,r,e){se(t,ni(t),n,e)})),Na=De(Ot),Ka=Cr((function(n,t){n=bi(n);var r=-1,e=t.length,u=e>2?t[2]:Z;for(u&&Ye(t[0],t[1],u)&&(e=1);++r1),t})),se(n,Ue(n),r),e&&(r=St(r,7,Fe));for(var u=t.length;u--;)Gr(r,t[u]);return r})),Xa=De((function(n,t){return null==n?{}:function(n,t){return Er(n,t,(function(t,r){return Xu(n,r)}))}(n,t)})),nf=ze(ni),tf=ze(ti),rf=de((function(n,t,r){return t=t.toLowerCase(),n+(r?ui(t):t)})),ef=de((function(n,t,r){return n+(r?"-":"")+t.toLowerCase()})),uf=de((function(n,t,r){return n+(r?" ":"")+t.toLowerCase()})),of=_e("toLowerCase"),af=de((function(n,t,r){return n+(r?"_":"")+t.toLowerCase()})),ff=de((function(n,t,r){return n+(r?" ":"")+lf(t)})),cf=de((function(n,t,r){return n+(r?" ":"")+t.toUpperCase()})),lf=_e("toUpperCase"),sf=Cr((function(n,t){try{return u(n,Z,t)}catch(n){return Cu(n)?n:new di(n)}})),hf=De((function(n,t){return o(t,(function(t){t=cu(t),kt(n,t,ma(n[t],n))})),n})),pf=we(),vf=we(!0),gf=Cr((function(n,t){return function(r){return tr(r,n,t)}})),_f=Cr((function(n,t){return function(r){return tr(n,r,t)}})),df=We(h),yf=We(f),mf=We(_),bf=ke(),wf=ke(!0),xf=Ie((function(n,t){return n+t}),0),Af=Se("ceil"),If=Ie((function(n,t){return n/t}),1),Wf=Se("floor"),jf=Ie((function(n,t){return n*t}),1),Rf=Se("round"),kf=Ie((function(n,t){return n-t}),0);return r.after=function(n,t){if("function"!=typeof t)throw new Ai(V);return n=Vu(n),function(){if(--n<1)return t.apply(this,arguments)}},r.ary=Ru,r.assign=Ua,r.assignIn=Pa,r.assignInWith=qa,r.assignWith=$a,r.at=Na,r.before=ku,r.bind=ma,r.bindAll=hf,r.bindKey=ba,r.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Ea(n)?n:[n]},r.chain=xu,r.chunk=function(n,t,r){t=(r?Ye(n,t,r):t===Z)?1:uo(Vu(t),0);var e=null==n?0:n.length;if(!e||t<1)return[];for(var u=0,i=0,o=gi(Yi(e/t));uu?0:u+r),(e=e===Z||e>u?u:Vu(e))<0&&(e+=u),e=r>e?0:Gu(e);r>>0)?(n=Yu(n))&&("string"==typeof t||null!=t&&!Ca(t))&&(!(t=Zr(t))&&F(n))?ee($(n),0,r):n.split(t,r):[]},r.spread=function(n,t){if("function"!=typeof n)throw new Ai(V);return t=null==t?0:uo(Vu(t),0),Cr((function(r){var e=r[t],i=ee(r,0,t);return e&&p(i,e),u(n,this,i)}))},r.tail=function(n){var t=null==n?0:n.length;return t?Ur(n,1,t):[]},r.take=function(n,t,r){return n&&n.length?Ur(n,0,(t=r||t===Z?1:Vu(t))<0?0:t):[]},r.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?Ur(n,(t=e-(t=r||t===Z?1:Vu(t)))<0?0:t,e):[]},r.takeRightWhile=function(n,t){return n&&n.length?Jr(n,$e(t,3),!1,!0):[]},r.takeWhile=function(n,t){return n&&n.length?Jr(n,$e(t,3)):[]},r.tap=function(n,t){return t(n),n},r.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new Ai(V);return Mu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Ou(n,t,{leading:e,maxWait:t,trailing:u})},r.thru=Au,r.toArray=Ku,r.toPairs=nf,r.toPairsIn=tf,r.toPath=function(n){return Ea(n)?h(n,cu):Nu(n)?[n]:le(Ko(Yu(n)))},r.toPlainObject=Ju,r.transform=function(n,t,r){var e=Ea(n),u=e||za(n)||Ta(n);if(t=$e(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:Mu(n)&&Fu(i)?Ro(Ui(n)):{}}return(u?o:Mt)(n,(function(n,e,u){return t(r,n,e,u)})),r},r.unary=function(n){return Ru(n,1)},r.union=na,r.unionBy=ta,r.unionWith=ra,r.uniq=function(n){return n&&n.length?Vr(n):[]},r.uniqBy=function(n,t){return n&&n.length?Vr(n,$e(t,2)):[]},r.uniqWith=function(n,t){return t="function"==typeof t?t:Z,n&&n.length?Vr(n,Z,t):[]},r.unset=function(n,t){return null==n||Gr(n,t)},r.unzip=bu,r.unzipWith=wu,r.update=function(n,t,r){return null==n?n:Hr(n,t,te(r))},r.updateWith=function(n,t,r,e){return e="function"==typeof e?e:Z,null==n?n:Hr(n,t,te(r),e)},r.values=ei,r.valuesIn=function(n){return null==n?[]:S(n,ti(n))},r.without=ea,r.words=oi,r.wrap=function(n,t){return Ia(te(t),n)},r.xor=ua,r.xorBy=ia,r.xorWith=oa,r.zip=aa,r.zipObject=function(n,t){return Xr(n||[],t||[],It)},r.zipObjectDeep=function(n,t){return Xr(n||[],t||[],Dr)},r.zipWith=fa,r.entries=nf,r.entriesIn=tf,r.extend=Pa,r.extendWith=qa,li(r,r),r.add=xf,r.attempt=sf,r.camelCase=rf,r.capitalize=ui,r.ceil=Af,r.clamp=function(n,t,r){return r===Z&&(r=t,t=Z),r!==Z&&(r=(r=Hu(r))==r?r:0),t!==Z&&(t=(t=Hu(t))==t?t:0),Et(Hu(n),t,r)},r.clone=function(n){return St(n,4)},r.cloneDeep=function(n){return St(n,5)},r.cloneDeepWith=function(n,t){return St(n,5,t="function"==typeof t?t:Z)},r.cloneWith=function(n,t){return St(n,4,t="function"==typeof t?t:Z)},r.conformsTo=function(n,t){return null==t||zt(n,t,ni(t))},r.deburr=ii,r.defaultTo=function(n,t){return null==n||n!=n?t:n},r.divide=If,r.endsWith=function(n,t,r){n=Yu(n),t=Zr(t);var e=n.length,u=r=r===Z?e:Et(Vu(r),0,e);return(r-=t.length)>=0&&n.slice(r,u)==t},r.eq=zu,r.escape=function(n){return(n=Yu(n))&&qn.test(n)?n.replace(Un,br):n},r.escapeRegExp=function(n){return(n=Yu(n))&&Jn.test(n)?n.replace(Hn,"\\$&"):n},r.every=function(n,t,r){var e=Ea(n)?f:Ct;return r&&Ye(n,t,r)&&(t=Z),e(n,$e(t,3))},r.find=sa,r.findIndex=pu,r.findKey=function(n,t){return y(n,$e(t,3),Mt)},r.findLast=ha,r.findLastIndex=vu,r.findLastKey=function(n,t){return y(n,$e(t,3),Ut)},r.floor=Wf,r.forEach=Iu,r.forEachRight=Wu,r.forIn=function(n,t){return null==n?n:Eo(n,$e(t,3),ti)},r.forInRight=function(n,t){return null==n?n:So(n,$e(t,3),ti)},r.forOwn=function(n,t){return n&&Mt(n,$e(t,3))},r.forOwnRight=function(n,t){return n&&Ut(n,$e(t,3))},r.get=Qu,r.gt=Ra,r.gte=ka,r.has=function(n,t){return null!=n&&Ve(n,t,Gt)},r.hasIn=Xu,r.head=_u,r.identity=fi,r.includes=function(n,t,r,e){n=Bu(n)?n:ei(n),r=r&&!e?Vu(r):0;var u=n.length;return r<0&&(r=uo(u+r,0)),$u(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&b(n,t,r)>-1},r.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:Vu(r);return u<0&&(u=uo(e+u,0)),b(n,t,u)},r.inRange=function(n,t,r){return t=Zu(t),r===Z?(r=t,t=0):r=Zu(r),function(n,t,r){return n>=io(t,r)&&n=-rn&&n<=rn},r.isSet=Fa,r.isString=$u,r.isSymbol=Nu,r.isTypedArray=Ta,r.isUndefined=function(n){return n===Z},r.isWeakMap=function(n){return Uu(n)&&Uo(n)==In},r.isWeakSet=function(n){return Uu(n)&&"[object WeakSet]"==Nt(n)},r.join=function(n,t){return null==n?"":ro.call(n,t)},r.kebabCase=ef,r.last=du,r.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;return r!==Z&&(u=(u=Vu(r))<0?uo(e+u,0):io(u,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,u):m(n,x,u,!0)},r.lowerCase=uf,r.lowerFirst=of,r.lt=Da,r.lte=Ma,r.max=function(n){return n&&n.length?Ft(n,fi,Vt):Z},r.maxBy=function(n,t){return n&&n.length?Ft(n,$e(t,2),Vt):Z},r.mean=function(n){return A(n,fi)},r.meanBy=function(n,t){return A(n,$e(t,2))},r.min=function(n){return n&&n.length?Ft(n,fi,Ar):Z},r.minBy=function(n,t){return n&&n.length?Ft(n,$e(t,2),Ar):Z},r.stubArray=pi,r.stubFalse=vi,r.stubObject=function(){return{}},r.stubString=function(){return""},r.stubTrue=function(){return!0},r.multiply=jf,r.nth=function(n,t){return n&&n.length?kr(n,Vu(t)):Z},r.noConflict=function(){return or._===this&&(or._=Li),this},r.noop=si,r.now=ya,r.pad=function(n,t,r){n=Yu(n);var e=(t=Vu(t))?q(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return je(Qi(u),r)+n+je(Yi(u),r)},r.padEnd=function(n,t,r){n=Yu(n);var e=(t=Vu(t))?q(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var u=fo();return io(n+u*(t-n+rr("1e-"+((u+"").length-1))),t)}return Br(n,t)},r.reduce=function(n,t,r){var e=Ea(n)?v:j,u=arguments.length<3;return e(n,$e(t,4),r,u,ko)},r.reduceRight=function(n,t,r){var e=Ea(n)?g:j,u=arguments.length<3;return e(n,$e(t,4),r,u,Oo)},r.repeat=function(n,t,r){return t=(r?Ye(n,t,r):t===Z)?1:Vu(t),Lr(Yu(n),t)},r.replace=function(){var n=arguments,t=Yu(n[0]);return n.length<3?t:t.replace(n[1],n[2])},r.result=function(n,t,r){var e=-1,u=(t=re(t,n)).length;for(u||(u=1,n=Z);++ern)return[];var r=un,e=io(n,un);t=$e(t),n-=un;for(var u=k(e,t);++r=i)return n;var a=r-q(e);if(a<1)return e;var f=o?ee(o,0,a).join(""):n.slice(0,a);if(u===Z)return f+e;if(o&&(a+=f.length-a),Ca(u)){if(n.slice(a).search(u)){var c,l=f;for(u.global||(u=wi(u.source,Yu(ot.exec(u))+"g")),u.lastIndex=0;c=u.exec(l);)var s=c.index;f=f.slice(0,s===Z?a:s)}}else if(n.indexOf(Zr(u),a)!=a){var h=f.lastIndexOf(u);h>-1&&(f=f.slice(0,h))}return f+e},r.unescape=function(n){return(n=Yu(n))&&Pn.test(n)?n.replace(Mn,wr):n},r.uniqueId=function(n){var t=++Ei;return Yu(n)+t},r.upperCase=cf,r.upperFirst=lf,r.each=Iu,r.eachRight=Wu,r.first=_u,li(r,function(){var n={};return Mt(r,(function(t,e){Oi.call(r.prototype,e)||(n[e]=t)})),n}(),{chain:!1}),r.VERSION="4.17.21",o(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(n){r[n].placeholder=r})),o(["drop","take"],(function(n,t){Qn.prototype[n]=function(r){r=r===Z?1:uo(Vu(r),0);var e=this.__filtered__&&!t?new Qn(this):this.clone();return e.__filtered__?e.__takeCount__=io(r,e.__takeCount__):e.__views__.push({size:io(r,un),type:n+(e.__dir__<0?"Right":"")}),e},Qn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}})),o(["filter","map","takeWhile"],(function(n,t){var r=t+1,e=1==r||3==r;Qn.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:$e(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}})),o(["head","last"],(function(n,t){var r="take"+(t?"Right":"");Qn.prototype[n]=function(){return this[r](1).value()[0]}})),o(["initial","tail"],(function(n,t){var r="drop"+(t?"":"Right");Qn.prototype[n]=function(){return this.__filtered__?new Qn(this):this[r](1)}})),Qn.prototype.compact=function(){return this.filter(fi)},Qn.prototype.find=function(n){return this.filter(n).head()},Qn.prototype.findLast=function(n){return this.reverse().find(n)},Qn.prototype.invokeMap=Cr((function(n,t){return"function"==typeof n?new Qn(this):this.map((function(r){return tr(r,n,t)}))})),Qn.prototype.reject=function(n){return this.filter(Su($e(n)))},Qn.prototype.slice=function(n,t){n=Vu(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Qn(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==Z&&(r=(t=Vu(t))<0?r.dropRight(-t):r.take(t-n)),r)},Qn.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Qn.prototype.toArray=function(){return this.take(un)},Mt(Qn.prototype,(function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),u=/^(?:head|last)$/.test(t),i=r[u?"take"+("last"==t?"Right":""):t],o=u||/^find/.test(t);i&&(r.prototype[t]=function(){var t=this.__wrapped__,a=u?[1]:arguments,f=t instanceof Qn,c=a[0],l=f||Ea(t),s=function(n){var t=i.apply(r,p([n],a));return u&&h?t[0]:t};l&&e&&"function"==typeof c&&1!=c.length&&(f=l=!1);var h=this.__chain__,v=!!this.__actions__.length,g=o&&!h,_=f&&!v;if(!o&&l){t=_?t:new Qn(this);var d=n.apply(t,a);return d.__actions__.push({func:Au,args:[s],thisArg:Z}),new W(d,h)}return g&&_?n.apply(this,a):(d=this.thru(s),g?u?d.value()[0]:d.value():d)})})),o(["pop","push","shift","sort","splice","unshift"],(function(n){var t=Ii[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",u=/^(?:pop|shift)$/.test(n);r.prototype[n]=function(){var n=arguments;if(u&&!this.__chain__){var r=this.value();return t.apply(Ea(r)?r:[],n)}return this[e]((function(r){return t.apply(Ea(r)?r:[],n)}))}})),Mt(Qn.prototype,(function(n,t){var e=r[t];if(e){var u=e.name+"";Oi.call(yo,u)||(yo[u]=[]),yo[u].push({name:t,func:e})}})),yo[xe(Z,2).name]=[{name:"wrapper",func:Z}],Qn.prototype.clone=function(){var n=new Qn(this.__wrapped__);return n.__actions__=le(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=le(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=le(this.__views__),n},Qn.prototype.reverse=function(){if(this.__filtered__){var n=new Qn(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},Qn.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=Ea(n),e=t<0,u=r?n.length:0,i=function(n,t,r){for(var e=-1,u=r.length;++e=this.__values__.length;return{done:n,value:n?Z:this.__values__[this.__index__++]}},r.prototype.plant=function(n){for(var t,r=this;r instanceof e;){var u=hu(r);u.__index__=0,u.__values__=Z,t?i.__wrapped__=u:t=u;var i=u;r=r.__wrapped__}return i.__wrapped__=n,t},r.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof Qn){var t=n;return this.__actions__.length&&(t=new Qn(this)),(t=t.reverse()).__actions__.push({func:Au,args:[mu],thisArg:Z}),new W(t,this.__chain__)}return this.thru(mu)},r.prototype.toJSON=r.prototype.valueOf=r.prototype.value=function(){return Yr(this.__wrapped__,this.__actions__)},r.prototype.first=r.prototype.head,Ki&&(r.prototype[Ki]=function(){return this}),r}();or._=xr,void 0===(e=function(){return xr}.call(t,r,t,n))||(n.exports=e)}.call(this)},6877:(n,t,r)=>{n.exports=r(4480)}},t={};function r(e){var u=t[e];if(void 0!==u)return u.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return n[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}return r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),r.nmd=n=>(n.paths=[],n.children||(n.children=[]),n),r(6877)})())); \ No newline at end of file + * Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE + */n=r.nmd(n),function(){function u(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function i(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u-1}function s(n,t,r){for(var e=-1,u=null==n?0:n.length;++e-1;);return r}function L(n,t){for(var r=n.length;r--&&b(t,n[r],0)>-1;);return r}function C(n){return"\\"+nr[n]}function F(n){return Ht.test(n)}function T(n){return Jt.test(n)}function D(n){var t=-1,r=Array(n.size);return n.forEach((function(n,e){r[++t]=[e,n]})),r}function M(n,t){return function(r){return n(t(r))}}function U(n,t){for(var r=-1,e=n.length,u=0,i=[];++r>>1,fn=[["ary",X],["bind",1],["bindKey",2],["curry",8],["curryRight",J],["flip",512],["partial",Y],["partialRight",Q],["rearg",nn]],cn="[object Arguments]",ln="[object Array]",sn="[object Boolean]",hn="[object Date]",pn="[object Error]",vn="[object Function]",gn="[object GeneratorFunction]",_n="[object Map]",dn="[object Number]",yn="[object Object]",mn="[object Promise]",bn="[object RegExp]",wn="[object Set]",xn="[object String]",An="[object Symbol]",In="[object WeakMap]",Wn="[object ArrayBuffer]",jn="[object DataView]",Rn="[object Float32Array]",kn="[object Float64Array]",On="[object Int8Array]",En="[object Int16Array]",zn="[object Int32Array]",Sn="[object Uint8Array]",Bn="[object Uint8ClampedArray]",Ln="[object Uint16Array]",Cn="[object Uint32Array]",Fn=/\b__p\+='';/g,Tn=/\b(__p\+=)''\+/g,Dn=/(__e\(.*?\)|\b__t\))\+'';/g,Mn=/&(?:amp|lt|gt|quot|#39);/g,Un=/[&<>"']/g,Pn=RegExp(Mn.source),qn=RegExp(Un.source),$n=/<%-([\s\S]+?)%>/g,Nn=/<%([\s\S]+?)%>/g,Kn=/<%=([\s\S]+?)%>/g,Zn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Vn=/^\w*$/,Gn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Hn=/[\\^$.*+?()[\]{}|]/g,Jn=RegExp(Hn.source),Yn=/^\s+/,Qn=/\s/,Xn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,nt=/\{\n\/\* \[wrapped with (.+)\] \*/,tt=/,? & /,rt=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,et=/[()=,{}\[\]\/\s]/,ut=/\\(\\)?/g,it=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,ot=/\w*$/,at=/^[-+]0x[0-9a-f]+$/i,ft=/^0b[01]+$/i,ct=/^\[object .+?Constructor\]$/,lt=/^0o[0-7]+$/i,st=/^(?:0|[1-9]\d*)$/,ht=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,pt=/($^)/,vt=/['\n\r\u2028\u2029\\]/g,gt="\\ud800-\\udfff",_t="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",dt="\\u2700-\\u27bf",yt="a-z\\xdf-\\xf6\\xf8-\\xff",mt="A-Z\\xc0-\\xd6\\xd8-\\xde",bt="\\ufe0e\\ufe0f",wt="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",xt="['’]",At="["+gt+"]",It="["+wt+"]",Wt="["+_t+"]",jt="\\d+",Rt="["+dt+"]",kt="["+yt+"]",Ot="[^"+gt+wt+jt+dt+yt+mt+"]",Et="\\ud83c[\\udffb-\\udfff]",zt="[^"+gt+"]",St="(?:\\ud83c[\\udde6-\\uddff]){2}",Bt="[\\ud800-\\udbff][\\udc00-\\udfff]",Lt="["+mt+"]",Ct="\\u200d",Ft="(?:"+kt+"|"+Ot+")",Tt="(?:"+Lt+"|"+Ot+")",Dt="(?:['’](?:d|ll|m|re|s|t|ve))?",Mt="(?:['’](?:D|LL|M|RE|S|T|VE))?",Ut="(?:"+Wt+"|"+Et+")"+"?",Pt="["+bt+"]?",qt=Pt+Ut+("(?:"+Ct+"(?:"+[zt,St,Bt].join("|")+")"+Pt+Ut+")*"),$t="(?:"+[Rt,St,Bt].join("|")+")"+qt,Nt="(?:"+[zt+Wt+"?",Wt,St,Bt,At].join("|")+")",Kt=RegExp(xt,"g"),Zt=RegExp(Wt,"g"),Vt=RegExp(Et+"(?="+Et+")|"+Nt+qt,"g"),Gt=RegExp([Lt+"?"+kt+"+"+Dt+"(?="+[It,Lt,"$"].join("|")+")",Tt+"+"+Mt+"(?="+[It,Lt+Ft,"$"].join("|")+")",Lt+"?"+Ft+"+"+Dt,Lt+"+"+Mt,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",jt,$t].join("|"),"g"),Ht=RegExp("["+Ct+gt+_t+bt+"]"),Jt=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Yt=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Qt={};Qt[Rn]=Qt[kn]=Qt[On]=Qt[En]=Qt[zn]=Qt[Sn]=Qt[Bn]=Qt[Ln]=Qt[Cn]=!0,Qt[cn]=Qt[ln]=Qt[Wn]=Qt[sn]=Qt[jn]=Qt[hn]=Qt[pn]=Qt[vn]=Qt[_n]=Qt[dn]=Qt[yn]=Qt[bn]=Qt[wn]=Qt[xn]=Qt[In]=!1;var Xt={};Xt[cn]=Xt[ln]=Xt[Wn]=Xt[jn]=Xt[sn]=Xt[hn]=Xt[Rn]=Xt[kn]=Xt[On]=Xt[En]=Xt[zn]=Xt[_n]=Xt[dn]=Xt[yn]=Xt[bn]=Xt[wn]=Xt[xn]=Xt[An]=Xt[Sn]=Xt[Bn]=Xt[Ln]=Xt[Cn]=!0,Xt[pn]=Xt[vn]=Xt[In]=!1;var nr={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},tr=parseFloat,rr=parseInt,er="object"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,ur="object"==typeof self&&self&&self.Object===Object&&self,ir=er||ur||Function("return this")(),or=t&&!t.nodeType&&t,ar=or&&n&&!n.nodeType&&n,fr=ar&&ar.exports===or,cr=fr&&er.process,lr=function(){try{var n=ar&&ar.require&&ar.require("util").types;return n||cr&&cr.binding&&cr.binding("util")}catch(n){}}(),sr=lr&&lr.isArrayBuffer,hr=lr&&lr.isDate,pr=lr&&lr.isMap,vr=lr&&lr.isRegExp,gr=lr&&lr.isSet,_r=lr&&lr.isTypedArray,dr=I("length"),yr=W({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"}),mr=W({"&":"&","<":"<",">":">",'"':""","'":"'"}),br=W({"&":"&","<":"<",">":">",""":'"',"'":"'"}),wr=function n(t){function r(n){if(Mu(n)&&!Oa(n)&&!(n instanceof Qn)){if(n instanceof W)return n;if(ki.call(n,"__wrapped__"))return su(n)}return new W(n)}function e(){}function W(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=Z}function Qn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=un,this.__views__=[]}function rt(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function zt(n,t,r,e,u,i){var a,f=1&t,c=2&t,l=4&t;if(r&&(a=u?r(n,e,u,i):r(n)),a!==Z)return a;if(!Du(n))return n;var s=Oa(n);if(s){if(a=function(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&ki.call(n,"index")&&(r.index=n.index,r.input=n.input),r}(n),!f)return ce(n,a)}else{var h=Mo(n),p=h==vn||h==gn;if(za(n))return ee(n,f);if(h==yn||h==cn||p&&!u){if(a=c||p?{}:Ve(n),!f)return c?function(n,t){return le(n,Do(n),t)}(n,function(n,t){return n&&le(t,ni(t),n)}(a,n)):function(n,t){return le(n,To(n),t)}(n,Rt(a,n))}else{if(!Xt[h])return u?n:{};a=function(n,t,r){var e=n.constructor;switch(t){case Wn:return ue(n);case sn:case hn:return new e(+n);case jn:return function(n,t){return new n.constructor(t?ue(n.buffer):n.buffer,n.byteOffset,n.byteLength)}(n,r);case Rn:case kn:case On:case En:case zn:case Sn:case Bn:case Ln:case Cn:return ie(n,r);case _n:return new e;case dn:case xn:return new e(n);case bn:return function(n){var t=new n.constructor(n.source,ot.exec(n));return t.lastIndex=n.lastIndex,t}(n);case wn:return new e;case An:return function(n){return Io?mi(Io.call(n)):{}}(n)}}(n,h,f)}}i||(i=new yt);var v=i.get(n);if(v)return v;i.set(n,a),Ca(n)?n.forEach((function(e){a.add(zt(e,t,r,e,n,i))})):Ba(n)&&n.forEach((function(e,u){a.set(u,zt(e,t,r,u,n,i))}));var g=s?Z:(l?c?Me:De:c?ni:Xu)(n);return o(g||n,(function(e,u){g&&(e=n[u=e]),It(a,u,zt(e,t,r,u,n,i))})),a}function St(n,t,r){var e=r.length;if(null==n)return!e;for(n=mi(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===Z&&!(u in n)||!i(o))return!1}return!0}function Bt(n,t,r){if("function"!=typeof n)throw new xi(V);return qo((function(){n.apply(Z,r)}),t)}function Lt(n,t,r,e){var u=-1,i=l,o=!0,a=n.length,f=[],c=t.length;if(!a)return f;r&&(t=h(t,E(r))),e?(i=s,o=!1):t.length>=200&&(i=S,o=!1,t=new dt(t));n:for(;++u0&&r(a)?t>1?Dt(a,t-1,r,e,u):p(u,a):e||(u[u.length]=a)}return u}function Mt(n,t){return n&&Oo(n,t,Xu)}function Ut(n,t){return n&&Eo(n,t,Xu)}function Pt(n,t){return c(t,(function(t){return Cu(n[t])}))}function qt(n,t){for(var r=0,e=(t=te(t,n)).length;null!=n&&rt}function Gt(n,t){return null!=n&&ki.call(n,t)}function Ht(n,t){return null!=n&&t in mi(n)}function Jt(n,t,r){for(var e=r?s:l,u=n[0].length,i=n.length,o=i,a=vi(i),f=1/0,c=[];o--;){var p=n[o];o&&t&&(p=h(p,E(t))),f=uo(p.length,f),a[o]=!r&&(t||u>=120&&p.length>=120)?new dt(o&&p):Z}p=n[0];var v=-1,g=a[0];n:for(;++v=a?f:f*("desc"==r[e]?-1:1)}return n.b-t.b}(n,t,r)}))}function Or(n,t,r){for(var e=-1,u=t.length,i={};++e-1;)a!==n&&qi.call(a,f,1),qi.call(n,f,1);return n}function zr(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;He(u)?qi.call(n,u,1):Vr(n,u)}}return n}function Sr(n,t){return n+Yi(ao()*(t-n+1))}function Br(n,t){var r="";if(!n||t<1||t>rn)return r;do{t%2&&(r+=n),(t=Yi(t/2))&&(n+=n)}while(t);return r}function Lr(n,t){return $o(ru(n,t,ai),n+"")}function Cr(n){return bt(ri(n))}function Fr(n,t){var r=ri(n);return au(r,Et(t,0,r.length))}function Tr(n,t,r,e){if(!Du(n))return n;for(var u=-1,i=(t=te(t,n)).length,o=i-1,a=n;null!=a&&++uu?0:u+t),(r=r>u?u:r)<0&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0;for(var i=vi(u);++e>>1,o=n[i];null!==o&&!$u(o)&&(r?o<=t:o=200){var c=t?null:Co(n);if(c)return P(c);o=!1,u=S,f=new dt}else f=t?[]:a;n:for(;++e=e?n:Mr(n,t,r)}function ee(n,t){if(t)return n.slice();var r=n.length,e=Di?Di(r):new n.constructor(r);return n.copy(e),e}function ue(n){var t=new n.constructor(n.byteLength);return new Ti(t).set(new Ti(n)),t}function ie(n,t){return new n.constructor(t?ue(n.buffer):n.buffer,n.byteOffset,n.length)}function oe(n,t){if(n!==t){var r=n!==Z,e=null===n,u=n==n,i=$u(n),o=t!==Z,a=null===t,f=t==t,c=$u(t);if(!a&&!c&&!i&&n>t||i&&o&&f&&!a&&!c||e&&o&&f||!r&&f||!u)return 1;if(!e&&!i&&!c&&n1?r[u-1]:Z,o=u>2?r[2]:Z;for(i=n.length>3&&"function"==typeof i?(u--,i):Z,o&&Je(r[0],r[1],o)&&(i=u<3?Z:i,u=1),t=mi(t);++e-1?u[i?t[o]:o]:Z}}function be(n){return Te((function(t){var r=t.length,e=r,u=W.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if("function"!=typeof i)throw new xi(V);if(u&&!o&&"wrapper"==Ue(i))var o=new W([],!0)}for(e=o?e:r;++e1&&y.reverse(),l&&fa))return!1;var c=i.get(n),l=i.get(t);if(c&&l)return c==t&&l==n;var s=-1,h=!0,p=2&r?new dt:Z;for(i.set(n,t),i.set(t,n);++s-1&&n%1==0&&n1?"& ":"")+t[e],t=t.join(r>2?", ":" "),n.replace(Xn,"{\n/* [wrapped with "+t+"] */\n")}(e,lu(function(n){var t=n.match(nt);return t?t[1].split(tt):[]}(e),r)))}function ou(n){var t=0,r=0;return function(){var e=io(),u=16-(e-r);if(r=e,u>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(Z,arguments)}}function au(n,t){var r=-1,e=n.length,u=e-1;for(t=t===Z?e:t;++r0&&(r=t.apply(this,arguments)),n<=1&&(t=Z),r}}function ku(n,t,r){function e(t){var r=f,e=c;return f=c=Z,v=t,s=n.apply(e,r)}function u(n){var r=n-p;return p===Z||r>=t||r<0||_&&n-v>=l}function i(){var n=da();return u(n)?o(n):(h=qo(i,function(n){var r=t-(n-p);return _?uo(r,l-(n-v)):r}(n)),Z)}function o(n){return h=Z,d&&f?e(n):(f=c=Z,s)}function a(){var n=da(),r=u(n);if(f=arguments,c=this,p=n,r){if(h===Z)return function(n){return v=n,h=qo(i,t),g?e(n):s}(p);if(_)return Lo(h),h=qo(i,t),e(p)}return h===Z&&(h=qo(i,t)),s}var f,c,l,s,h,p,v=0,g=!1,_=!1,d=!0;if("function"!=typeof n)throw new xi(V);return t=Gu(t)||0,Du(r)&&(g=!!r.leading,l=(_="maxWait"in r)?eo(Gu(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),a.cancel=function(){h!==Z&&Lo(h),v=0,f=p=c=h=Z},a.flush=function(){return h===Z?s:o(da())},a}function Ou(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new xi(V);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(Ou.Cache||_t),r}function Eu(n){if("function"!=typeof n)throw new xi(V);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function zu(n,t){return n===t||n!=n&&t!=t}function Su(n){return null!=n&&Tu(n.length)&&!Cu(n)}function Bu(n){return Mu(n)&&Su(n)}function Lu(n){if(!Mu(n))return!1;var t=Nt(n);return t==pn||"[object DOMException]"==t||"string"==typeof n.message&&"string"==typeof n.name&&!Pu(n)}function Cu(n){if(!Du(n))return!1;var t=Nt(n);return t==vn||t==gn||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Fu(n){return"number"==typeof n&&n==Zu(n)}function Tu(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=rn}function Du(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function Mu(n){return null!=n&&"object"==typeof n}function Uu(n){return"number"==typeof n||Mu(n)&&Nt(n)==dn}function Pu(n){if(!Mu(n)||Nt(n)!=yn)return!1;var t=Mi(n);if(null===t)return!0;var r=ki.call(t,"constructor")&&t.constructor;return"function"==typeof r&&r instanceof r&&Ri.call(r)==Si}function qu(n){return"string"==typeof n||!Oa(n)&&Mu(n)&&Nt(n)==xn}function $u(n){return"symbol"==typeof n||Mu(n)&&Nt(n)==An}function Nu(n){if(!n)return[];if(Su(n))return qu(n)?$(n):ce(n);if(Ni&&n[Ni])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Ni]());var t=Mo(n);return(t==_n?D:t==wn?P:ri)(n)}function Ku(n){return n?(n=Gu(n))===tn||n===-tn?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function Zu(n){var t=Ku(n),r=t%1;return t==t?r?t-r:t:0}function Vu(n){return n?Et(Zu(n),0,un):0}function Gu(n){if("number"==typeof n)return n;if($u(n))return en;if(Du(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=Du(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=O(n);var r=ft.test(n);return r||lt.test(n)?rr(n.slice(2),r?2:8):at.test(n)?en:+n}function Hu(n){return le(n,ni(n))}function Ju(n){return null==n?"":Kr(n)}function Yu(n,t,r){var e=null==n?Z:qt(n,t);return e===Z?r:e}function Qu(n,t){return null!=n&&Ze(n,t,Ht)}function Xu(n){return Su(n)?mt(n):lr(n)}function ni(n){return Su(n)?mt(n,!0):dr(n)}function ti(n,t){if(null==n)return{};var r=h(Me(n),(function(n){return[n]}));return t=qe(t),Or(n,r,(function(n,r){return t(n,r[0])}))}function ri(n){return null==n?[]:z(n,Xu(n))}function ei(n){return cf(Ju(n).toLowerCase())}function ui(n){return(n=Ju(n))&&n.replace(ht,yr).replace(Zt,"")}function ii(n,t,r){return n=Ju(n),(t=r?Z:t)===Z?T(n)?K(n):d(n):n.match(t)||[]}function oi(n){return function(){return n}}function ai(n){return n}function fi(n){return cr("function"==typeof n?n:zt(n,1))}function ci(n,t,r){var e=Xu(t),u=Pt(t,e);null!=r||Du(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=Pt(t,Xu(t)));var i=!(Du(r)&&"chain"in r&&!r.chain),a=Cu(n);return o(u,(function(r){var e=t[r];n[r]=e,a&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=ce(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,p([this.value()],arguments))})})),n}function li(){}function si(n){return Ye(n)?I(fu(n)):function(n){return function(t){return qt(t,n)}}(n)}function hi(){return[]}function pi(){return!1}var vi=(t=null==t?ir:wr.defaults(ir.Object(),t,wr.pick(ir,Yt))).Array,gi=t.Date,_i=t.Error,di=t.Function,yi=t.Math,mi=t.Object,bi=t.RegExp,wi=t.String,xi=t.TypeError,Ai=vi.prototype,Ii=di.prototype,Wi=mi.prototype,ji=t["__core-js_shared__"],Ri=Ii.toString,ki=Wi.hasOwnProperty,Oi=0,Ei=function(){var n=/[^.]+$/.exec(ji&&ji.keys&&ji.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),zi=Wi.toString,Si=Ri.call(mi),Bi=ir._,Li=bi("^"+Ri.call(ki).replace(Hn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ci=fr?t.Buffer:Z,Fi=t.Symbol,Ti=t.Uint8Array,Di=Ci?Ci.allocUnsafe:Z,Mi=M(mi.getPrototypeOf,mi),Ui=mi.create,Pi=Wi.propertyIsEnumerable,qi=Ai.splice,$i=Fi?Fi.isConcatSpreadable:Z,Ni=Fi?Fi.iterator:Z,Ki=Fi?Fi.toStringTag:Z,Zi=function(){try{var n=Ke(mi,"defineProperty");return n({},"",{}),n}catch(n){}}(),Vi=t.clearTimeout!==ir.clearTimeout&&t.clearTimeout,Gi=gi&&gi.now!==ir.Date.now&&gi.now,Hi=t.setTimeout!==ir.setTimeout&&t.setTimeout,Ji=yi.ceil,Yi=yi.floor,Qi=mi.getOwnPropertySymbols,Xi=Ci?Ci.isBuffer:Z,no=t.isFinite,to=Ai.join,ro=M(mi.keys,mi),eo=yi.max,uo=yi.min,io=gi.now,oo=t.parseInt,ao=yi.random,fo=Ai.reverse,co=Ke(t,"DataView"),lo=Ke(t,"Map"),so=Ke(t,"Promise"),ho=Ke(t,"Set"),po=Ke(t,"WeakMap"),vo=Ke(mi,"create"),go=po&&new po,_o={},yo=cu(co),mo=cu(lo),bo=cu(so),wo=cu(ho),xo=cu(po),Ao=Fi?Fi.prototype:Z,Io=Ao?Ao.valueOf:Z,Wo=Ao?Ao.toString:Z,jo=function(){function n(){}return function(t){if(!Du(t))return{};if(Ui)return Ui(t);n.prototype=t;var r=new n;return n.prototype=Z,r}}();r.templateSettings={escape:$n,evaluate:Nn,interpolate:Kn,variable:"",imports:{_:r}},r.prototype=e.prototype,r.prototype.constructor=r,W.prototype=jo(e.prototype),W.prototype.constructor=W,Qn.prototype=jo(e.prototype),Qn.prototype.constructor=Qn,rt.prototype.clear=function(){this.__data__=vo?vo(null):{},this.size=0},rt.prototype.delete=function(n){var t=this.has(n)&&delete this.__data__[n];return this.size-=t?1:0,t},rt.prototype.get=function(n){var t=this.__data__;if(vo){var r=t[n];return r===G?Z:r}return ki.call(t,n)?t[n]:Z},rt.prototype.has=function(n){var t=this.__data__;return vo?t[n]!==Z:ki.call(t,n)},rt.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=vo&&t===Z?G:t,this},gt.prototype.clear=function(){this.__data__=[],this.size=0},gt.prototype.delete=function(n){var t=this.__data__,r=Wt(t,n);return!(r<0||(r==t.length-1?t.pop():qi.call(t,r,1),--this.size,0))},gt.prototype.get=function(n){var t=this.__data__,r=Wt(t,n);return r<0?Z:t[r][1]},gt.prototype.has=function(n){return Wt(this.__data__,n)>-1},gt.prototype.set=function(n,t){var r=this.__data__,e=Wt(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},_t.prototype.clear=function(){this.size=0,this.__data__={hash:new rt,map:new(lo||gt),string:new rt}},_t.prototype.delete=function(n){var t=$e(this,n).delete(n);return this.size-=t?1:0,t},_t.prototype.get=function(n){return $e(this,n).get(n)},_t.prototype.has=function(n){return $e(this,n).has(n)},_t.prototype.set=function(n,t){var r=$e(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},dt.prototype.add=dt.prototype.push=function(n){return this.__data__.set(n,G),this},dt.prototype.has=function(n){return this.__data__.has(n)},yt.prototype.clear=function(){this.__data__=new gt,this.size=0},yt.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},yt.prototype.get=function(n){return this.__data__.get(n)},yt.prototype.has=function(n){return this.__data__.has(n)},yt.prototype.set=function(n,t){var r=this.__data__;if(r instanceof gt){var e=r.__data__;if(!lo||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new _t(e)}return r.set(n,t),this.size=r.size,this};var Ro=pe(Mt),ko=pe(Ut,!0),Oo=ve(),Eo=ve(!0),zo=go?function(n,t){return go.set(n,t),n}:ai,So=Zi?function(n,t){return Zi(n,"toString",{configurable:!0,enumerable:!1,value:oi(t),writable:!0})}:ai,Bo=Lr,Lo=Vi||function(n){return ir.clearTimeout(n)},Co=ho&&1/P(new ho([,-0]))[1]==tn?function(n){return new ho(n)}:li,Fo=go?function(n){return go.get(n)}:li,To=Qi?function(n){return null==n?[]:(n=mi(n),c(Qi(n),(function(t){return Pi.call(n,t)})))}:hi,Do=Qi?function(n){for(var t=[];n;)p(t,To(n)),n=Mi(n);return t}:hi,Mo=Nt;(co&&Mo(new co(new ArrayBuffer(1)))!=jn||lo&&Mo(new lo)!=_n||so&&Mo(so.resolve())!=mn||ho&&Mo(new ho)!=wn||po&&Mo(new po)!=In)&&(Mo=function(n){var t=Nt(n),r=t==yn?n.constructor:Z,e=r?cu(r):"";if(e)switch(e){case yo:return jn;case mo:return _n;case bo:return mn;case wo:return wn;case xo:return In}return t});var Uo=ji?Cu:pi,Po=ou(zo),qo=Hi||function(n,t){return ir.setTimeout(n,t)},$o=ou(So),No=function(n){var t=Ou(n,(function(n){return 500===r.size&&r.clear(),n})),r=t.cache;return t}((function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(Gn,(function(n,r,e,u){t.push(e?u.replace(ut,"$1"):r||n)})),t})),Ko=Lr((function(n,t){return Bu(n)?Lt(n,Dt(t,1,Bu,!0)):[]})),Zo=Lr((function(n,t){var r=_u(t);return Bu(r)&&(r=Z),Bu(n)?Lt(n,Dt(t,1,Bu,!0),qe(r,2)):[]})),Vo=Lr((function(n,t){var r=_u(t);return Bu(r)&&(r=Z),Bu(n)?Lt(n,Dt(t,1,Bu,!0),Z,r):[]})),Go=Lr((function(n){var t=h(n,Xr);return t.length&&t[0]===n[0]?Jt(t):[]})),Ho=Lr((function(n){var t=_u(n),r=h(n,Xr);return t===_u(r)?t=Z:r.pop(),r.length&&r[0]===n[0]?Jt(r,qe(t,2)):[]})),Jo=Lr((function(n){var t=_u(n),r=h(n,Xr);return(t="function"==typeof t?t:Z)&&r.pop(),r.length&&r[0]===n[0]?Jt(r,Z,t):[]})),Yo=Lr(du),Qo=Te((function(n,t){var r=null==n?0:n.length,e=Ot(n,t);return zr(n,h(t,(function(n){return He(n,r)?+n:n})).sort(oe)),e})),Xo=Lr((function(n){return Zr(Dt(n,1,Bu,!0))})),na=Lr((function(n){var t=_u(n);return Bu(t)&&(t=Z),Zr(Dt(n,1,Bu,!0),qe(t,2))})),ta=Lr((function(n){var t=_u(n);return t="function"==typeof t?t:Z,Zr(Dt(n,1,Bu,!0),Z,t)})),ra=Lr((function(n,t){return Bu(n)?Lt(n,t):[]})),ea=Lr((function(n){return Yr(c(n,Bu))})),ua=Lr((function(n){var t=_u(n);return Bu(t)&&(t=Z),Yr(c(n,Bu),qe(t,2))})),ia=Lr((function(n){var t=_u(n);return t="function"==typeof t?t:Z,Yr(c(n,Bu),Z,t)})),oa=Lr(mu),aa=Lr((function(n){var t=n.length,r=t>1?n[t-1]:Z;return r="function"==typeof r?(n.pop(),r):Z,bu(n,r)})),fa=Te((function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return Ot(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Qn&&He(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:xu,args:[u],thisArg:Z}),new W(e,this.__chain__).thru((function(n){return t&&!n.length&&n.push(Z),n}))):this.thru(u)})),ca=se((function(n,t,r){ki.call(n,r)?++n[r]:kt(n,r,1)})),la=me(hu),sa=me(pu),ha=se((function(n,t,r){ki.call(n,r)?n[r].push(t):kt(n,r,[t])})),pa=Lr((function(n,t,r){var e=-1,i="function"==typeof t,o=Su(n)?vi(n.length):[];return Ro(n,(function(n){o[++e]=i?u(t,n,r):nr(n,t,r)})),o})),va=se((function(n,t,r){kt(n,r,t)})),ga=se((function(n,t,r){n[r?0:1].push(t)}),(function(){return[[],[]]})),_a=Lr((function(n,t){if(null==n)return[];var r=t.length;return r>1&&Je(n,t[0],t[1])?t=[]:r>2&&Je(t[0],t[1],t[2])&&(t=[t[0]]),kr(n,Dt(t,1),[])})),da=Gi||function(){return ir.Date.now()},ya=Lr((function(n,t,r){var e=1;if(r.length){var u=U(r,Pe(ya));e|=Y}return Se(n,e,t,r,u)})),ma=Lr((function(n,t,r){var e=3;if(r.length){var u=U(r,Pe(ma));e|=Y}return Se(t,e,n,r,u)})),ba=Lr((function(n,t){return Bt(n,1,t)})),wa=Lr((function(n,t,r){return Bt(n,Gu(t)||0,r)}));Ou.Cache=_t;var xa=Bo((function(n,t){var r=(t=1==t.length&&Oa(t[0])?h(t[0],E(qe())):h(Dt(t,1),E(qe()))).length;return Lr((function(e){for(var i=-1,o=uo(e.length,r);++i=t})),ka=er(function(){return arguments}())?er:function(n){return Mu(n)&&ki.call(n,"callee")&&!Pi.call(n,"callee")},Oa=vi.isArray,Ea=sr?E(sr):function(n){return Mu(n)&&Nt(n)==Wn},za=Xi||pi,Sa=hr?E(hr):function(n){return Mu(n)&&Nt(n)==hn},Ba=pr?E(pr):function(n){return Mu(n)&&Mo(n)==_n},La=vr?E(vr):function(n){return Mu(n)&&Nt(n)==bn},Ca=gr?E(gr):function(n){return Mu(n)&&Mo(n)==wn},Fa=_r?E(_r):function(n){return Mu(n)&&Tu(n.length)&&!!Qt[Nt(n)]},Ta=ke(xr),Da=ke((function(n,t){return n<=t})),Ma=he((function(n,t){if(Xe(t)||Su(t))return le(t,Xu(t),n),Z;for(var r in t)ki.call(t,r)&&It(n,r,t[r])})),Ua=he((function(n,t){le(t,ni(t),n)})),Pa=he((function(n,t,r,e){le(t,ni(t),n,e)})),qa=he((function(n,t,r,e){le(t,Xu(t),n,e)})),$a=Te(Ot),Na=Lr((function(n,t){n=mi(n);var r=-1,e=t.length,u=e>2?t[2]:Z;for(u&&Je(t[0],t[1],u)&&(e=1);++r1),t})),le(n,Me(n),r),e&&(r=zt(r,7,Ce));for(var u=t.length;u--;)Vr(r,t[u]);return r})),Qa=Te((function(n,t){return null==n?{}:function(n,t){return Or(n,t,(function(t,r){return Qu(n,r)}))}(n,t)})),Xa=ze(Xu),nf=ze(ni),tf=_e((function(n,t,r){return t=t.toLowerCase(),n+(r?ei(t):t)})),rf=_e((function(n,t,r){return n+(r?"-":"")+t.toLowerCase()})),ef=_e((function(n,t,r){return n+(r?" ":"")+t.toLowerCase()})),uf=ge("toLowerCase"),of=_e((function(n,t,r){return n+(r?"_":"")+t.toLowerCase()})),af=_e((function(n,t,r){return n+(r?" ":"")+cf(t)})),ff=_e((function(n,t,r){return n+(r?" ":"")+t.toUpperCase()})),cf=ge("toUpperCase"),lf=Lr((function(n,t){try{return u(n,Z,t)}catch(n){return Lu(n)?n:new _i(n)}})),sf=Te((function(n,t){return o(t,(function(t){t=fu(t),kt(n,t,ya(n[t],n))})),n})),hf=be(),pf=be(!0),vf=Lr((function(n,t){return function(r){return nr(r,n,t)}})),gf=Lr((function(n,t){return function(r){return nr(n,r,t)}})),_f=Ie(h),df=Ie(f),yf=Ie(_),mf=Re(),bf=Re(!0),wf=Ae((function(n,t){return n+t}),0),xf=Ee("ceil"),Af=Ae((function(n,t){return n/t}),1),If=Ee("floor"),Wf=Ae((function(n,t){return n*t}),1),jf=Ee("round"),Rf=Ae((function(n,t){return n-t}),0);return r.after=function(n,t){if("function"!=typeof t)throw new xi(V);return n=Zu(n),function(){if(--n<1)return t.apply(this,arguments)}},r.ary=ju,r.assign=Ma,r.assignIn=Ua,r.assignInWith=Pa,r.assignWith=qa,r.at=$a,r.before=Ru,r.bind=ya,r.bindAll=sf,r.bindKey=ma,r.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Oa(n)?n:[n]},r.chain=wu,r.chunk=function(n,t,r){t=(r?Je(n,t,r):t===Z)?1:eo(Zu(t),0);var e=null==n?0:n.length;if(!e||t<1)return[];for(var u=0,i=0,o=vi(Ji(e/t));uu?0:u+r),(e=e===Z||e>u?u:Zu(e))<0&&(e+=u),e=r>e?0:Vu(e);r>>0)?(n=Ju(n))&&("string"==typeof t||null!=t&&!La(t))&&(!(t=Kr(t))&&F(n))?re($(n),0,r):n.split(t,r):[]},r.spread=function(n,t){if("function"!=typeof n)throw new xi(V);return t=null==t?0:eo(Zu(t),0),Lr((function(r){var e=r[t],i=re(r,0,t);return e&&p(i,e),u(n,this,i)}))},r.tail=function(n){var t=null==n?0:n.length;return t?Mr(n,1,t):[]},r.take=function(n,t,r){return n&&n.length?Mr(n,0,(t=r||t===Z?1:Zu(t))<0?0:t):[]},r.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?Mr(n,(t=e-(t=r||t===Z?1:Zu(t)))<0?0:t,e):[]},r.takeRightWhile=function(n,t){return n&&n.length?Hr(n,qe(t,3),!1,!0):[]},r.takeWhile=function(n,t){return n&&n.length?Hr(n,qe(t,3)):[]},r.tap=function(n,t){return t(n),n},r.throttle=function(n,t,r){var e=!0,u=!0;if("function"!=typeof n)throw new xi(V);return Du(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ku(n,t,{leading:e,maxWait:t,trailing:u})},r.thru=xu,r.toArray=Nu,r.toPairs=Xa,r.toPairsIn=nf,r.toPath=function(n){return Oa(n)?h(n,fu):$u(n)?[n]:ce(No(Ju(n)))},r.toPlainObject=Hu,r.transform=function(n,t,r){var e=Oa(n),u=e||za(n)||Fa(n);if(t=qe(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:Du(n)&&Cu(i)?jo(Mi(n)):{}}return(u?o:Mt)(n,(function(n,e,u){return t(r,n,e,u)})),r},r.unary=function(n){return ju(n,1)},r.union=Xo,r.unionBy=na,r.unionWith=ta,r.uniq=function(n){return n&&n.length?Zr(n):[]},r.uniqBy=function(n,t){return n&&n.length?Zr(n,qe(t,2)):[]},r.uniqWith=function(n,t){return t="function"==typeof t?t:Z,n&&n.length?Zr(n,Z,t):[]},r.unset=function(n,t){return null==n||Vr(n,t)},r.unzip=mu,r.unzipWith=bu,r.update=function(n,t,r){return null==n?n:Gr(n,t,ne(r))},r.updateWith=function(n,t,r,e){return e="function"==typeof e?e:Z,null==n?n:Gr(n,t,ne(r),e)},r.values=ri,r.valuesIn=function(n){return null==n?[]:z(n,ni(n))},r.without=ra,r.words=ii,r.wrap=function(n,t){return Aa(ne(t),n)},r.xor=ea,r.xorBy=ua,r.xorWith=ia,r.zip=oa,r.zipObject=function(n,t){return Qr(n||[],t||[],It)},r.zipObjectDeep=function(n,t){return Qr(n||[],t||[],Tr)},r.zipWith=aa,r.entries=Xa,r.entriesIn=nf,r.extend=Ua,r.extendWith=Pa,ci(r,r),r.add=wf,r.attempt=lf,r.camelCase=tf,r.capitalize=ei,r.ceil=xf,r.clamp=function(n,t,r){return r===Z&&(r=t,t=Z),r!==Z&&(r=(r=Gu(r))==r?r:0),t!==Z&&(t=(t=Gu(t))==t?t:0),Et(Gu(n),t,r)},r.clone=function(n){return zt(n,4)},r.cloneDeep=function(n){return zt(n,5)},r.cloneDeepWith=function(n,t){return zt(n,5,t="function"==typeof t?t:Z)},r.cloneWith=function(n,t){return zt(n,4,t="function"==typeof t?t:Z)},r.conformsTo=function(n,t){return null==t||St(n,t,Xu(t))},r.deburr=ui,r.defaultTo=function(n,t){return null==n||n!=n?t:n},r.divide=Af,r.endsWith=function(n,t,r){n=Ju(n),t=Kr(t);var e=n.length,u=r=r===Z?e:Et(Zu(r),0,e);return(r-=t.length)>=0&&n.slice(r,u)==t},r.eq=zu,r.escape=function(n){return(n=Ju(n))&&qn.test(n)?n.replace(Un,mr):n},r.escapeRegExp=function(n){return(n=Ju(n))&&Jn.test(n)?n.replace(Hn,"\\$&"):n},r.every=function(n,t,r){var e=Oa(n)?f:Ct;return r&&Je(n,t,r)&&(t=Z),e(n,qe(t,3))},r.find=la,r.findIndex=hu,r.findKey=function(n,t){return y(n,qe(t,3),Mt)},r.findLast=sa,r.findLastIndex=pu,r.findLastKey=function(n,t){return y(n,qe(t,3),Ut)},r.floor=If,r.forEach=Au,r.forEachRight=Iu,r.forIn=function(n,t){return null==n?n:Oo(n,qe(t,3),ni)},r.forInRight=function(n,t){return null==n?n:Eo(n,qe(t,3),ni)},r.forOwn=function(n,t){return n&&Mt(n,qe(t,3))},r.forOwnRight=function(n,t){return n&&Ut(n,qe(t,3))},r.get=Yu,r.gt=ja,r.gte=Ra,r.has=function(n,t){return null!=n&&Ze(n,t,Gt)},r.hasIn=Qu,r.head=gu,r.identity=ai,r.includes=function(n,t,r,e){n=Su(n)?n:ri(n),r=r&&!e?Zu(r):0;var u=n.length;return r<0&&(r=eo(u+r,0)),qu(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&b(n,t,r)>-1},r.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:Zu(r);return u<0&&(u=eo(e+u,0)),b(n,t,u)},r.inRange=function(n,t,r){return t=Ku(t),r===Z?(r=t,t=0):r=Ku(r),function(n,t,r){return n>=uo(t,r)&&n=-rn&&n<=rn},r.isSet=Ca,r.isString=qu,r.isSymbol=$u,r.isTypedArray=Fa,r.isUndefined=function(n){return n===Z},r.isWeakMap=function(n){return Mu(n)&&Mo(n)==In},r.isWeakSet=function(n){return Mu(n)&&"[object WeakSet]"==Nt(n)},r.join=function(n,t){return null==n?"":to.call(n,t)},r.kebabCase=rf,r.last=_u,r.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;return r!==Z&&(u=(u=Zu(r))<0?eo(e+u,0):uo(u,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,u):m(n,x,u,!0)},r.lowerCase=ef,r.lowerFirst=uf,r.lt=Ta,r.lte=Da,r.max=function(n){return n&&n.length?Ft(n,ai,Vt):Z},r.maxBy=function(n,t){return n&&n.length?Ft(n,qe(t,2),Vt):Z},r.mean=function(n){return A(n,ai)},r.meanBy=function(n,t){return A(n,qe(t,2))},r.min=function(n){return n&&n.length?Ft(n,ai,xr):Z},r.minBy=function(n,t){return n&&n.length?Ft(n,qe(t,2),xr):Z},r.stubArray=hi,r.stubFalse=pi,r.stubObject=function(){return{}},r.stubString=function(){return""},r.stubTrue=function(){return!0},r.multiply=Wf,r.nth=function(n,t){return n&&n.length?Rr(n,Zu(t)):Z},r.noConflict=function(){return ir._===this&&(ir._=Bi),this},r.noop=li,r.now=da,r.pad=function(n,t,r){n=Ju(n);var e=(t=Zu(t))?q(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return We(Yi(u),r)+n+We(Ji(u),r)},r.padEnd=function(n,t,r){n=Ju(n);var e=(t=Zu(t))?q(n):0;return t&&et){var e=n;n=t,t=e}if(r||n%1||t%1){var u=ao();return uo(n+u*(t-n+tr("1e-"+((u+"").length-1))),t)}return Sr(n,t)},r.reduce=function(n,t,r){var e=Oa(n)?v:j,u=arguments.length<3;return e(n,qe(t,4),r,u,Ro)},r.reduceRight=function(n,t,r){var e=Oa(n)?g:j,u=arguments.length<3;return e(n,qe(t,4),r,u,ko)},r.repeat=function(n,t,r){return t=(r?Je(n,t,r):t===Z)?1:Zu(t),Br(Ju(n),t)},r.replace=function(){var n=arguments,t=Ju(n[0]);return n.length<3?t:t.replace(n[1],n[2])},r.result=function(n,t,r){var e=-1,u=(t=te(t,n)).length;for(u||(u=1,n=Z);++ern)return[];var r=un,e=uo(n,un);t=qe(t),n-=un;for(var u=k(e,t);++r=i)return n;var a=r-q(e);if(a<1)return e;var f=o?re(o,0,a).join(""):n.slice(0,a);if(u===Z)return f+e;if(o&&(a+=f.length-a),La(u)){if(n.slice(a).search(u)){var c,l=f;for(u.global||(u=bi(u.source,Ju(ot.exec(u))+"g")),u.lastIndex=0;c=u.exec(l);)var s=c.index;f=f.slice(0,s===Z?a:s)}}else if(n.indexOf(Kr(u),a)!=a){var h=f.lastIndexOf(u);h>-1&&(f=f.slice(0,h))}return f+e},r.unescape=function(n){return(n=Ju(n))&&Pn.test(n)?n.replace(Mn,br):n},r.uniqueId=function(n){var t=++Oi;return Ju(n)+t},r.upperCase=ff,r.upperFirst=cf,r.each=Au,r.eachRight=Iu,r.first=gu,ci(r,function(){var n={};return Mt(r,(function(t,e){ki.call(r.prototype,e)||(n[e]=t)})),n}(),{chain:!1}),r.VERSION="4.18.1",o(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(n){r[n].placeholder=r})),o(["drop","take"],(function(n,t){Qn.prototype[n]=function(r){r=r===Z?1:eo(Zu(r),0);var e=this.__filtered__&&!t?new Qn(this):this.clone();return e.__filtered__?e.__takeCount__=uo(r,e.__takeCount__):e.__views__.push({size:uo(r,un),type:n+(e.__dir__<0?"Right":"")}),e},Qn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}})),o(["filter","map","takeWhile"],(function(n,t){var r=t+1,e=1==r||3==r;Qn.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:qe(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}})),o(["head","last"],(function(n,t){var r="take"+(t?"Right":"");Qn.prototype[n]=function(){return this[r](1).value()[0]}})),o(["initial","tail"],(function(n,t){var r="drop"+(t?"":"Right");Qn.prototype[n]=function(){return this.__filtered__?new Qn(this):this[r](1)}})),Qn.prototype.compact=function(){return this.filter(ai)},Qn.prototype.find=function(n){return this.filter(n).head()},Qn.prototype.findLast=function(n){return this.reverse().find(n)},Qn.prototype.invokeMap=Lr((function(n,t){return"function"==typeof n?new Qn(this):this.map((function(r){return nr(r,n,t)}))})),Qn.prototype.reject=function(n){return this.filter(Eu(qe(n)))},Qn.prototype.slice=function(n,t){n=Zu(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Qn(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==Z&&(r=(t=Zu(t))<0?r.dropRight(-t):r.take(t-n)),r)},Qn.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Qn.prototype.toArray=function(){return this.take(un)},Mt(Qn.prototype,(function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),u=/^(?:head|last)$/.test(t),i=r[u?"take"+("last"==t?"Right":""):t],o=u||/^find/.test(t);i&&(r.prototype[t]=function(){var t=this.__wrapped__,a=u?[1]:arguments,f=t instanceof Qn,c=a[0],l=f||Oa(t),s=function(n){var t=i.apply(r,p([n],a));return u&&h?t[0]:t};l&&e&&"function"==typeof c&&1!=c.length&&(f=l=!1);var h=this.__chain__,v=!!this.__actions__.length,g=o&&!h,_=f&&!v;if(!o&&l){t=_?t:new Qn(this);var d=n.apply(t,a);return d.__actions__.push({func:xu,args:[s],thisArg:Z}),new W(d,h)}return g&&_?n.apply(this,a):(d=this.thru(s),g?u?d.value()[0]:d.value():d)})})),o(["pop","push","shift","sort","splice","unshift"],(function(n){var t=Ai[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",u=/^(?:pop|shift)$/.test(n);r.prototype[n]=function(){var n=arguments;if(u&&!this.__chain__){var r=this.value();return t.apply(Oa(r)?r:[],n)}return this[e]((function(r){return t.apply(Oa(r)?r:[],n)}))}})),Mt(Qn.prototype,(function(n,t){var e=r[t];if(e){var u=e.name+"";ki.call(_o,u)||(_o[u]=[]),_o[u].push({name:t,func:e})}})),_o[we(Z,2).name]=[{name:"wrapper",func:Z}],Qn.prototype.clone=function(){var n=new Qn(this.__wrapped__);return n.__actions__=ce(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=ce(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=ce(this.__views__),n},Qn.prototype.reverse=function(){if(this.__filtered__){var n=new Qn(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},Qn.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=Oa(n),e=t<0,u=r?n.length:0,i=function(n,t,r){for(var e=-1,u=r.length;++e=this.__values__.length;return{done:n,value:n?Z:this.__values__[this.__index__++]}},r.prototype.plant=function(n){for(var t,r=this;r instanceof e;){var u=su(r);u.__index__=0,u.__values__=Z,t?i.__wrapped__=u:t=u;var i=u;r=r.__wrapped__}return i.__wrapped__=n,t},r.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof Qn){var t=n;return this.__actions__.length&&(t=new Qn(this)),(t=t.reverse()).__actions__.push({func:xu,args:[yu],thisArg:Z}),new W(t,this.__chain__)}return this.thru(yu)},r.prototype.toJSON=r.prototype.valueOf=r.prototype.value=function(){return Jr(this.__wrapped__,this.__actions__)},r.prototype.first=r.prototype.head,Ni&&(r.prototype[Ni]=function(){return this}),r}();ir._=wr,void 0===(e=function(){return wr}.call(t,r,t,n))||(n.exports=e)}.call(this)},6877(n,t,r){n.exports=r(4480)}},t={};function r(e){var u=t[e];if(void 0!==u)return u.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return n[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}return r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),r.nmd=n=>(n.paths=[],n.children||(n.children=[]),n),r(6877)})())); \ No newline at end of file diff --git a/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/moment.js b/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/moment.js index 377cea4d1..10a5346e0 100644 --- a/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/moment.js +++ b/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/dist/moment.js @@ -1,277 +1,277 @@ -!function(e,a){"object"==typeof exports&&"object"==typeof module?module.exports=a():"function"==typeof define&&define.amd?define([],a):"object"==typeof exports?exports.moment=a():e.moment=a()}(this,(()=>(()=>{var e={5177:function(e,a,t){!function(e){"use strict"; +!function(e,a){"object"==typeof exports&&"object"==typeof module?module.exports=a():"function"==typeof define&&define.amd?define([],a):"object"==typeof exports?exports.moment=a():e.moment=a()}(this,(()=>(()=>{var e={5177(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des".split("_"),weekdays:"Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag".split("_"),weekdaysShort:"Son_Maa_Din_Woe_Don_Vry_Sat".split("_"),weekdaysMin:"So_Ma_Di_Wo_Do_Vr_Sa".split("_"),meridiemParse:/vm|nm/i,isPM:function(e){return/^nm$/i.test(e)},meridiem:function(e,a,t){return e<12?t?"vm":"VM":t?"nm":"NM"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Vandag om] LT",nextDay:"[Môre om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gister om] LT",lastWeek:"[Laas] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oor %s",past:"%s gelede",s:"'n paar sekondes",ss:"%d sekondes",m:"'n minuut",mm:"%d minute",h:"'n uur",hh:"%d ure",d:"'n dag",dd:"%d dae",M:"'n maand",MM:"%d maande",y:"'n jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},1488:function(e,a,t){!function(e){"use strict"; +e.defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des".split("_"),weekdays:"Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag".split("_"),weekdaysShort:"Son_Maa_Din_Woe_Don_Vry_Sat".split("_"),weekdaysMin:"So_Ma_Di_Wo_Do_Vr_Sa".split("_"),meridiemParse:/vm|nm/i,isPM:function(e){return/^nm$/i.test(e)},meridiem:function(e,a,t){return e<12?t?"vm":"VM":t?"nm":"NM"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Vandag om] LT",nextDay:"[Môre om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gister om] LT",lastWeek:"[Laas] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oor %s",past:"%s gelede",s:"'n paar sekondes",ss:"%d sekondes",m:"'n minuut",mm:"%d minute",h:"'n uur",hh:"%d ure",d:"'n dag",dd:"%d dae",M:"'n maand",MM:"%d maande",y:"'n jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},1488(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},t={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},s=function(e){return function(s,n,r,i){var d=a(s),_=t[e][a(s)];return 2===d&&(_=_[n?0:1]),_.replace(/%d/i,s)}},n=["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويلية","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];e.defineLocale("ar-dz",{months:n,monthsShort:n,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:s("s"),ss:s("s"),m:s("m"),mm:s("m"),h:s("h"),hh:s("h"),d:s("d"),dd:s("d"),M:s("M"),MM:s("M"),y:s("y"),yy:s("y")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:0,doy:4}})}(t(5093))},8676:function(e,a,t){!function(e){"use strict"; +var a=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},t={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},s=function(e){return function(s,n,r,d){var i=a(s),_=t[e][a(s)];return 2===i&&(_=_[n?0:1]),_.replace(/%d/i,s)}},n=["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويلية","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];e.defineLocale("ar-dz",{months:n,monthsShort:n,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:s("s"),ss:s("s"),m:s("m"),mm:s("m"),h:s("h"),hh:s("h"),d:s("d"),dd:s("d"),M:s("M"),MM:s("M"),y:s("y"),yy:s("y")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:0,doy:4}})}(t(5093))},8676(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ar-kw",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:0,doy:12}})}(t(5093))},2353:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ar-kw",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:0,doy:12}})}(t(5093))},2353(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",0:"0"},t=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},s={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},n=function(e){return function(a,n,r,i){var d=t(a),_=s[e][t(a)];return 2===d&&(_=_[n?0:1]),_.replace(/%d/i,a)}},r=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];e.defineLocale("ar-ly",{months:r,monthsShort:r,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:n("s"),ss:n("s"),m:n("m"),mm:n("m"),h:n("h"),hh:n("h"),d:n("d"),dd:n("d"),M:n("M"),MM:n("M"),y:n("y"),yy:n("y")},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:6,doy:12}})}(t(5093))},4496:function(e,a,t){!function(e){"use strict"; +var a={1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",0:"0"},t=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},s={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},n=function(e){return function(a,n,r,d){var i=t(a),_=s[e][t(a)];return 2===i&&(_=_[n?0:1]),_.replace(/%d/i,a)}},r=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];e.defineLocale("ar-ly",{months:r,monthsShort:r,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:n("s"),ss:n("s"),m:n("m"),mm:n("m"),h:n("h"),hh:n("h"),d:n("d"),dd:n("d"),M:n("M"),MM:n("M"),y:n("y"),yy:n("y")},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:6,doy:12}})}(t(5093))},4496(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اثنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}})}(t(5093))},6947:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اثنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}})}(t(5093))},6947(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"};e.defineLocale("ar-ps",{months:"كانون الثاني_شباط_آذار_نيسان_أيّار_حزيران_تمّوز_آب_أيلول_تشري الأوّل_تشرين الثاني_كانون الأوّل".split("_"),monthsShort:"ك٢_شباط_آذار_نيسان_أيّار_حزيران_تمّوز_آب_أيلول_ت١_ت٢_ك١".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(e){return e.replace(/[٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).split("").reverse().join("").replace(/[١٢](?![\u062a\u0643])/g,(function(e){return t[e]})).split("").reverse().join("").replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:0,doy:6}})}(t(5093))},2682:function(e,a,t){!function(e){"use strict"; +var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"};e.defineLocale("ar-ps",{months:"كانون الثاني_شباط_آذار_نيسان_أيّار_حزيران_تمّوز_آب_أيلول_تشري الأوّل_تشرين الثاني_كانون الأوّل".split("_"),monthsShort:"ك٢_شباط_آذار_نيسان_أيّار_حزيران_تمّوز_آب_أيلول_ت١_ت٢_ك١".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(e){return e.replace(/[٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).split("").reverse().join("").replace(/[١٢](?![\u062a\u0643])/g,(function(e){return t[e]})).split("").reverse().join("").replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:0,doy:6}})}(t(5093))},2682(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"};e.defineLocale("ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:0,doy:6}})}(t(5093))},9756:function(e,a,t){!function(e){"use strict"; +var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"};e.defineLocale("ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:0,doy:6}})}(t(5093))},9756(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}})}(t(5093))},1509:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}})}(t(5093))},1509(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},s=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},n={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},r=function(e){return function(a,t,r,i){var d=s(a),_=n[e][s(a)];return 2===d&&(_=_[t?0:1]),_.replace(/%d/i,a)}},i=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];e.defineLocale("ar",{months:i,monthsShort:i,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:r("s"),ss:r("s"),m:r("m"),mm:r("m"),h:r("h"),hh:r("h"),d:r("d"),dd:r("d"),M:r("M"),MM:r("M"),y:r("y"),yy:r("y")},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:6,doy:12}})}(t(5093))},5533:function(e,a,t){!function(e){"use strict"; +var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},s=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},n={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},r=function(e){return function(a,t,r,d){var i=s(a),_=n[e][s(a)];return 2===i&&(_=_[t?0:1]),_.replace(/%d/i,a)}},d=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];e.defineLocale("ar",{months:d,monthsShort:d,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:r("s"),ss:r("s"),m:r("m"),mm:r("m"),h:r("h"),hh:r("h"),d:r("d"),dd:r("d"),M:r("M"),MM:r("M"),y:r("y"),yy:r("y")},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:6,doy:12}})}(t(5093))},5533(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"};e.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"bir neçə saniyə",ss:"%d saniyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(e){return/^(gündüz|axşam)$/.test(e)},meridiem:function(e,a,t){return e<4?"gecə":e<12?"səhər":e<17?"gündüz":"axşam"},dayOfMonthOrdinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(e){if(0===e)return e+"-ıncı";var t=e%10,s=e%100-t,n=e>=100?100:null;return e+(a[t]||a[s]||a[n])},week:{dow:1,doy:7}})}(t(5093))},8959:function(e,a,t){!function(e){"use strict"; +var a={1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"};e.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"bir neçə saniyə",ss:"%d saniyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(e){return/^(gündüz|axşam)$/.test(e)},meridiem:function(e,a,t){return e<4?"gecə":e<12?"səhər":e<17?"gündüz":"axşam"},dayOfMonthOrdinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(e){if(0===e)return e+"-ıncı";var t=e%10,s=e%100-t,n=e>=100?100:null;return e+(a[t]||a[s]||a[n])},week:{dow:1,doy:7}})}(t(5093))},8959(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,s){return"m"===s?t?"хвіліна":"хвіліну":"h"===s?t?"гадзіна":"гадзіну":e+" "+a({ss:t?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:t?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:t?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"}[s],+e)}e.defineLocale("be",{months:{format:"студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня".split("_"),standalone:"студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань".split("_")},monthsShort:"студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж".split("_"),weekdays:{format:"нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу".split("_"),standalone:"нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота".split("_"),isFormat:/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/},weekdaysShort:"нд_пн_ат_ср_чц_пт_сб".split("_"),weekdaysMin:"нд_пн_ат_ср_чц_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сёння ў] LT",nextDay:"[Заўтра ў] LT",lastDay:"[Учора ў] LT",nextWeek:function(){return"[У] dddd [ў] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[У мінулую] dddd [ў] LT";case 1:case 2:case 4:return"[У мінулы] dddd [ў] LT"}},sameElse:"L"},relativeTime:{future:"праз %s",past:"%s таму",s:"некалькі секунд",m:t,mm:t,h:t,hh:t,d:"дзень",dd:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночы|раніцы|дня|вечара/,isPM:function(e){return/^(дня|вечара)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночы":e<12?"раніцы":e<17?"дня":"вечара"},dayOfMonthOrdinalParse:/\d{1,2}-(і|ы|га)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":case"w":case"W":return e%10!=2&&e%10!=3||e%100==12||e%100==13?e+"-ы":e+"-і";case"D":return e+"-га";default:return e}},week:{dow:1,doy:7}})}(t(5093))},7777:function(e,a,t){!function(e){"use strict"; +function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,s){return"m"===s?t?"хвіліна":"хвіліну":"h"===s?t?"гадзіна":"гадзіну":e+" "+a({ss:t?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:t?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:t?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"}[s],+e)}e.defineLocale("be",{months:{format:"студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня".split("_"),standalone:"студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань".split("_")},monthsShort:"студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж".split("_"),weekdays:{format:"нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу".split("_"),standalone:"нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота".split("_"),isFormat:/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/},weekdaysShort:"нд_пн_ат_ср_чц_пт_сб".split("_"),weekdaysMin:"нд_пн_ат_ср_чц_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сёння ў] LT",nextDay:"[Заўтра ў] LT",lastDay:"[Учора ў] LT",nextWeek:function(){return"[У] dddd [ў] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[У мінулую] dddd [ў] LT";case 1:case 2:case 4:return"[У мінулы] dddd [ў] LT"}},sameElse:"L"},relativeTime:{future:"праз %s",past:"%s таму",s:"некалькі секунд",m:t,mm:t,h:t,hh:t,d:"дзень",dd:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночы|раніцы|дня|вечара/,isPM:function(e){return/^(дня|вечара)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночы":e<12?"раніцы":e<17?"дня":"вечара"},dayOfMonthOrdinalParse:/\d{1,2}-(і|ы|га)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":case"w":case"W":return e%10!=2&&e%10!=3||e%100==12||e%100==13?e+"-ы":e+"-і";case"D":return e+"-га";default:return e}},week:{dow:1,doy:7}})}(t(5093))},7777(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"яну_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Миналата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[Миналия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",ss:"%d секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",w:"седмица",ww:"%d седмици",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},dayOfMonthOrdinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var a=e%10,t=e%100;return 0===e?e+"-ев":0===t?e+"-ен":t>10&&t<20?e+"-ти":1===a?e+"-ви":2===a?e+"-ри":7===a||8===a?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})}(t(5093))},4903:function(e,a,t){!function(e){"use strict"; +e.defineLocale("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"яну_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Миналата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[Миналия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",ss:"%d секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",w:"седмица",ww:"%d седмици",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},dayOfMonthOrdinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var a=e%10,t=e%100;return 0===e?e+"-ев":0===t?e+"-ен":t>10&&t<20?e+"-ти":1===a?e+"-ви":2===a?e+"-ри":7===a||8===a?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})}(t(5093))},4903(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("bm",{months:"Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_Mɛkalo_Zuwɛnkalo_Zuluyekalo_Utikalo_Sɛtanburukalo_ɔkutɔburukalo_Nowanburukalo_Desanburukalo".split("_"),monthsShort:"Zan_Few_Mar_Awi_Mɛ_Zuw_Zul_Uti_Sɛt_ɔku_Now_Des".split("_"),weekdays:"Kari_Ntɛnɛn_Tarata_Araba_Alamisa_Juma_Sibiri".split("_"),weekdaysShort:"Kar_Ntɛ_Tar_Ara_Ala_Jum_Sib".split("_"),weekdaysMin:"Ka_Nt_Ta_Ar_Al_Ju_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"MMMM [tile] D [san] YYYY",LLL:"MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm",LLLL:"dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm"},calendar:{sameDay:"[Bi lɛrɛ] LT",nextDay:"[Sini lɛrɛ] LT",nextWeek:"dddd [don lɛrɛ] LT",lastDay:"[Kunu lɛrɛ] LT",lastWeek:"dddd [tɛmɛnen lɛrɛ] LT",sameElse:"L"},relativeTime:{future:"%s kɔnɔ",past:"a bɛ %s bɔ",s:"sanga dama dama",ss:"sekondi %d",m:"miniti kelen",mm:"miniti %d",h:"lɛrɛ kelen",hh:"lɛrɛ %d",d:"tile kelen",dd:"tile %d",M:"kalo kelen",MM:"kalo %d",y:"san kelen",yy:"san %d"},week:{dow:1,doy:4}})}(t(5093))},7357:function(e,a,t){!function(e){"use strict"; +e.defineLocale("bm",{months:"Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_Mɛkalo_Zuwɛnkalo_Zuluyekalo_Utikalo_Sɛtanburukalo_ɔkutɔburukalo_Nowanburukalo_Desanburukalo".split("_"),monthsShort:"Zan_Few_Mar_Awi_Mɛ_Zuw_Zul_Uti_Sɛt_ɔku_Now_Des".split("_"),weekdays:"Kari_Ntɛnɛn_Tarata_Araba_Alamisa_Juma_Sibiri".split("_"),weekdaysShort:"Kar_Ntɛ_Tar_Ara_Ala_Jum_Sib".split("_"),weekdaysMin:"Ka_Nt_Ta_Ar_Al_Ju_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"MMMM [tile] D [san] YYYY",LLL:"MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm",LLLL:"dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm"},calendar:{sameDay:"[Bi lɛrɛ] LT",nextDay:"[Sini lɛrɛ] LT",nextWeek:"dddd [don lɛrɛ] LT",lastDay:"[Kunu lɛrɛ] LT",lastWeek:"dddd [tɛmɛnen lɛrɛ] LT",sameElse:"L"},relativeTime:{future:"%s kɔnɔ",past:"a bɛ %s bɔ",s:"sanga dama dama",ss:"sekondi %d",m:"miniti kelen",mm:"miniti %d",h:"lɛrɛ kelen",hh:"lɛrɛ %d",d:"tile kelen",dd:"tile %d",M:"kalo kelen",MM:"kalo %d",y:"san kelen",yy:"san %d"},week:{dow:1,doy:4}})}(t(5093))},7357(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"},t={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"};e.defineLocale("bn-bd",{months:"জানুয়ারি_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব্রু_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্ট_অক্টো_নভে_ডিসে".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি".split("_"),weekdaysMin:"রবি_সোম_মঙ্গল_বুধ_বৃহ_শুক্র_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",ss:"%d সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(e){return e.replace(/[১২৩৪৫৬৭৮৯০]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/রাত|ভোর|সকাল|দুপুর|বিকাল|সন্ধ্যা|রাত/,meridiemHour:function(e,a){return 12===e&&(e=0),"রাত"===a?e<4?e:e+12:"ভোর"===a||"সকাল"===a?e:"দুপুর"===a?e>=3?e:e+12:"বিকাল"===a||"সন্ধ্যা"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"রাত":e<6?"ভোর":e<12?"সকাল":e<15?"দুপুর":e<18?"বিকাল":e<20?"সন্ধ্যা":"রাত"},week:{dow:0,doy:6}})}(t(5093))},1290:function(e,a,t){!function(e){"use strict"; +var a={1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"},t={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"};e.defineLocale("bn-bd",{months:"জানুয়ারি_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব্রু_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্ট_অক্টো_নভে_ডিসে".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি".split("_"),weekdaysMin:"রবি_সোম_মঙ্গল_বুধ_বৃহ_শুক্র_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",ss:"%d সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(e){return e.replace(/[১২৩৪৫৬৭৮৯০]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/রাত|ভোর|সকাল|দুপুর|বিকাল|সন্ধ্যা|রাত/,meridiemHour:function(e,a){return 12===e&&(e=0),"রাত"===a?e<4?e:e+12:"ভোর"===a||"সকাল"===a?e:"দুপুর"===a?e>=3?e:e+12:"বিকাল"===a||"সন্ধ্যা"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"রাত":e<6?"ভোর":e<12?"সকাল":e<15?"দুপুর":e<18?"বিকাল":e<20?"সন্ধ্যা":"রাত"},week:{dow:0,doy:6}})}(t(5093))},1290(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"},t={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"};e.defineLocale("bn",{months:"জানুয়ারি_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব্রু_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্ট_অক্টো_নভে_ডিসে".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি".split("_"),weekdaysMin:"রবি_সোম_মঙ্গল_বুধ_বৃহ_শুক্র_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",ss:"%d সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(e){return e.replace(/[১২৩৪৫৬৭৮৯০]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/রাত|সকাল|দুপুর|বিকাল|রাত/,meridiemHour:function(e,a){return 12===e&&(e=0),"রাত"===a&&e>=4||"দুপুর"===a&&e<5||"বিকাল"===a?e+12:e},meridiem:function(e,a,t){return e<4?"রাত":e<10?"সকাল":e<17?"দুপুর":e<20?"বিকাল":"রাত"},week:{dow:0,doy:6}})}(t(5093))},1545:function(e,a,t){!function(e){"use strict"; +var a={1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"},t={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"};e.defineLocale("bn",{months:"জানুয়ারি_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব্রু_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্ট_অক্টো_নভে_ডিসে".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি".split("_"),weekdaysMin:"রবি_সোম_মঙ্গল_বুধ_বৃহ_শুক্র_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",ss:"%d সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(e){return e.replace(/[১২৩৪৫৬৭৮৯০]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/রাত|সকাল|দুপুর|বিকাল|রাত/,meridiemHour:function(e,a){return 12===e&&(e=0),"রাত"===a&&e>=4||"দুপুর"===a&&e<5||"বিকাল"===a?e+12:e},meridiem:function(e,a,t){return e<4?"রাত":e<10?"সকাল":e<17?"দুপুর":e<20?"বিকাল":"রাত"},week:{dow:0,doy:6}})}(t(5093))},1545(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"༡",2:"༢",3:"༣",4:"༤",5:"༥",6:"༦",7:"༧",8:"༨",9:"༩",0:"༠"},t={"༡":"1","༢":"2","༣":"3","༤":"4","༥":"5","༦":"6","༧":"7","༨":"8","༩":"9","༠":"0"};e.defineLocale("bo",{months:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),monthsShort:"ཟླ་1_ཟླ་2_ཟླ་3_ཟླ་4_ཟླ་5_ཟླ་6_ཟླ་7_ཟླ་8_ཟླ་9_ཟླ་10_ཟླ་11_ཟླ་12".split("_"),monthsShortRegex:/^(ཟླ་\d{1,2})/,monthsParseExact:!0,weekdays:"གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་".split("_"),weekdaysShort:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),weekdaysMin:"ཉི_ཟླ_མིག_ལྷག_ཕུར_སངས_སྤེན".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[དི་རིང] LT",nextDay:"[སང་ཉིན] LT",nextWeek:"[བདུན་ཕྲག་རྗེས་མ], LT",lastDay:"[ཁ་སང] LT",lastWeek:"[བདུན་ཕྲག་མཐའ་མ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ལ་",past:"%s སྔན་ལ",s:"ལམ་སང",ss:"%d སྐར་ཆ།",m:"སྐར་མ་གཅིག",mm:"%d སྐར་མ",h:"ཆུ་ཚོད་གཅིག",hh:"%d ཆུ་ཚོད",d:"ཉིན་གཅིག",dd:"%d ཉིན་",M:"ཟླ་བ་གཅིག",MM:"%d ཟླ་བ",y:"ལོ་གཅིག",yy:"%d ལོ"},preparse:function(e){return e.replace(/[༡༢༣༤༥༦༧༨༩༠]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,meridiemHour:function(e,a){return 12===e&&(e=0),"མཚན་མོ"===a&&e>=4||"ཉིན་གུང"===a&&e<5||"དགོང་དག"===a?e+12:e},meridiem:function(e,a,t){return e<4?"མཚན་མོ":e<10?"ཞོགས་ཀས":e<17?"ཉིན་གུང":e<20?"དགོང་དག":"མཚན་མོ"},week:{dow:0,doy:6}})}(t(5093))},1470:function(e,a,t){!function(e){"use strict"; +var a={1:"༡",2:"༢",3:"༣",4:"༤",5:"༥",6:"༦",7:"༧",8:"༨",9:"༩",0:"༠"},t={"༡":"1","༢":"2","༣":"3","༤":"4","༥":"5","༦":"6","༧":"7","༨":"8","༩":"9","༠":"0"};e.defineLocale("bo",{months:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),monthsShort:"ཟླ་1_ཟླ་2_ཟླ་3_ཟླ་4_ཟླ་5_ཟླ་6_ཟླ་7_ཟླ་8_ཟླ་9_ཟླ་10_ཟླ་11_ཟླ་12".split("_"),monthsShortRegex:/^(ཟླ་\d{1,2})/,monthsParseExact:!0,weekdays:"གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་".split("_"),weekdaysShort:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),weekdaysMin:"ཉི_ཟླ_མིག_ལྷག_ཕུར_སངས_སྤེན".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[དི་རིང] LT",nextDay:"[སང་ཉིན] LT",nextWeek:"[བདུན་ཕྲག་རྗེས་མ], LT",lastDay:"[ཁ་སང] LT",lastWeek:"[བདུན་ཕྲག་མཐའ་མ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ལ་",past:"%s སྔན་ལ",s:"ལམ་སང",ss:"%d སྐར་ཆ།",m:"སྐར་མ་གཅིག",mm:"%d སྐར་མ",h:"ཆུ་ཚོད་གཅིག",hh:"%d ཆུ་ཚོད",d:"ཉིན་གཅིག",dd:"%d ཉིན་",M:"ཟླ་བ་གཅིག",MM:"%d ཟླ་བ",y:"ལོ་གཅིག",yy:"%d ལོ"},preparse:function(e){return e.replace(/[༡༢༣༤༥༦༧༨༩༠]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,meridiemHour:function(e,a){return 12===e&&(e=0),"མཚན་མོ"===a&&e>=4||"ཉིན་གུང"===a&&e<5||"དགོང་དག"===a?e+12:e},meridiem:function(e,a,t){return e<4?"མཚན་མོ":e<10?"ཞོགས་ཀས":e<17?"ཉིན་གུང":e<20?"དགོང་དག":"མཚན་མོ"},week:{dow:0,doy:6}})}(t(5093))},1470(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t){return e+" "+n({mm:"munutenn",MM:"miz",dd:"devezh"}[t],e)}function t(e){switch(s(e)){case 1:case 3:case 4:case 5:case 9:return e+" bloaz";default:return e+" vloaz"}}function s(e){return e>9?s(e%10):e}function n(e,a){return 2===a?r(e):e}function r(e){var a={m:"v",b:"v",d:"z"};return void 0===a[e.charAt(0)]?e:a[e.charAt(0)]+e.substring(1)}var i=[/^gen/i,/^c[ʼ\']hwe/i,/^meu/i,/^ebr/i,/^mae/i,/^(mez|eve)/i,/^gou/i,/^eos/i,/^gwe/i,/^her/i,/^du/i,/^ker/i],d=/^(genver|c[ʼ\']hwevrer|meurzh|ebrel|mae|mezheven|gouere|eost|gwengolo|here|du|kerzu|gen|c[ʼ\']hwe|meu|ebr|mae|eve|gou|eos|gwe|her|du|ker)/i,_=/^(genver|c[ʼ\']hwevrer|meurzh|ebrel|mae|mezheven|gouere|eost|gwengolo|here|du|kerzu)/i,o=/^(gen|c[ʼ\']hwe|meu|ebr|mae|eve|gou|eos|gwe|her|du|ker)/i,u=[/^sul/i,/^lun/i,/^meurzh/i,/^merc[ʼ\']her/i,/^yaou/i,/^gwener/i,/^sadorn/i],m=[/^Sul/i,/^Lun/i,/^Meu/i,/^Mer/i,/^Yao/i,/^Gwe/i,/^Sad/i],l=[/^Su/i,/^Lu/i,/^Me([^r]|$)/i,/^Mer/i,/^Ya/i,/^Gw/i,/^Sa/i];e.defineLocale("br",{months:"Genver_Cʼhwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_Cʼhwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Mercʼher_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),weekdaysParse:l,fullWeekdaysParse:u,shortWeekdaysParse:m,minWeekdaysParse:l,monthsRegex:d,monthsShortRegex:d,monthsStrictRegex:_,monthsShortStrictRegex:o,monthsParse:i,longMonthsParse:i,shortMonthsParse:i,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY HH:mm",LLLL:"dddd, D [a viz] MMMM YYYY HH:mm"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warcʼhoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Decʼh da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s ʼzo",s:"un nebeud segondennoù",ss:"%d eilenn",m:"ur vunutenn",mm:a,h:"un eur",hh:"%d eur",d:"un devezh",dd:a,M:"ur miz",MM:a,y:"ur bloaz",yy:t},dayOfMonthOrdinalParse:/\d{1,2}(añ|vet)/,ordinal:function(e){return e+(1===e?"añ":"vet")},week:{dow:1,doy:4},meridiemParse:/a.m.|g.m./,isPM:function(e){return"g.m."===e},meridiem:function(e,a,t){return e<12?"a.m.":"g.m."}})}(t(5093))},4429:function(e,a,t){!function(e){"use strict"; +function a(e,a,t){return e+" "+n({mm:"munutenn",MM:"miz",dd:"devezh"}[t],e)}function t(e){switch(s(e)){case 1:case 3:case 4:case 5:case 9:return e+" bloaz";default:return e+" vloaz"}}function s(e){return e>9?s(e%10):e}function n(e,a){return 2===a?r(e):e}function r(e){var a={m:"v",b:"v",d:"z"};return void 0===a[e.charAt(0)]?e:a[e.charAt(0)]+e.substring(1)}var d=[/^gen/i,/^c[ʼ\']hwe/i,/^meu/i,/^ebr/i,/^mae/i,/^(mez|eve)/i,/^gou/i,/^eos/i,/^gwe/i,/^her/i,/^du/i,/^ker/i],i=/^(genver|c[ʼ\']hwevrer|meurzh|ebrel|mae|mezheven|gouere|eost|gwengolo|here|du|kerzu|gen|c[ʼ\']hwe|meu|ebr|mae|eve|gou|eos|gwe|her|du|ker)/i,_=/^(genver|c[ʼ\']hwevrer|meurzh|ebrel|mae|mezheven|gouere|eost|gwengolo|here|du|kerzu)/i,o=/^(gen|c[ʼ\']hwe|meu|ebr|mae|eve|gou|eos|gwe|her|du|ker)/i,m=[/^sul/i,/^lun/i,/^meurzh/i,/^merc[ʼ\']her/i,/^yaou/i,/^gwener/i,/^sadorn/i],u=[/^Sul/i,/^Lun/i,/^Meu/i,/^Mer/i,/^Yao/i,/^Gwe/i,/^Sad/i],l=[/^Su/i,/^Lu/i,/^Me([^r]|$)/i,/^Mer/i,/^Ya/i,/^Gw/i,/^Sa/i];e.defineLocale("br",{months:"Genver_Cʼhwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_Cʼhwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Mercʼher_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),weekdaysParse:l,fullWeekdaysParse:m,shortWeekdaysParse:u,minWeekdaysParse:l,monthsRegex:i,monthsShortRegex:i,monthsStrictRegex:_,monthsShortStrictRegex:o,monthsParse:d,longMonthsParse:d,shortMonthsParse:d,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY HH:mm",LLLL:"dddd, D [a viz] MMMM YYYY HH:mm"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warcʼhoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Decʼh da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s ʼzo",s:"un nebeud segondennoù",ss:"%d eilenn",m:"ur vunutenn",mm:a,h:"un eur",hh:"%d eur",d:"un devezh",dd:a,M:"ur miz",MM:a,y:"ur bloaz",yy:t},dayOfMonthOrdinalParse:/\d{1,2}(añ|vet)/,ordinal:function(e){return e+(1===e?"añ":"vet")},week:{dow:1,doy:4},meridiemParse:/a.m.|g.m./,isPM:function(e){return"g.m."===e},meridiem:function(e,a,t){return e<12?"a.m.":"g.m."}})}(t(5093))},4429(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){if("m"===t)return a?"jedna minuta":s?"jednu minutu":"jedne minute"}function t(e,a,t){var s=e+" ";switch(t){case"ss":return s+=1===e?"sekunda":2===e||3===e||4===e?"sekunde":"sekundi";case"mm":return s+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return"jedan sat";case"hh":return s+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return s+=1===e?"dan":"dana";case"MM":return s+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return s+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}e.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:t,m:a,mm:t,h:t,hh:t,d:"dan",dd:t,M:"mjesec",MM:t,y:"godinu",yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},7306:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){if("m"===t)return a?"jedna minuta":s?"jednu minutu":"jedne minute"}function t(e,a,t){var s=e+" ";switch(t){case"ss":return s+=1===e?"sekunda":2===e||3===e||4===e?"sekunde":"sekundi";case"mm":return s+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return"jedan sat";case"hh":return s+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return s+=1===e?"dan":"dana";case"MM":return s+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return s+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}e.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:t,m:a,mm:t,h:t,hh:t,d:"dan",dd:t,M:"mjesec",MM:t,y:"godinu",yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},7306(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ca",{months:{standalone:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),format:"de gener_de febrer_de març_d'abril_de maig_de juny_de juliol_d'agost_de setembre_d'octubre_de novembre_de desembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dt_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a les] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a les] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"uns segons",ss:"%d segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(e,a){var t=1===e?"r":2===e?"n":3===e?"r":4===e?"t":"è";return"w"!==a&&"W"!==a||(t="a"),e+t},week:{dow:1,doy:4}})}(t(5093))},6464:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ca",{months:{standalone:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),format:"de gener_de febrer_de març_d'abril_de maig_de juny_de juliol_d'agost_de setembre_d'octubre_de novembre_de desembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dt_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a les] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a les] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"uns segons",ss:"%d segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(e,a){var t=1===e?"r":2===e?"n":3===e?"r":4===e?"t":"è";return"w"!==a&&"W"!==a||(t="a"),e+t},week:{dow:1,doy:4}})}(t(5093))},6464(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={standalone:"leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),format:"ledna_února_března_dubna_května_června_července_srpna_září_října_listopadu_prosince".split("_"),isFormat:/DD?[o.]?(\[[^\[\]]*\]|\s)+MMMM/},t="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"),s=[/^led/i,/^úno/i,/^bře/i,/^dub/i,/^kvě/i,/^(čvn|červen$|června)/i,/^(čvc|červenec|července)/i,/^srp/i,/^zář/i,/^říj/i,/^lis/i,/^pro/i],n=/^(leden|únor|březen|duben|květen|červenec|července|červen|června|srpen|září|říjen|listopad|prosinec|led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i;function r(e){return e>1&&e<5&&1!=~~(e/10)}function i(e,a,t,s){var n=e+" ";switch(t){case"s":return a||s?"pár sekund":"pár sekundami";case"ss":return a||s?n+(r(e)?"sekundy":"sekund"):n+"sekundami";case"m":return a?"minuta":s?"minutu":"minutou";case"mm":return a||s?n+(r(e)?"minuty":"minut"):n+"minutami";case"h":return a?"hodina":s?"hodinu":"hodinou";case"hh":return a||s?n+(r(e)?"hodiny":"hodin"):n+"hodinami";case"d":return a||s?"den":"dnem";case"dd":return a||s?n+(r(e)?"dny":"dní"):n+"dny";case"M":return a||s?"měsíc":"měsícem";case"MM":return a||s?n+(r(e)?"měsíce":"měsíců"):n+"měsíci";case"y":return a||s?"rok":"rokem";case"yy":return a||s?n+(r(e)?"roky":"let"):n+"lety"}}e.defineLocale("cs",{months:a,monthsShort:t,monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(leden|ledna|února|únor|březen|března|duben|dubna|květen|května|červenec|července|červen|června|srpen|srpna|září|říjen|října|listopadu|listopad|prosinec|prosince)/i,monthsShortStrictRegex:/^(led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:i,ss:i,m:i,mm:i,h:i,hh:i,d:i,dd:i,M:i,MM:i,y:i,yy:i},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},3635:function(e,a,t){!function(e){"use strict"; +var a={standalone:"leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),format:"ledna_února_března_dubna_května_června_července_srpna_září_října_listopadu_prosince".split("_"),isFormat:/DD?[o.]?(\[[^\[\]]*\]|\s)+MMMM/},t="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"),s=[/^led/i,/^úno/i,/^bře/i,/^dub/i,/^kvě/i,/^(čvn|červen$|června)/i,/^(čvc|červenec|července)/i,/^srp/i,/^zář/i,/^říj/i,/^lis/i,/^pro/i],n=/^(leden|únor|březen|duben|květen|červenec|července|červen|června|srpen|září|říjen|listopad|prosinec|led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i;function r(e){return e>1&&e<5&&1!=~~(e/10)}function d(e,a,t,s){var n=e+" ";switch(t){case"s":return a||s?"pár sekund":"pár sekundami";case"ss":return a||s?n+(r(e)?"sekundy":"sekund"):n+"sekundami";case"m":return a?"minuta":s?"minutu":"minutou";case"mm":return a||s?n+(r(e)?"minuty":"minut"):n+"minutami";case"h":return a?"hodina":s?"hodinu":"hodinou";case"hh":return a||s?n+(r(e)?"hodiny":"hodin"):n+"hodinami";case"d":return a||s?"den":"dnem";case"dd":return a||s?n+(r(e)?"dny":"dní"):n+"dny";case"M":return a||s?"měsíc":"měsícem";case"MM":return a||s?n+(r(e)?"měsíce":"měsíců"):n+"měsíci";case"y":return a||s?"rok":"rokem";case"yy":return a||s?n+(r(e)?"roky":"let"):n+"lety"}}e.defineLocale("cs",{months:a,monthsShort:t,monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(leden|ledna|února|únor|březen|března|duben|dubna|květen|května|červenec|července|červen|června|srpen|srpna|září|říjen|října|listopadu|listopad|prosinec|prosince)/i,monthsShortStrictRegex:/^(led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:d,ss:d,m:d,mm:d,h:d,hh:d,d,dd:d,M:d,MM:d,y:d,yy:d},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},3635(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("cv",{months:"кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав".split("_"),monthsShort:"кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кӗҫ_эрн_шӑм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кҫ_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]",LLL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm",LLLL:"dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ӗнер] LT [сехетре]",nextWeek:"[Ҫитес] dddd LT [сехетре]",lastWeek:"[Иртнӗ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(e){return e+(/сехет$/i.exec(e)?"рен":/ҫул$/i.exec(e)?"тан":"ран")},past:"%s каялла",s:"пӗр-ик ҫеккунт",ss:"%d ҫеккунт",m:"пӗр минут",mm:"%d минут",h:"пӗр сехет",hh:"%d сехет",d:"пӗр кун",dd:"%d кун",M:"пӗр уйӑх",MM:"%d уйӑх",y:"пӗр ҫул",yy:"%d ҫул"},dayOfMonthOrdinalParse:/\d{1,2}-мӗш/,ordinal:"%d-мӗш",week:{dow:1,doy:7}})}(t(5093))},4226:function(e,a,t){!function(e){"use strict"; +e.defineLocale("cv",{months:"кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав".split("_"),monthsShort:"кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кӗҫ_эрн_шӑм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кҫ_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]",LLL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm",LLLL:"dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ӗнер] LT [сехетре]",nextWeek:"[Ҫитес] dddd LT [сехетре]",lastWeek:"[Иртнӗ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(e){return e+(/сехет$/i.exec(e)?"рен":/ҫул$/i.exec(e)?"тан":"ран")},past:"%s каялла",s:"пӗр-ик ҫеккунт",ss:"%d ҫеккунт",m:"пӗр минут",mm:"%d минут",h:"пӗр сехет",hh:"%d сехет",d:"пӗр кун",dd:"%d кун",M:"пӗр уйӑх",MM:"%d уйӑх",y:"пӗр ҫул",yy:"%d ҫул"},dayOfMonthOrdinalParse:/\d{1,2}-мӗш/,ordinal:"%d-мӗш",week:{dow:1,doy:7}})}(t(5093))},4226(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn ôl",s:"ychydig eiliadau",ss:"%d eiliad",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},dayOfMonthOrdinalParse:/\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,ordinal:function(e){var a="";return e>20?a=40===e||50===e||60===e||80===e||100===e?"fed":"ain":e>0&&(a=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed","eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"][e]),e+a},week:{dow:1,doy:4}})}(t(5093))},3601:function(e,a,t){!function(e){"use strict"; +e.defineLocale("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn ôl",s:"ychydig eiliadau",ss:"%d eiliad",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},dayOfMonthOrdinalParse:/\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,ordinal:function(e){var a="";return e>20?a=40===e||50===e||60===e||80===e||100===e?"fed":"ain":e>0&&(a=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed","eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"][e]),e+a},week:{dow:1,doy:4}})}(t(5093))},3601(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"på dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[i] dddd[s kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",ss:"%d sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},6111:function(e,a,t){!function(e){"use strict"; +e.defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"på dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[i] dddd[s kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",ss:"%d sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},6111(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?n[t][0]:n[t][1]}e.defineLocale("de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,w:a,ww:"%d Wochen",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},4697:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?n[t][0]:n[t][1]}e.defineLocale("de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,w:a,ww:"%d Wochen",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},4697(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?n[t][0]:n[t][1]}e.defineLocale("de-ch",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,w:a,ww:"%d Wochen",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7853:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?n[t][0]:n[t][1]}e.defineLocale("de-ch",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,w:a,ww:"%d Wochen",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7853(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?n[t][0]:n[t][1]}e.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,w:a,ww:"%d Wochen",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},708:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?n[t][0]:n[t][1]}e.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,w:a,ww:"%d Wochen",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},708(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=["ޖެނުއަރީ","ފެބްރުއަރީ","މާރިޗު","އޭޕްރީލު","މޭ","ޖޫން","ޖުލައި","އޯގަސްޓު","ސެޕްޓެމްބަރު","އޮކްޓޯބަރު","ނޮވެމްބަރު","ޑިސެމްބަރު"],t=["އާދިއްތަ","ހޯމަ","އަންގާރަ","ބުދަ","ބުރާސްފަތި","ހުކުރު","ހޮނިހިރު"];e.defineLocale("dv",{months:a,monthsShort:a,weekdays:t,weekdaysShort:t,weekdaysMin:"އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/މކ|މފ/,isPM:function(e){return"މފ"===e},meridiem:function(e,a,t){return e<12?"މކ":"މފ"},calendar:{sameDay:"[މިއަދު] LT",nextDay:"[މާދަމާ] LT",nextWeek:"dddd LT",lastDay:"[އިއްޔެ] LT",lastWeek:"[ފާއިތުވި] dddd LT",sameElse:"L"},relativeTime:{future:"ތެރޭގައި %s",past:"ކުރިން %s",s:"ސިކުންތުކޮޅެއް",ss:"d% ސިކުންތު",m:"މިނިޓެއް",mm:"މިނިޓު %d",h:"ގަޑިއިރެއް",hh:"ގަޑިއިރު %d",d:"ދުވަހެއް",dd:"ދުވަސް %d",M:"މަހެއް",MM:"މަސް %d",y:"އަހަރެއް",yy:"އަހަރު %d"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:7,doy:12}})}(t(5093))},4691:function(e,a,t){!function(e){"use strict"; +var a=["ޖެނުއަރީ","ފެބްރުއަރީ","މާރިޗު","އޭޕްރީލު","މޭ","ޖޫން","ޖުލައި","އޯގަސްޓު","ސެޕްޓެމްބަރު","އޮކްޓޯބަރު","ނޮވެމްބަރު","ޑިސެމްބަރު"],t=["އާދިއްތަ","ހޯމަ","އަންގާރަ","ބުދަ","ބުރާސްފަތި","ހުކުރު","ހޮނިހިރު"];e.defineLocale("dv",{months:a,monthsShort:a,weekdays:t,weekdaysShort:t,weekdaysMin:"އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/މކ|މފ/,isPM:function(e){return"މފ"===e},meridiem:function(e,a,t){return e<12?"މކ":"މފ"},calendar:{sameDay:"[މިއަދު] LT",nextDay:"[މާދަމާ] LT",nextWeek:"dddd LT",lastDay:"[އިއްޔެ] LT",lastWeek:"[ފާއިތުވި] dddd LT",sameElse:"L"},relativeTime:{future:"ތެރޭގައި %s",past:"ކުރިން %s",s:"ސިކުންތުކޮޅެއް",ss:"d% ސިކުންތު",m:"މިނިޓެއް",mm:"މިނިޓު %d",h:"ގަޑިއިރެއް",hh:"ގަޑިއިރު %d",d:"ދުވަހެއް",dd:"ދުވަސް %d",M:"މަހެއް",MM:"މަސް %d",y:"އަހަރެއް",yy:"އަހަރު %d"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:7,doy:12}})}(t(5093))},4691(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e){return"undefined"!=typeof Function&&e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}e.defineLocale("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(e,a){return e?"string"==typeof a&&/D/.test(a.substring(0,a.indexOf("MMMM")))?this._monthsGenitiveEl[e.month()]:this._monthsNominativeEl[e.month()]:this._monthsNominativeEl},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(e,a,t){return e>11?t?"μμ":"ΜΜ":t?"πμ":"ΠΜ"},isPM:function(e){return"μ"===(e+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){return 6===this.day()?"[το προηγούμενο] dddd [{}] LT":"[την προηγούμενη] dddd [{}] LT"},sameElse:"L"},calendar:function(e,t){var s=this._calendarEl[e],n=t&&t.hours();return a(s)&&(s=s.apply(t)),s.replace("{}",n%12==1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",ss:"%d δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},dayOfMonthOrdinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,doy:4}})}(t(5093))},3872:function(e,a,t){!function(e){"use strict"; +function a(e){return"undefined"!=typeof Function&&e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}e.defineLocale("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(e,a){return e?"string"==typeof a&&/D/.test(a.substring(0,a.indexOf("MMMM")))?this._monthsGenitiveEl[e.month()]:this._monthsNominativeEl[e.month()]:this._monthsNominativeEl},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(e,a,t){return e>11?t?"μμ":"ΜΜ":t?"πμ":"ΠΜ"},isPM:function(e){return"μ"===(e+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){return 6===this.day()?"[το προηγούμενο] dddd [{}] LT":"[την προηγούμενη] dddd [{}] LT"},sameElse:"L"},calendar:function(e,t){var s=this._calendarEl[e],n=t&&t.hours();return a(s)&&(s=s.apply(t)),s.replace("{}",n%12==1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",ss:"%d δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},dayOfMonthOrdinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,doy:4}})}(t(5093))},3872(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:0,doy:4}})}(t(5093))},8298:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:0,doy:4}})}(t(5093))},8298(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}})}(t(5093))},6195:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}})}(t(5093))},6195(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},6584:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},6584(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},5543:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},5543(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-il",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}})}(t(5093))},9033:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-il",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}})}(t(5093))},9033(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-in",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:0,doy:6}})}(t(5093))},9402:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-in",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:0,doy:6}})}(t(5093))},9402(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},3004:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},3004(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("en-sg",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},2934:function(e,a,t){!function(e){"use strict"; +e.defineLocale("en-sg",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},2934(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mart_apr_maj_jun_jul_aŭg_sept_okt_nov_dec".split("_"),weekdays:"dimanĉo_lundo_mardo_merkredo_ĵaŭdo_vendredo_sabato".split("_"),weekdaysShort:"dim_lun_mard_merk_ĵaŭ_ven_sab".split("_"),weekdaysMin:"di_lu_ma_me_ĵa_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"[la] D[-an de] MMMM, YYYY",LLL:"[la] D[-an de] MMMM, YYYY HH:mm",LLLL:"dddd[n], [la] D[-an de] MMMM, YYYY HH:mm",llll:"ddd, [la] D[-an de] MMM, YYYY HH:mm"},meridiemParse:/[ap]\.t\.m/i,isPM:function(e){return"p"===e.charAt(0).toLowerCase()},meridiem:function(e,a,t){return e>11?t?"p.t.m.":"P.T.M.":t?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodiaŭ je] LT",nextDay:"[Morgaŭ je] LT",nextWeek:"dddd[n je] LT",lastDay:"[Hieraŭ je] LT",lastWeek:"[pasintan] dddd[n je] LT",sameElse:"L"},relativeTime:{future:"post %s",past:"antaŭ %s",s:"kelkaj sekundoj",ss:"%d sekundoj",m:"unu minuto",mm:"%d minutoj",h:"unu horo",hh:"%d horoj",d:"unu tago",dd:"%d tagoj",M:"unu monato",MM:"%d monatoj",y:"unu jaro",yy:"%d jaroj"},dayOfMonthOrdinalParse:/\d{1,2}a/,ordinal:"%da",week:{dow:1,doy:7}})}(t(5093))},838:function(e,a,t){!function(e){"use strict"; +e.defineLocale("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mart_apr_maj_jun_jul_aŭg_sept_okt_nov_dec".split("_"),weekdays:"dimanĉo_lundo_mardo_merkredo_ĵaŭdo_vendredo_sabato".split("_"),weekdaysShort:"dim_lun_mard_merk_ĵaŭ_ven_sab".split("_"),weekdaysMin:"di_lu_ma_me_ĵa_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"[la] D[-an de] MMMM, YYYY",LLL:"[la] D[-an de] MMMM, YYYY HH:mm",LLLL:"dddd[n], [la] D[-an de] MMMM, YYYY HH:mm",llll:"ddd, [la] D[-an de] MMM, YYYY HH:mm"},meridiemParse:/[ap]\.t\.m/i,isPM:function(e){return"p"===e.charAt(0).toLowerCase()},meridiem:function(e,a,t){return e>11?t?"p.t.m.":"P.T.M.":t?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodiaŭ je] LT",nextDay:"[Morgaŭ je] LT",nextWeek:"dddd[n je] LT",lastDay:"[Hieraŭ je] LT",lastWeek:"[pasintan] dddd[n je] LT",sameElse:"L"},relativeTime:{future:"post %s",past:"antaŭ %s",s:"kelkaj sekundoj",ss:"%d sekundoj",m:"unu minuto",mm:"%d minutoj",h:"unu horo",hh:"%d horoj",d:"unu tago",dd:"%d tagoj",M:"unu monato",MM:"%d monatoj",y:"unu jaro",yy:"%d jaroj"},dayOfMonthOrdinalParse:/\d{1,2}a/,ordinal:"%da",week:{dow:1,doy:7}})}(t(5093))},838(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es-do",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},7730:function(e,a,t){!function(e){"use strict"; +var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es-do",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},7730(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es-mx",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:4},invalidDate:"Fecha inválida"})}(t(5093))},6575:function(e,a,t){!function(e){"use strict"; +var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es-mx",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:4},invalidDate:"Fecha inválida"})}(t(5093))},6575(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es-us",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"MM/DD/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:6}})}(t(5093))},7650:function(e,a,t){!function(e){"use strict"; +var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es-us",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"MM/DD/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:6}})}(t(5093))},7650(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4},invalidDate:"Fecha inválida"})}(t(5093))},3035:function(e,a,t){!function(e){"use strict"; +var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),s=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],n=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;e.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4},invalidDate:"Fecha inválida"})}(t(5093))},3035(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={s:["mõne sekundi","mõni sekund","paar sekundit"],ss:[e+"sekundi",e+"sekundit"],m:["ühe minuti","üks minut"],mm:[e+" minuti",e+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[e+" tunni",e+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[e+" kuu",e+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[e+" aasta",e+" aastat"]};return a?n[t][2]?n[t][2]:n[t][1]:s?n[t][0]:n[t][1]}e.defineLocale("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:"%d päeva",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},3508:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={s:["mõne sekundi","mõni sekund","paar sekundit"],ss:[e+"sekundi",e+"sekundit"],m:["ühe minuti","üks minut"],mm:[e+" minuti",e+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[e+" tunni",e+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[e+" kuu",e+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[e+" aasta",e+" aastat"]};return a?n[t][2]?n[t][2]:n[t][1]:s?n[t][0]:n[t][1]}e.defineLocale("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:"%d päeva",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},3508(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",ss:"%d segundo",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},119:function(e,a,t){!function(e){"use strict"; +e.defineLocale("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",ss:"%d segundo",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},119(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"},t={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"};e.defineLocale("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(e){return/بعد از ظهر/.test(e)},meridiem:function(e,a,t){return e<12?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چند ثانیه",ss:"%d ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(e){return e.replace(/[۰-۹]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},dayOfMonthOrdinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,doy:12}})}(t(5093))},527:function(e,a,t){!function(e){"use strict"; +var a={1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"},t={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"};e.defineLocale("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(e){return/بعد از ظهر/.test(e)},meridiem:function(e,a,t){return e<12?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چند ثانیه",ss:"%d ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(e){return e.replace(/[۰-۹]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},dayOfMonthOrdinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,doy:12}})}(t(5093))},527(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),t=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",a[7],a[8],a[9]];function s(e,a,t,s){var r="";switch(t){case"s":return s?"muutaman sekunnin":"muutama sekunti";case"ss":r=s?"sekunnin":"sekuntia";break;case"m":return s?"minuutin":"minuutti";case"mm":r=s?"minuutin":"minuuttia";break;case"h":return s?"tunnin":"tunti";case"hh":r=s?"tunnin":"tuntia";break;case"d":return s?"päivän":"päivä";case"dd":r=s?"päivän":"päivää";break;case"M":return s?"kuukauden":"kuukausi";case"MM":r=s?"kuukauden":"kuukautta";break;case"y":return s?"vuoden":"vuosi";case"yy":r=s?"vuoden":"vuotta"}return r=n(e,s)+" "+r}function n(e,s){return e<10?s?t[e]:a[e]:e}e.defineLocale("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s,ss:s,m:s,mm:s,h:s,hh:s,d:s,dd:s,M:s,MM:s,y:s,yy:s},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},5995:function(e,a,t){!function(e){"use strict"; +var a="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),t=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",a[7],a[8],a[9]];function s(e,a,t,s){var r="";switch(t){case"s":return s?"muutaman sekunnin":"muutama sekunti";case"ss":r=s?"sekunnin":"sekuntia";break;case"m":return s?"minuutin":"minuutti";case"mm":r=s?"minuutin":"minuuttia";break;case"h":return s?"tunnin":"tunti";case"hh":r=s?"tunnin":"tuntia";break;case"d":return s?"päivän":"päivä";case"dd":r=s?"päivän":"päivää";break;case"M":return s?"kuukauden":"kuukausi";case"MM":r=s?"kuukauden":"kuukautta";break;case"y":return s?"vuoden":"vuosi";case"yy":r=s?"vuoden":"vuotta"}return r=n(e,s)+" "+r}function n(e,s){return e<10?s?t[e]:a[e]:e}e.defineLocale("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s,ss:s,m:s,mm:s,h:s,hh:s,d:s,dd:s,M:s,MM:s,y:s,yy:s},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},5995(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("fil",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"LT [ngayong araw]",nextDay:"[Bukas ng] LT",nextWeek:"LT [sa susunod na] dddd",lastDay:"LT [kahapon]",lastWeek:"LT [noong nakaraang] dddd",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",ss:"%d segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})}(t(5093))},2477:function(e,a,t){!function(e){"use strict"; +e.defineLocale("fil",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"LT [ngayong araw]",nextDay:"[Bukas ng] LT",nextWeek:"LT [sa susunod na] dddd",lastDay:"LT [kahapon]",lastWeek:"LT [noong nakaraang] dddd",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",ss:"%d segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})}(t(5093))},2477(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("fo",{months:"januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),weekdaysShort:"sun_mán_týs_mik_hós_frí_ley".split("_"),weekdaysMin:"su_má_tý_mi_hó_fr_le".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D. MMMM, YYYY HH:mm"},calendar:{sameDay:"[Í dag kl.] LT",nextDay:"[Í morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[Í gjár kl.] LT",lastWeek:"[síðstu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s síðani",s:"fá sekund",ss:"%d sekundir",m:"ein minuttur",mm:"%d minuttir",h:"ein tími",hh:"%d tímar",d:"ein dagur",dd:"%d dagar",M:"ein mánaður",MM:"%d mánaðir",y:"eitt ár",yy:"%d ár"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},6435:function(e,a,t){!function(e){"use strict"; +e.defineLocale("fo",{months:"januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),weekdaysShort:"sun_mán_týs_mik_hós_frí_ley".split("_"),weekdaysMin:"su_má_tý_mi_hó_fr_le".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D. MMMM, YYYY HH:mm"},calendar:{sameDay:"[Í dag kl.] LT",nextDay:"[Í morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[Í gjár kl.] LT",lastWeek:"[síðstu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s síðani",s:"fá sekund",ss:"%d sekundir",m:"ein minuttur",mm:"%d minuttir",h:"ein tími",hh:"%d tímar",d:"ein dagur",dd:"%d dagar",M:"ein mánaður",MM:"%d mánaðir",y:"eitt ár",yy:"%d ár"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},6435(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(e,a){switch(a){default:case"M":case"Q":case"D":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}}})}(t(5093))},7892:function(e,a,t){!function(e){"use strict"; +e.defineLocale("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(e,a){switch(a){default:case"M":case"Q":case"D":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}}})}(t(5093))},7892(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(e,a){switch(a){default:case"M":case"Q":case"D":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})}(t(5093))},5498:function(e,a,t){!function(e){"use strict"; +e.defineLocale("fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(e,a){switch(a){default:case"M":case"Q":case"D":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})}(t(5093))},5498(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=/^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,t=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?)/i,s=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,n=[/^janv/i,/^févr/i,/^mars/i,/^avr/i,/^mai/i,/^juin/i,/^juil/i,/^août/i,/^sept/i,/^oct/i,/^nov/i,/^déc/i];e.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsRegex:s,monthsShortRegex:s,monthsStrictRegex:a,monthsShortStrictRegex:t,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",w:"une semaine",ww:"%d semaines",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(e,a){switch(a){case"D":return e+(1===e?"er":"");default:case"M":case"Q":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})}(t(5093))},7071:function(e,a,t){!function(e){"use strict"; +var a=/^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,t=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?)/i,s=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,n=[/^janv/i,/^févr/i,/^mars/i,/^avr/i,/^mai/i,/^juin/i,/^juil/i,/^août/i,/^sept/i,/^oct/i,/^nov/i,/^déc/i];e.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsRegex:s,monthsShortRegex:s,monthsStrictRegex:a,monthsShortStrictRegex:t,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",w:"une semaine",ww:"%d semaines",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(e,a){switch(a){case"D":return e+(1===e?"er":"");default:case"M":case"Q":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})}(t(5093))},7071(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.".split("_"),t="jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_");e.defineLocale("fy",{months:"jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsParseExact:!0,weekdays:"snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon".split("_"),weekdaysShort:"si._mo._ti._wo._to._fr._so.".split("_"),weekdaysMin:"Si_Mo_Ti_Wo_To_Fr_So".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[hjoed om] LT",nextDay:"[moarn om] LT",nextWeek:"dddd [om] LT",lastDay:"[juster om] LT",lastWeek:"[ôfrûne] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oer %s",past:"%s lyn",s:"in pear sekonden",ss:"%d sekonden",m:"ien minút",mm:"%d minuten",h:"ien oere",hh:"%d oeren",d:"ien dei",dd:"%d dagen",M:"ien moanne",MM:"%d moannen",y:"ien jier",yy:"%d jierren"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},1734:function(e,a,t){!function(e){"use strict"; +var a="jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.".split("_"),t="jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_");e.defineLocale("fy",{months:"jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsParseExact:!0,weekdays:"snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon".split("_"),weekdaysShort:"si._mo._ti._wo._to._fr._so.".split("_"),weekdaysMin:"Si_Mo_Ti_Wo_To_Fr_So".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[hjoed om] LT",nextDay:"[moarn om] LT",nextWeek:"dddd [om] LT",lastDay:"[juster om] LT",lastWeek:"[ôfrûne] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oer %s",past:"%s lyn",s:"in pear sekonden",ss:"%d sekonden",m:"ien minút",mm:"%d minuten",h:"ien oere",hh:"%d oeren",d:"ien dei",dd:"%d dagen",M:"ien moanne",MM:"%d moannen",y:"ien jier",yy:"%d jierren"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},1734(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=["Eanáir","Feabhra","Márta","Aibreán","Bealtaine","Meitheamh","Iúil","Lúnasa","Meán Fómhair","Deireadh Fómhair","Samhain","Nollaig"],t=["Ean","Feabh","Márt","Aib","Beal","Meith","Iúil","Lún","M.F.","D.F.","Samh","Noll"],s=["Dé Domhnaigh","Dé Luain","Dé Máirt","Dé Céadaoin","Déardaoin","Dé hAoine","Dé Sathairn"],n=["Domh","Luan","Máirt","Céad","Déar","Aoine","Sath"],r=["Do","Lu","Má","Cé","Dé","A","Sa"];e.defineLocale("ga",{months:a,monthsShort:t,monthsParseExact:!0,weekdays:s,weekdaysShort:n,weekdaysMin:r,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Inniu ag] LT",nextDay:"[Amárach ag] LT",nextWeek:"dddd [ag] LT",lastDay:"[Inné ag] LT",lastWeek:"dddd [seo caite] [ag] LT",sameElse:"L"},relativeTime:{future:"i %s",past:"%s ó shin",s:"cúpla soicind",ss:"%d soicind",m:"nóiméad",mm:"%d nóiméad",h:"uair an chloig",hh:"%d uair an chloig",d:"lá",dd:"%d lá",M:"mí",MM:"%d míonna",y:"bliain",yy:"%d bliain"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(e){return e+(1===e?"d":e%10==2?"na":"mh")},week:{dow:1,doy:4}})}(t(5093))},217:function(e,a,t){!function(e){"use strict"; +var a=["Eanáir","Feabhra","Márta","Aibreán","Bealtaine","Meitheamh","Iúil","Lúnasa","Meán Fómhair","Deireadh Fómhair","Samhain","Nollaig"],t=["Ean","Feabh","Márt","Aib","Beal","Meith","Iúil","Lún","M.F.","D.F.","Samh","Noll"],s=["Dé Domhnaigh","Dé Luain","Dé Máirt","Dé Céadaoin","Déardaoin","Dé hAoine","Dé Sathairn"],n=["Domh","Luan","Máirt","Céad","Déar","Aoine","Sath"],r=["Do","Lu","Má","Cé","Dé","A","Sa"];e.defineLocale("ga",{months:a,monthsShort:t,monthsParseExact:!0,weekdays:s,weekdaysShort:n,weekdaysMin:r,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Inniu ag] LT",nextDay:"[Amárach ag] LT",nextWeek:"dddd [ag] LT",lastDay:"[Inné ag] LT",lastWeek:"dddd [seo caite] [ag] LT",sameElse:"L"},relativeTime:{future:"i %s",past:"%s ó shin",s:"cúpla soicind",ss:"%d soicind",m:"nóiméad",mm:"%d nóiméad",h:"uair an chloig",hh:"%d uair an chloig",d:"lá",dd:"%d lá",M:"mí",MM:"%d míonna",y:"bliain",yy:"%d bliain"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(e){return e+(1===e?"d":e%10==2?"na":"mh")},week:{dow:1,doy:4}})}(t(5093))},217(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=["Am Faoilleach","An Gearran","Am Màrt","An Giblean","An Cèitean","An t-Ògmhios","An t-Iuchar","An Lùnastal","An t-Sultain","An Dàmhair","An t-Samhain","An Dùbhlachd"],t=["Faoi","Gear","Màrt","Gibl","Cèit","Ògmh","Iuch","Lùn","Sult","Dàmh","Samh","Dùbh"],s=["Didòmhnaich","Diluain","Dimàirt","Diciadain","Diardaoin","Dihaoine","Disathairne"],n=["Did","Dil","Dim","Dic","Dia","Dih","Dis"],r=["Dò","Lu","Mà","Ci","Ar","Ha","Sa"];e.defineLocale("gd",{months:a,monthsShort:t,monthsParseExact:!0,weekdays:s,weekdaysShort:n,weekdaysMin:r,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[An-diugh aig] LT",nextDay:"[A-màireach aig] LT",nextWeek:"dddd [aig] LT",lastDay:"[An-dè aig] LT",lastWeek:"dddd [seo chaidh] [aig] LT",sameElse:"L"},relativeTime:{future:"ann an %s",past:"bho chionn %s",s:"beagan diogan",ss:"%d diogan",m:"mionaid",mm:"%d mionaidean",h:"uair",hh:"%d uairean",d:"latha",dd:"%d latha",M:"mìos",MM:"%d mìosan",y:"bliadhna",yy:"%d bliadhna"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(e){return e+(1===e?"d":e%10==2?"na":"mh")},week:{dow:1,doy:4}})}(t(5093))},7329:function(e,a,t){!function(e){"use strict"; +var a=["Am Faoilleach","An Gearran","Am Màrt","An Giblean","An Cèitean","An t-Ògmhios","An t-Iuchar","An Lùnastal","An t-Sultain","An Dàmhair","An t-Samhain","An Dùbhlachd"],t=["Faoi","Gear","Màrt","Gibl","Cèit","Ògmh","Iuch","Lùn","Sult","Dàmh","Samh","Dùbh"],s=["Didòmhnaich","Diluain","Dimàirt","Diciadain","Diardaoin","Dihaoine","Disathairne"],n=["Did","Dil","Dim","Dic","Dia","Dih","Dis"],r=["Dò","Lu","Mà","Ci","Ar","Ha","Sa"];e.defineLocale("gd",{months:a,monthsShort:t,monthsParseExact:!0,weekdays:s,weekdaysShort:n,weekdaysMin:r,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[An-diugh aig] LT",nextDay:"[A-màireach aig] LT",nextWeek:"dddd [aig] LT",lastDay:"[An-dè aig] LT",lastWeek:"dddd [seo chaidh] [aig] LT",sameElse:"L"},relativeTime:{future:"ann an %s",past:"bho chionn %s",s:"beagan diogan",ss:"%d diogan",m:"mionaid",mm:"%d mionaidean",h:"uair",hh:"%d uairean",d:"latha",dd:"%d latha",M:"mìos",MM:"%d mìosan",y:"bliadhna",yy:"%d bliadhna"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(e){return e+(1===e?"d":e%10==2?"na":"mh")},week:{dow:1,doy:4}})}(t(5093))},7329(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("gl",{months:"xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro".split("_"),monthsShort:"xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"domingo_luns_martes_mércores_xoves_venres_sábado".split("_"),weekdaysShort:"dom._lun._mar._mér._xov._ven._sáb.".split("_"),weekdaysMin:"do_lu_ma_mé_xo_ve_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(e){return 0===e.indexOf("un")?"n"+e:"en "+e},past:"hai %s",s:"uns segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},2124:function(e,a,t){!function(e){"use strict"; +e.defineLocale("gl",{months:"xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro".split("_"),monthsShort:"xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"domingo_luns_martes_mércores_xoves_venres_sábado".split("_"),weekdaysShort:"dom._lun._mar._mér._xov._ven._sáb.".split("_"),weekdaysMin:"do_lu_ma_mé_xo_ve_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(e){return 0===e.indexOf("un")?"n"+e:"en "+e},past:"hai %s",s:"uns segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},2124(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={s:["थोडया सॅकंडांनी","थोडे सॅकंड"],ss:[e+" सॅकंडांनी",e+" सॅकंड"],m:["एका मिणटान","एक मिनूट"],mm:[e+" मिणटांनी",e+" मिणटां"],h:["एका वरान","एक वर"],hh:[e+" वरांनी",e+" वरां"],d:["एका दिसान","एक दीस"],dd:[e+" दिसांनी",e+" दीस"],M:["एका म्हयन्यान","एक म्हयनो"],MM:[e+" म्हयन्यानी",e+" म्हयने"],y:["एका वर्सान","एक वर्स"],yy:[e+" वर्सांनी",e+" वर्सां"]};return s?n[t][0]:n[t][1]}e.defineLocale("gom-deva",{months:{standalone:"जानेवारी_फेब्रुवारी_मार्च_एप्रील_मे_जून_जुलय_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),format:"जानेवारीच्या_फेब्रुवारीच्या_मार्चाच्या_एप्रीलाच्या_मेयाच्या_जूनाच्या_जुलयाच्या_ऑगस्टाच्या_सप्टेंबराच्या_ऑक्टोबराच्या_नोव्हेंबराच्या_डिसेंबराच्या".split("_"),isFormat:/MMMM(\s)+D[oD]?/},monthsShort:"जाने._फेब्रु._मार्च_एप्री._मे_जून_जुल._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"आयतार_सोमार_मंगळार_बुधवार_बिरेस्तार_सुक्रार_शेनवार".split("_"),weekdaysShort:"आयत._सोम._मंगळ._बुध._ब्रेस्त._सुक्र._शेन.".split("_"),weekdaysMin:"आ_सो_मं_बु_ब्रे_सु_शे".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A h:mm [वाजतां]",LTS:"A h:mm:ss [वाजतां]",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY A h:mm [वाजतां]",LLLL:"dddd, MMMM Do, YYYY, A h:mm [वाजतां]",llll:"ddd, D MMM YYYY, A h:mm [वाजतां]"},calendar:{sameDay:"[आयज] LT",nextDay:"[फाल्यां] LT",nextWeek:"[फुडलो] dddd[,] LT",lastDay:"[काल] LT",lastWeek:"[फाटलो] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s",past:"%s आदीं",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}(वेर)/,ordinal:function(e,a){return"D"===a?e+"वेर":e},week:{dow:0,doy:3},meridiemParse:/राती|सकाळीं|दनपारां|सांजे/,meridiemHour:function(e,a){return 12===e&&(e=0),"राती"===a?e<4?e:e+12:"सकाळीं"===a?e:"दनपारां"===a?e>12?e:e+12:"सांजे"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"राती":e<12?"सकाळीं":e<16?"दनपारां":e<20?"सांजे":"राती"}})}(t(5093))},3383:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={s:["थोडया सॅकंडांनी","थोडे सॅकंड"],ss:[e+" सॅकंडांनी",e+" सॅकंड"],m:["एका मिणटान","एक मिनूट"],mm:[e+" मिणटांनी",e+" मिणटां"],h:["एका वरान","एक वर"],hh:[e+" वरांनी",e+" वरां"],d:["एका दिसान","एक दीस"],dd:[e+" दिसांनी",e+" दीस"],M:["एका म्हयन्यान","एक म्हयनो"],MM:[e+" म्हयन्यानी",e+" म्हयने"],y:["एका वर्सान","एक वर्स"],yy:[e+" वर्सांनी",e+" वर्सां"]};return s?n[t][0]:n[t][1]}e.defineLocale("gom-deva",{months:{standalone:"जानेवारी_फेब्रुवारी_मार्च_एप्रील_मे_जून_जुलय_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),format:"जानेवारीच्या_फेब्रुवारीच्या_मार्चाच्या_एप्रीलाच्या_मेयाच्या_जूनाच्या_जुलयाच्या_ऑगस्टाच्या_सप्टेंबराच्या_ऑक्टोबराच्या_नोव्हेंबराच्या_डिसेंबराच्या".split("_"),isFormat:/MMMM(\s)+D[oD]?/},monthsShort:"जाने._फेब्रु._मार्च_एप्री._मे_जून_जुल._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"आयतार_सोमार_मंगळार_बुधवार_बिरेस्तार_सुक्रार_शेनवार".split("_"),weekdaysShort:"आयत._सोम._मंगळ._बुध._ब्रेस्त._सुक्र._शेन.".split("_"),weekdaysMin:"आ_सो_मं_बु_ब्रे_सु_शे".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A h:mm [वाजतां]",LTS:"A h:mm:ss [वाजतां]",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY A h:mm [वाजतां]",LLLL:"dddd, MMMM Do, YYYY, A h:mm [वाजतां]",llll:"ddd, D MMM YYYY, A h:mm [वाजतां]"},calendar:{sameDay:"[आयज] LT",nextDay:"[फाल्यां] LT",nextWeek:"[फुडलो] dddd[,] LT",lastDay:"[काल] LT",lastWeek:"[फाटलो] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s",past:"%s आदीं",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}(वेर)/,ordinal:function(e,a){return"D"===a?e+"वेर":e},week:{dow:0,doy:3},meridiemParse:/राती|सकाळीं|दनपारां|सांजे/,meridiemHour:function(e,a){return 12===e&&(e=0),"राती"===a?e<4?e:e+12:"सकाळीं"===a?e:"दनपारां"===a?e>12?e:e+12:"सांजे"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"राती":e<12?"सकाळीं":e<16?"दनपारां":e<20?"सांजे":"राती"}})}(t(5093))},3383(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={s:["thoddea sekondamni","thodde sekond"],ss:[e+" sekondamni",e+" sekond"],m:["eka mintan","ek minut"],mm:[e+" mintamni",e+" mintam"],h:["eka voran","ek vor"],hh:[e+" voramni",e+" voram"],d:["eka disan","ek dis"],dd:[e+" disamni",e+" dis"],M:["eka mhoinean","ek mhoino"],MM:[e+" mhoineamni",e+" mhoine"],y:["eka vorsan","ek voros"],yy:[e+" vorsamni",e+" vorsam"]};return s?n[t][0]:n[t][1]}e.defineLocale("gom-latn",{months:{standalone:"Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr".split("_"),format:"Janerachea_Febrerachea_Marsachea_Abrilachea_Maiachea_Junachea_Julaiachea_Agostachea_Setembrachea_Otubrachea_Novembrachea_Dezembrachea".split("_"),isFormat:/MMMM(\s)+D[oD]?/},monthsShort:"Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Aitar_Somar_Mongllar_Budhvar_Birestar_Sukrar_Son'var".split("_"),weekdaysShort:"Ait._Som._Mon._Bud._Bre._Suk._Son.".split("_"),weekdaysMin:"Ai_Sm_Mo_Bu_Br_Su_Sn".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A h:mm [vazta]",LTS:"A h:mm:ss [vazta]",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY A h:mm [vazta]",LLLL:"dddd, MMMM Do, YYYY, A h:mm [vazta]",llll:"ddd, D MMM YYYY, A h:mm [vazta]"},calendar:{sameDay:"[Aiz] LT",nextDay:"[Faleam] LT",nextWeek:"[Fuddlo] dddd[,] LT",lastDay:"[Kal] LT",lastWeek:"[Fattlo] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s",past:"%s adim",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}(er)/,ordinal:function(e,a){return"D"===a?e+"er":e},week:{dow:0,doy:3},meridiemParse:/rati|sokallim|donparam|sanje/,meridiemHour:function(e,a){return 12===e&&(e=0),"rati"===a?e<4?e:e+12:"sokallim"===a?e:"donparam"===a?e>12?e:e+12:"sanje"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"rati":e<12?"sokallim":e<16?"donparam":e<20?"sanje":"rati"}})}(t(5093))},5050:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={s:["thoddea sekondamni","thodde sekond"],ss:[e+" sekondamni",e+" sekond"],m:["eka mintan","ek minut"],mm:[e+" mintamni",e+" mintam"],h:["eka voran","ek vor"],hh:[e+" voramni",e+" voram"],d:["eka disan","ek dis"],dd:[e+" disamni",e+" dis"],M:["eka mhoinean","ek mhoino"],MM:[e+" mhoineamni",e+" mhoine"],y:["eka vorsan","ek voros"],yy:[e+" vorsamni",e+" vorsam"]};return s?n[t][0]:n[t][1]}e.defineLocale("gom-latn",{months:{standalone:"Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr".split("_"),format:"Janerachea_Febrerachea_Marsachea_Abrilachea_Maiachea_Junachea_Julaiachea_Agostachea_Setembrachea_Otubrachea_Novembrachea_Dezembrachea".split("_"),isFormat:/MMMM(\s)+D[oD]?/},monthsShort:"Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Aitar_Somar_Mongllar_Budhvar_Birestar_Sukrar_Son'var".split("_"),weekdaysShort:"Ait._Som._Mon._Bud._Bre._Suk._Son.".split("_"),weekdaysMin:"Ai_Sm_Mo_Bu_Br_Su_Sn".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A h:mm [vazta]",LTS:"A h:mm:ss [vazta]",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY A h:mm [vazta]",LLLL:"dddd, MMMM Do, YYYY, A h:mm [vazta]",llll:"ddd, D MMM YYYY, A h:mm [vazta]"},calendar:{sameDay:"[Aiz] LT",nextDay:"[Faleam] LT",nextWeek:"[Fuddlo] dddd[,] LT",lastDay:"[Kal] LT",lastWeek:"[Fattlo] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s",past:"%s adim",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}(er)/,ordinal:function(e,a){return"D"===a?e+"er":e},week:{dow:0,doy:3},meridiemParse:/rati|sokallim|donparam|sanje/,meridiemHour:function(e,a){return 12===e&&(e=0),"rati"===a?e<4?e:e+12:"sokallim"===a?e:"donparam"===a?e>12?e:e+12:"sanje"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"rati":e<12?"sokallim":e<16?"donparam":e<20?"sanje":"rati"}})}(t(5093))},5050(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"૧",2:"૨",3:"૩",4:"૪",5:"૫",6:"૬",7:"૭",8:"૮",9:"૯",0:"૦"},t={"૧":"1","૨":"2","૩":"3","૪":"4","૫":"5","૬":"6","૭":"7","૮":"8","૯":"9","૦":"0"};e.defineLocale("gu",{months:"જાન્યુઆરી_ફેબ્રુઆરી_માર્ચ_એપ્રિલ_મે_જૂન_જુલાઈ_ઑગસ્ટ_સપ્ટેમ્બર_ઑક્ટ્બર_નવેમ્બર_ડિસેમ્બર".split("_"),monthsShort:"જાન્યુ._ફેબ્રુ._માર્ચ_એપ્રિ._મે_જૂન_જુલા._ઑગ._સપ્ટે._ઑક્ટ્._નવે._ડિસે.".split("_"),monthsParseExact:!0,weekdays:"રવિવાર_સોમવાર_મંગળવાર_બુધ્વાર_ગુરુવાર_શુક્રવાર_શનિવાર".split("_"),weekdaysShort:"રવિ_સોમ_મંગળ_બુધ્_ગુરુ_શુક્ર_શનિ".split("_"),weekdaysMin:"ર_સો_મં_બુ_ગુ_શુ_શ".split("_"),longDateFormat:{LT:"A h:mm વાગ્યે",LTS:"A h:mm:ss વાગ્યે",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm વાગ્યે",LLLL:"dddd, D MMMM YYYY, A h:mm વાગ્યે"},calendar:{sameDay:"[આજ] LT",nextDay:"[કાલે] LT",nextWeek:"dddd, LT",lastDay:"[ગઇકાલે] LT",lastWeek:"[પાછલા] dddd, LT",sameElse:"L"},relativeTime:{future:"%s મા",past:"%s પહેલા",s:"અમુક પળો",ss:"%d સેકંડ",m:"એક મિનિટ",mm:"%d મિનિટ",h:"એક કલાક",hh:"%d કલાક",d:"એક દિવસ",dd:"%d દિવસ",M:"એક મહિનો",MM:"%d મહિનો",y:"એક વર્ષ",yy:"%d વર્ષ"},preparse:function(e){return e.replace(/[૧૨૩૪૫૬૭૮૯૦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/રાત|બપોર|સવાર|સાંજ/,meridiemHour:function(e,a){return 12===e&&(e=0),"રાત"===a?e<4?e:e+12:"સવાર"===a?e:"બપોર"===a?e>=10?e:e+12:"સાંજ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"રાત":e<10?"સવાર":e<17?"બપોર":e<20?"સાંજ":"રાત"},week:{dow:0,doy:6}})}(t(5093))},1713:function(e,a,t){!function(e){"use strict"; +var a={1:"૧",2:"૨",3:"૩",4:"૪",5:"૫",6:"૬",7:"૭",8:"૮",9:"૯",0:"૦"},t={"૧":"1","૨":"2","૩":"3","૪":"4","૫":"5","૬":"6","૭":"7","૮":"8","૯":"9","૦":"0"};e.defineLocale("gu",{months:"જાન્યુઆરી_ફેબ્રુઆરી_માર્ચ_એપ્રિલ_મે_જૂન_જુલાઈ_ઑગસ્ટ_સપ્ટેમ્બર_ઑક્ટ્બર_નવેમ્બર_ડિસેમ્બર".split("_"),monthsShort:"જાન્યુ._ફેબ્રુ._માર્ચ_એપ્રિ._મે_જૂન_જુલા._ઑગ._સપ્ટે._ઑક્ટ્._નવે._ડિસે.".split("_"),monthsParseExact:!0,weekdays:"રવિવાર_સોમવાર_મંગળવાર_બુધ્વાર_ગુરુવાર_શુક્રવાર_શનિવાર".split("_"),weekdaysShort:"રવિ_સોમ_મંગળ_બુધ્_ગુરુ_શુક્ર_શનિ".split("_"),weekdaysMin:"ર_સો_મં_બુ_ગુ_શુ_શ".split("_"),longDateFormat:{LT:"A h:mm વાગ્યે",LTS:"A h:mm:ss વાગ્યે",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm વાગ્યે",LLLL:"dddd, D MMMM YYYY, A h:mm વાગ્યે"},calendar:{sameDay:"[આજ] LT",nextDay:"[કાલે] LT",nextWeek:"dddd, LT",lastDay:"[ગઇકાલે] LT",lastWeek:"[પાછલા] dddd, LT",sameElse:"L"},relativeTime:{future:"%s મા",past:"%s પહેલા",s:"અમુક પળો",ss:"%d સેકંડ",m:"એક મિનિટ",mm:"%d મિનિટ",h:"એક કલાક",hh:"%d કલાક",d:"એક દિવસ",dd:"%d દિવસ",M:"એક મહિનો",MM:"%d મહિનો",y:"એક વર્ષ",yy:"%d વર્ષ"},preparse:function(e){return e.replace(/[૧૨૩૪૫૬૭૮૯૦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/રાત|બપોર|સવાર|સાંજ/,meridiemHour:function(e,a){return 12===e&&(e=0),"રાત"===a?e<4?e:e+12:"સવાર"===a?e:"બપોર"===a?e>=10?e:e+12:"સાંજ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"રાત":e<10?"સવાર":e<17?"બપોર":e<20?"સાંજ":"રાત"},week:{dow:0,doy:6}})}(t(5093))},1713(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",ss:"%d שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(e){return 2===e?"שעתיים":e+" שעות"},d:"יום",dd:function(e){return 2===e?"יומיים":e+" ימים"},M:"חודש",MM:function(e){return 2===e?"חודשיים":e+" חודשים"},y:"שנה",yy:function(e){return 2===e?"שנתיים":e%10==0&&10!==e?e+" שנה":e+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(e){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(e)},meridiem:function(e,a,t){return e<5?"לפנות בוקר":e<10?"בבוקר":e<12?t?'לפנה"צ':"לפני הצהריים":e<18?t?'אחה"צ':"אחרי הצהריים":"בערב"}})}(t(5093))},3861:function(e,a,t){!function(e){"use strict"; +e.defineLocale("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",ss:"%d שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(e){return 2===e?"שעתיים":e+" שעות"},d:"יום",dd:function(e){return 2===e?"יומיים":e+" ימים"},M:"חודש",MM:function(e){return 2===e?"חודשיים":e+" חודשים"},y:"שנה",yy:function(e){return 2===e?"שנתיים":e%10==0&&10!==e?e+" שנה":e+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(e){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(e)},meridiem:function(e,a,t){return e<5?"לפנות בוקר":e<10?"בבוקר":e<12?t?'לפנה"צ':"לפני הצהריים":e<18?t?'אחה"צ':"אחרי הצהריים":"בערב"}})}(t(5093))},3861(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},s=[/^जन/i,/^फ़र|फर/i,/^मार्च/i,/^अप्रै/i,/^मई/i,/^जून/i,/^जुल/i,/^अग/i,/^सितं|सित/i,/^अक्टू/i,/^नव|नवं/i,/^दिसं|दिस/i],n=[/^जन/i,/^फ़र/i,/^मार्च/i,/^अप्रै/i,/^मई/i,/^जून/i,/^जुल/i,/^अग/i,/^सित/i,/^अक्टू/i,/^नव/i,/^दिस/i];e.defineLocale("hi",{months:{format:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),standalone:"जनवरी_फरवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितंबर_अक्टूबर_नवंबर_दिसंबर".split("_")},monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},monthsParse:s,longMonthsParse:s,shortMonthsParse:n,monthsRegex:/^(जनवरी|जन\.?|फ़रवरी|फरवरी|फ़र\.?|मार्च?|अप्रैल|अप्रै\.?|मई?|जून?|जुलाई|जुल\.?|अगस्त|अग\.?|सितम्बर|सितंबर|सित\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर|नव\.?|दिसम्बर|दिसंबर|दिस\.?)/i,monthsShortRegex:/^(जनवरी|जन\.?|फ़रवरी|फरवरी|फ़र\.?|मार्च?|अप्रैल|अप्रै\.?|मई?|जून?|जुलाई|जुल\.?|अगस्त|अग\.?|सितम्बर|सितंबर|सित\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर|नव\.?|दिसम्बर|दिसंबर|दिस\.?)/i,monthsStrictRegex:/^(जनवरी?|फ़रवरी|फरवरी?|मार्च?|अप्रैल?|मई?|जून?|जुलाई?|अगस्त?|सितम्बर|सितंबर|सित?\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर?|दिसम्बर|दिसंबर?)/i,monthsShortStrictRegex:/^(जन\.?|फ़र\.?|मार्च?|अप्रै\.?|मई?|जून?|जुल\.?|अग\.?|सित\.?|अक्टू\.?|नव\.?|दिस\.?)/i,calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",ss:"%d सेकंड",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(e,a){return 12===e&&(e=0),"रात"===a?e<4?e:e+12:"सुबह"===a?e:"दोपहर"===a?e>=10?e:e+12:"शाम"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"रात":e<10?"सुबह":e<17?"दोपहर":e<20?"शाम":"रात"},week:{dow:0,doy:6}})}(t(5093))},6308:function(e,a,t){!function(e){"use strict"; +var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},s=[/^जन/i,/^फ़र|फर/i,/^मार्च/i,/^अप्रै/i,/^मई/i,/^जून/i,/^जुल/i,/^अग/i,/^सितं|सित/i,/^अक्टू/i,/^नव|नवं/i,/^दिसं|दिस/i],n=[/^जन/i,/^फ़र/i,/^मार्च/i,/^अप्रै/i,/^मई/i,/^जून/i,/^जुल/i,/^अग/i,/^सित/i,/^अक्टू/i,/^नव/i,/^दिस/i];e.defineLocale("hi",{months:{format:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),standalone:"जनवरी_फरवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितंबर_अक्टूबर_नवंबर_दिसंबर".split("_")},monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},monthsParse:s,longMonthsParse:s,shortMonthsParse:n,monthsRegex:/^(जनवरी|जन\.?|फ़रवरी|फरवरी|फ़र\.?|मार्च?|अप्रैल|अप्रै\.?|मई?|जून?|जुलाई|जुल\.?|अगस्त|अग\.?|सितम्बर|सितंबर|सित\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर|नव\.?|दिसम्बर|दिसंबर|दिस\.?)/i,monthsShortRegex:/^(जनवरी|जन\.?|फ़रवरी|फरवरी|फ़र\.?|मार्च?|अप्रैल|अप्रै\.?|मई?|जून?|जुलाई|जुल\.?|अगस्त|अग\.?|सितम्बर|सितंबर|सित\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर|नव\.?|दिसम्बर|दिसंबर|दिस\.?)/i,monthsStrictRegex:/^(जनवरी?|फ़रवरी|फरवरी?|मार्च?|अप्रैल?|मई?|जून?|जुलाई?|अगस्त?|सितम्बर|सितंबर|सित?\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर?|दिसम्बर|दिसंबर?)/i,monthsShortStrictRegex:/^(जन\.?|फ़र\.?|मार्च?|अप्रै\.?|मई?|जून?|जुल\.?|अग\.?|सित\.?|अक्टू\.?|नव\.?|दिस\.?)/i,calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",ss:"%d सेकंड",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(e,a){return 12===e&&(e=0),"रात"===a?e<4?e:e+12:"सुबह"===a?e:"दोपहर"===a?e>=10?e:e+12:"शाम"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"रात":e<10?"सुबह":e<17?"दोपहर":e<20?"शाम":"रात"},week:{dow:0,doy:6}})}(t(5093))},6308(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t){var s=e+" ";switch(t){case"ss":return s+=1===e?"sekunda":2===e||3===e||4===e?"sekunde":"sekundi";case"m":return a?"jedna minuta":"jedne minute";case"mm":return s+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return a?"jedan sat":"jednog sata";case"hh":return s+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return s+=1===e?"dan":"dana";case"MM":return s+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return s+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}e.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"Do MMMM YYYY",LLL:"Do MMMM YYYY H:mm",LLLL:"dddd, Do MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:return"[prošlu] [nedjelju] [u] LT";case 3:return"[prošlu] [srijedu] [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:a,m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},609:function(e,a,t){!function(e){"use strict"; +function a(e,a,t){var s=e+" ";switch(t){case"ss":return s+=1===e?"sekunda":2===e||3===e||4===e?"sekunde":"sekundi";case"m":return a?"jedna minuta":"jedne minute";case"mm":return s+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return a?"jedan sat":"jednog sata";case"hh":return s+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return s+=1===e?"dan":"dana";case"MM":return s+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return s+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}e.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"Do MMMM YYYY",LLL:"Do MMMM YYYY H:mm",LLLL:"dddd, Do MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:return"[prošlu] [nedjelju] [u] LT";case 3:return"[prošlu] [srijedu] [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:a,m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},609(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ");function t(e,a,t,s){var n=e;switch(t){case"s":return s||a?"néhány másodperc":"néhány másodperce";case"ss":return n+(s||a)?" másodperc":" másodperce";case"m":return"egy"+(s||a?" perc":" perce");case"mm":return n+(s||a?" perc":" perce");case"h":return"egy"+(s||a?" óra":" órája");case"hh":return n+(s||a?" óra":" órája");case"d":return"egy"+(s||a?" nap":" napja");case"dd":return n+(s||a?" nap":" napja");case"M":return"egy"+(s||a?" hónap":" hónapja");case"MM":return n+(s||a?" hónap":" hónapja");case"y":return"egy"+(s||a?" év":" éve");case"yy":return n+(s||a?" év":" éve")}return""}function s(e){return(e?"":"[múlt] ")+"["+a[this.day()]+"] LT[-kor]"}e.defineLocale("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan._feb._márc._ápr._máj._jún._júl._aug._szept._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(e){return"u"===e.charAt(1).toLowerCase()},meridiem:function(e,a,t){return e<12?!0===t?"de":"DE":!0===t?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return s.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return s.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:t,ss:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7160:function(e,a,t){!function(e){"use strict"; +var a="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ");function t(e,a,t,s){var n=e;switch(t){case"s":return s||a?"néhány másodperc":"néhány másodperce";case"ss":return n+(s||a)?" másodperc":" másodperce";case"m":return"egy"+(s||a?" perc":" perce");case"mm":return n+(s||a?" perc":" perce");case"h":return"egy"+(s||a?" óra":" órája");case"hh":return n+(s||a?" óra":" órája");case"d":return"egy"+(s||a?" nap":" napja");case"dd":return n+(s||a?" nap":" napja");case"M":return"egy"+(s||a?" hónap":" hónapja");case"MM":return n+(s||a?" hónap":" hónapja");case"y":return"egy"+(s||a?" év":" éve");case"yy":return n+(s||a?" év":" éve")}return""}function s(e){return(e?"":"[múlt] ")+"["+a[this.day()]+"] LT[-kor]"}e.defineLocale("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan._feb._márc._ápr._máj._jún._júl._aug._szept._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(e){return"u"===e.charAt(1).toLowerCase()},meridiem:function(e,a,t){return e<12?!0===t?"de":"DE":!0===t?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return s.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return s.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:t,ss:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7160(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("hy-am",{months:{format:"հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի".split("_"),standalone:"հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր".split("_")},monthsShort:"հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ".split("_"),weekdays:"կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ".split("_"),weekdaysShort:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),weekdaysMin:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY թ.",LLL:"D MMMM YYYY թ., HH:mm",LLLL:"dddd, D MMMM YYYY թ., HH:mm"},calendar:{sameDay:"[այսօր] LT",nextDay:"[վաղը] LT",lastDay:"[երեկ] LT",nextWeek:function(){return"dddd [օրը ժամը] LT"},lastWeek:function(){return"[անցած] dddd [օրը ժամը] LT"},sameElse:"L"},relativeTime:{future:"%s հետո",past:"%s առաջ",s:"մի քանի վայրկյան",ss:"%d վայրկյան",m:"րոպե",mm:"%d րոպե",h:"ժամ",hh:"%d ժամ",d:"օր",dd:"%d օր",M:"ամիս",MM:"%d ամիս",y:"տարի",yy:"%d տարի"},meridiemParse:/գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,isPM:function(e){return/^(ցերեկվա|երեկոյան)$/.test(e)},meridiem:function(e){return e<4?"գիշերվա":e<12?"առավոտվա":e<17?"ցերեկվա":"երեկոյան"},dayOfMonthOrdinalParse:/\d{1,2}|\d{1,2}-(ին|րդ)/,ordinal:function(e,a){switch(a){case"DDD":case"w":case"W":case"DDDo":return 1===e?e+"-ին":e+"-րդ";default:return e}},week:{dow:1,doy:7}})}(t(5093))},4063:function(e,a,t){!function(e){"use strict"; +e.defineLocale("hy-am",{months:{format:"հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի".split("_"),standalone:"հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր".split("_")},monthsShort:"հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ".split("_"),weekdays:"կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ".split("_"),weekdaysShort:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),weekdaysMin:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY թ.",LLL:"D MMMM YYYY թ., HH:mm",LLLL:"dddd, D MMMM YYYY թ., HH:mm"},calendar:{sameDay:"[այսօր] LT",nextDay:"[վաղը] LT",lastDay:"[երեկ] LT",nextWeek:function(){return"dddd [օրը ժամը] LT"},lastWeek:function(){return"[անցած] dddd [օրը ժամը] LT"},sameElse:"L"},relativeTime:{future:"%s հետո",past:"%s առաջ",s:"մի քանի վայրկյան",ss:"%d վայրկյան",m:"րոպե",mm:"%d րոպե",h:"ժամ",hh:"%d ժամ",d:"օր",dd:"%d օր",M:"ամիս",MM:"%d ամիս",y:"տարի",yy:"%d տարի"},meridiemParse:/գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,isPM:function(e){return/^(ցերեկվա|երեկոյան)$/.test(e)},meridiem:function(e){return e<4?"գիշերվա":e<12?"առավոտվա":e<17?"ցերեկվա":"երեկոյան"},dayOfMonthOrdinalParse:/\d{1,2}|\d{1,2}-(ին|րդ)/,ordinal:function(e,a){switch(a){case"DDD":case"w":case"W":case"DDDo":return 1===e?e+"-ին":e+"-րդ";default:return e}},week:{dow:1,doy:7}})}(t(5093))},4063(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Agt_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"siang"===a?e>=11?e:e+12:"sore"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"siang":e<19?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",ss:"%d detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:0,doy:6}})}(t(5093))},9374:function(e,a,t){!function(e){"use strict"; +e.defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Agt_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"siang"===a?e>=11?e:e+12:"sore"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"siang":e<19?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",ss:"%d detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:0,doy:6}})}(t(5093))},9374(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e){return e%100==11||e%10!=1}function t(e,t,s,n){var r=e+" ";switch(s){case"s":return t||n?"nokkrar sekúndur":"nokkrum sekúndum";case"ss":return a(e)?r+(t||n?"sekúndur":"sekúndum"):r+"sekúnda";case"m":return t?"mínúta":"mínútu";case"mm":return a(e)?r+(t||n?"mínútur":"mínútum"):t?r+"mínúta":r+"mínútu";case"hh":return a(e)?r+(t||n?"klukkustundir":"klukkustundum"):r+"klukkustund";case"d":return t?"dagur":n?"dag":"degi";case"dd":return a(e)?t?r+"dagar":r+(n?"daga":"dögum"):t?r+"dagur":r+(n?"dag":"degi");case"M":return t?"mánuður":n?"mánuð":"mánuði";case"MM":return a(e)?t?r+"mánuðir":r+(n?"mánuði":"mánuðum"):t?r+"mánuður":r+(n?"mánuð":"mánuði");case"y":return t||n?"ár":"ári";case"yy":return a(e)?r+(t||n?"ár":"árum"):r+(t||n?"ár":"ári")}}e.defineLocale("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:t,ss:t,m:t,mm:t,h:"klukkustund",hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},1827:function(e,a,t){!function(e){"use strict"; +function a(e){return e%100==11||e%10!=1}function t(e,t,s,n){var r=e+" ";switch(s){case"s":return t||n?"nokkrar sekúndur":"nokkrum sekúndum";case"ss":return a(e)?r+(t||n?"sekúndur":"sekúndum"):r+"sekúnda";case"m":return t?"mínúta":"mínútu";case"mm":return a(e)?r+(t||n?"mínútur":"mínútum"):t?r+"mínúta":r+"mínútu";case"hh":return a(e)?r+(t||n?"klukkustundir":"klukkustundum"):r+"klukkustund";case"d":return t?"dagur":n?"dag":"degi";case"dd":return a(e)?t?r+"dagar":r+(n?"daga":"dögum"):t?r+"dagur":r+(n?"dag":"degi");case"M":return t?"mánuður":n?"mánuð":"mánuði";case"MM":return a(e)?t?r+"mánuðir":r+(n?"mánuði":"mánuðum"):t?r+"mánuður":r+(n?"mánuð":"mánuði");case"y":return t||n?"ár":"ári";case"yy":return a(e)?r+(t||n?"ár":"árum"):r+(t||n?"ár":"ári")}}e.defineLocale("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:t,ss:t,m:t,mm:t,h:"klukkustund",hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},1827(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("it-ch",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){return 0===this.day()?"[la scorsa] dddd [alle] LT":"[lo scorso] dddd [alle] LT"},sameElse:"L"},relativeTime:{future:function(e){return(/^[0-9].+$/.test(e)?"tra":"in")+" "+e},past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},8383:function(e,a,t){!function(e){"use strict"; +e.defineLocale("it-ch",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){return 0===this.day()?"[la scorsa] dddd [alle] LT":"[lo scorso] dddd [alle] LT"},sameElse:"L"},relativeTime:{future:function(e){return(/^[0-9].+$/.test(e)?"tra":"in")+" "+e},past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},8383(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:function(){return"[Oggi a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextDay:function(){return"[Domani a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextWeek:function(){return"dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastDay:function(){return"[Ieri a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastWeek:function(){return 0===this.day()?"[La scorsa] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT":"[Lo scorso] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},sameElse:"L"},relativeTime:{future:"tra %s",past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",w:"una settimana",ww:"%d settimane",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},3827:function(e,a,t){!function(e){"use strict"; +e.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:function(){return"[Oggi a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextDay:function(){return"[Domani a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextWeek:function(){return"dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastDay:function(){return"[Ieri a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastWeek:function(){return 0===this.day()?"[La scorsa] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT":"[Lo scorso] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},sameElse:"L"},relativeTime:{future:"tra %s",past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",w:"una settimana",ww:"%d settimane",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},3827(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ja",{eras:[{since:"2019-05-01",offset:1,name:"令和",narrow:"㋿",abbr:"R"},{since:"1989-01-08",until:"2019-04-30",offset:1,name:"平成",narrow:"㍻",abbr:"H"},{since:"1926-12-25",until:"1989-01-07",offset:1,name:"昭和",narrow:"㍼",abbr:"S"},{since:"1912-07-30",until:"1926-12-24",offset:1,name:"大正",narrow:"㍽",abbr:"T"},{since:"1873-01-01",until:"1912-07-29",offset:6,name:"明治",narrow:"㍾",abbr:"M"},{since:"0001-01-01",until:"1873-12-31",offset:1,name:"西暦",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"紀元前",narrow:"BC",abbr:"BC"}],eraYearOrdinalRegex:/(元|\d+)年/,eraYearOrdinalParse:function(e,a){return"元"===a[1]?1:parseInt(a[1]||e,10)},months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日(ddd) HH:mm"},meridiemParse:/午前|午後/i,isPM:function(e){return"午後"===e},meridiem:function(e,a,t){return e<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:function(e){return e.week()!==this.week()?"[来週]dddd LT":"dddd LT"},lastDay:"[昨日] LT",lastWeek:function(e){return this.week()!==e.week()?"[先週]dddd LT":"dddd LT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}日/,ordinal:function(e,a){switch(a){case"y":return 1===e?"元年":e+"年";case"d":case"D":case"DDD":return e+"日";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",ss:"%d秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}})}(t(5093))},9722:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ja",{eras:[{since:"2019-05-01",offset:1,name:"令和",narrow:"㋿",abbr:"R"},{since:"1989-01-08",until:"2019-04-30",offset:1,name:"平成",narrow:"㍻",abbr:"H"},{since:"1926-12-25",until:"1989-01-07",offset:1,name:"昭和",narrow:"㍼",abbr:"S"},{since:"1912-07-30",until:"1926-12-24",offset:1,name:"大正",narrow:"㍽",abbr:"T"},{since:"1873-01-01",until:"1912-07-29",offset:6,name:"明治",narrow:"㍾",abbr:"M"},{since:"0001-01-01",until:"1873-12-31",offset:1,name:"西暦",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"紀元前",narrow:"BC",abbr:"BC"}],eraYearOrdinalRegex:/(元|\d+)年/,eraYearOrdinalParse:function(e,a){return"元"===a[1]?1:parseInt(a[1]||e,10)},months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日(ddd) HH:mm"},meridiemParse:/午前|午後/i,isPM:function(e){return"午後"===e},meridiem:function(e,a,t){return e<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:function(e){return e.week()!==this.week()?"[来週]dddd LT":"dddd LT"},lastDay:"[昨日] LT",lastWeek:function(e){return this.week()!==e.week()?"[先週]dddd LT":"dddd LT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}日/,ordinal:function(e,a){switch(a){case"y":return 1===e?"元年":e+"年";case"d":case"D":case"DDD":return e+"日";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",ss:"%d秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}})}(t(5093))},9722(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("jv",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des".split("_"),weekdays:"Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu".split("_"),weekdaysShort:"Min_Sen_Sel_Reb_Kem_Jem_Sep".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sp".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/enjing|siyang|sonten|ndalu/,meridiemHour:function(e,a){return 12===e&&(e=0),"enjing"===a?e:"siyang"===a?e>=11?e:e+12:"sonten"===a||"ndalu"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"enjing":e<15?"siyang":e<19?"sonten":"ndalu"},calendar:{sameDay:"[Dinten puniko pukul] LT",nextDay:"[Mbenjang pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kala wingi pukul] LT",lastWeek:"dddd [kepengker pukul] LT",sameElse:"L"},relativeTime:{future:"wonten ing %s",past:"%s ingkang kepengker",s:"sawetawis detik",ss:"%d detik",m:"setunggal menit",mm:"%d menit",h:"setunggal jam",hh:"%d jam",d:"sedinten",dd:"%d dinten",M:"sewulan",MM:"%d wulan",y:"setaun",yy:"%d taun"},week:{dow:1,doy:7}})}(t(5093))},1794:function(e,a,t){!function(e){"use strict"; +e.defineLocale("jv",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des".split("_"),weekdays:"Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu".split("_"),weekdaysShort:"Min_Sen_Sel_Reb_Kem_Jem_Sep".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sp".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/enjing|siyang|sonten|ndalu/,meridiemHour:function(e,a){return 12===e&&(e=0),"enjing"===a?e:"siyang"===a?e>=11?e:e+12:"sonten"===a||"ndalu"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"enjing":e<15?"siyang":e<19?"sonten":"ndalu"},calendar:{sameDay:"[Dinten puniko pukul] LT",nextDay:"[Mbenjang pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kala wingi pukul] LT",lastWeek:"dddd [kepengker pukul] LT",sameElse:"L"},relativeTime:{future:"wonten ing %s",past:"%s ingkang kepengker",s:"sawetawis detik",ss:"%d detik",m:"setunggal menit",mm:"%d menit",h:"setunggal jam",hh:"%d jam",d:"sedinten",dd:"%d dinten",M:"sewulan",MM:"%d wulan",y:"setaun",yy:"%d taun"},week:{dow:1,doy:7}})}(t(5093))},1794(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ka",{months:"იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი".split("_"),monthsShort:"იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),weekdays:{standalone:"კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი".split("_"),format:"კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს".split("_"),isFormat:/(წინა|შემდეგ)/},weekdaysShort:"კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),weekdaysMin:"კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[დღეს] LT[-ზე]",nextDay:"[ხვალ] LT[-ზე]",lastDay:"[გუშინ] LT[-ზე]",nextWeek:"[შემდეგ] dddd LT[-ზე]",lastWeek:"[წინა] dddd LT-ზე",sameElse:"L"},relativeTime:{future:function(e){return e.replace(/(წამ|წუთ|საათ|წელ|დღ|თვ)(ი|ე)/,(function(e,a,t){return"ი"===t?a+"ში":a+t+"ში"}))},past:function(e){return/(წამი|წუთი|საათი|დღე|თვე)/.test(e)?e.replace(/(ი|ე)$/,"ის წინ"):/წელი/.test(e)?e.replace(/წელი$/,"წლის წინ"):e},s:"რამდენიმე წამი",ss:"%d წამი",m:"წუთი",mm:"%d წუთი",h:"საათი",hh:"%d საათი",d:"დღე",dd:"%d დღე",M:"თვე",MM:"%d თვე",y:"წელი",yy:"%d წელი"},dayOfMonthOrdinalParse:/0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,ordinal:function(e){return 0===e?e:1===e?e+"-ლი":e<20||e<=100&&e%20==0||e%100==0?"მე-"+e:e+"-ე"},week:{dow:1,doy:7}})}(t(5093))},7088:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ka",{months:"იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი".split("_"),monthsShort:"იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),weekdays:{standalone:"კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი".split("_"),format:"კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს".split("_"),isFormat:/(წინა|შემდეგ)/},weekdaysShort:"კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),weekdaysMin:"კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[დღეს] LT[-ზე]",nextDay:"[ხვალ] LT[-ზე]",lastDay:"[გუშინ] LT[-ზე]",nextWeek:"[შემდეგ] dddd LT[-ზე]",lastWeek:"[წინა] dddd LT-ზე",sameElse:"L"},relativeTime:{future:function(e){return e.replace(/(წამ|წუთ|საათ|წელ|დღ|თვ)(ი|ე)/,(function(e,a,t){return"ი"===t?a+"ში":a+t+"ში"}))},past:function(e){return/(წამი|წუთი|საათი|დღე|თვე)/.test(e)?e.replace(/(ი|ე)$/,"ის წინ"):/წელი/.test(e)?e.replace(/წელი$/,"წლის წინ"):e},s:"რამდენიმე წამი",ss:"%d წამი",m:"წუთი",mm:"%d წუთი",h:"საათი",hh:"%d საათი",d:"დღე",dd:"%d დღე",M:"თვე",MM:"%d თვე",y:"წელი",yy:"%d წელი"},dayOfMonthOrdinalParse:/0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,ordinal:function(e){return 0===e?e:1===e?e+"-ლი":e<20||e<=100&&e%20==0||e%100==0?"მე-"+e:e+"-ე"},week:{dow:1,doy:7}})}(t(5093))},7088(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={0:"-ші",1:"-ші",2:"-ші",3:"-ші",4:"-ші",5:"-ші",6:"-шы",7:"-ші",8:"-ші",9:"-шы",10:"-шы",20:"-шы",30:"-шы",40:"-шы",50:"-ші",60:"-шы",70:"-ші",80:"-ші",90:"-шы",100:"-ші"};e.defineLocale("kk",{months:"қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан".split("_"),monthsShort:"қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел".split("_"),weekdays:"жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі".split("_"),weekdaysShort:"жек_дүй_сей_сәр_бей_жұм_сен".split("_"),weekdaysMin:"жк_дй_сй_ср_бй_жм_сн".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгін сағат] LT",nextDay:"[Ертең сағат] LT",nextWeek:"dddd [сағат] LT",lastDay:"[Кеше сағат] LT",lastWeek:"[Өткен аптаның] dddd [сағат] LT",sameElse:"L"},relativeTime:{future:"%s ішінде",past:"%s бұрын",s:"бірнеше секунд",ss:"%d секунд",m:"бір минут",mm:"%d минут",h:"бір сағат",hh:"%d сағат",d:"бір күн",dd:"%d күн",M:"бір ай",MM:"%d ай",y:"бір жыл",yy:"%d жыл"},dayOfMonthOrdinalParse:/\d{1,2}-(ші|шы)/,ordinal:function(e){var t=e%10,s=e>=100?100:null;return e+(a[e]||a[t]||a[s])},week:{dow:1,doy:7}})}(t(5093))},6870:function(e,a,t){!function(e){"use strict"; +var a={0:"-ші",1:"-ші",2:"-ші",3:"-ші",4:"-ші",5:"-ші",6:"-шы",7:"-ші",8:"-ші",9:"-шы",10:"-шы",20:"-шы",30:"-шы",40:"-шы",50:"-ші",60:"-шы",70:"-ші",80:"-ші",90:"-шы",100:"-ші"};e.defineLocale("kk",{months:"қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан".split("_"),monthsShort:"қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел".split("_"),weekdays:"жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі".split("_"),weekdaysShort:"жек_дүй_сей_сәр_бей_жұм_сен".split("_"),weekdaysMin:"жк_дй_сй_ср_бй_жм_сн".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгін сағат] LT",nextDay:"[Ертең сағат] LT",nextWeek:"dddd [сағат] LT",lastDay:"[Кеше сағат] LT",lastWeek:"[Өткен аптаның] dddd [сағат] LT",sameElse:"L"},relativeTime:{future:"%s ішінде",past:"%s бұрын",s:"бірнеше секунд",ss:"%d секунд",m:"бір минут",mm:"%d минут",h:"бір сағат",hh:"%d сағат",d:"бір күн",dd:"%d күн",M:"бір ай",MM:"%d ай",y:"бір жыл",yy:"%d жыл"},dayOfMonthOrdinalParse:/\d{1,2}-(ші|шы)/,ordinal:function(e){var t=e%10,s=e>=100?100:null;return e+(a[e]||a[t]||a[s])},week:{dow:1,doy:7}})}(t(5093))},6870(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"១",2:"២",3:"៣",4:"៤",5:"៥",6:"៦",7:"៧",8:"៨",9:"៩",0:"០"},t={"១":"1","២":"2","៣":"3","៤":"4","៥":"5","៦":"6","៧":"7","៨":"8","៩":"9","០":"0"};e.defineLocale("km",{months:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),monthsShort:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),weekdays:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),weekdaysShort:"អា_ច_អ_ព_ព្រ_សុ_ស".split("_"),weekdaysMin:"អា_ច_អ_ព_ព្រ_សុ_ស".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/ព្រឹក|ល្ងាច/,isPM:function(e){return"ល្ងាច"===e},meridiem:function(e,a,t){return e<12?"ព្រឹក":"ល្ងាច"},calendar:{sameDay:"[ថ្ងៃនេះ ម៉ោង] LT",nextDay:"[ស្អែក ម៉ោង] LT",nextWeek:"dddd [ម៉ោង] LT",lastDay:"[ម្សិលមិញ ម៉ោង] LT",lastWeek:"dddd [សប្តាហ៍មុន] [ម៉ោង] LT",sameElse:"L"},relativeTime:{future:"%sទៀត",past:"%sមុន",s:"ប៉ុន្មានវិនាទី",ss:"%d វិនាទី",m:"មួយនាទី",mm:"%d នាទី",h:"មួយម៉ោង",hh:"%d ម៉ោង",d:"មួយថ្ងៃ",dd:"%d ថ្ងៃ",M:"មួយខែ",MM:"%d ខែ",y:"មួយឆ្នាំ",yy:"%d ឆ្នាំ"},dayOfMonthOrdinalParse:/ទី\d{1,2}/,ordinal:"ទី%d",preparse:function(e){return e.replace(/[១២៣៤៥៦៧៨៩០]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},week:{dow:1,doy:4}})}(t(5093))},4451:function(e,a,t){!function(e){"use strict"; +var a={1:"១",2:"២",3:"៣",4:"៤",5:"៥",6:"៦",7:"៧",8:"៨",9:"៩",0:"០"},t={"១":"1","២":"2","៣":"3","៤":"4","៥":"5","៦":"6","៧":"7","៨":"8","៩":"9","០":"0"};e.defineLocale("km",{months:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),monthsShort:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),weekdays:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),weekdaysShort:"អា_ច_អ_ព_ព្រ_សុ_ស".split("_"),weekdaysMin:"អា_ច_អ_ព_ព្រ_សុ_ស".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/ព្រឹក|ល្ងាច/,isPM:function(e){return"ល្ងាច"===e},meridiem:function(e,a,t){return e<12?"ព្រឹក":"ល្ងាច"},calendar:{sameDay:"[ថ្ងៃនេះ ម៉ោង] LT",nextDay:"[ស្អែក ម៉ោង] LT",nextWeek:"dddd [ម៉ោង] LT",lastDay:"[ម្សិលមិញ ម៉ោង] LT",lastWeek:"dddd [សប្តាហ៍មុន] [ម៉ោង] LT",sameElse:"L"},relativeTime:{future:"%sទៀត",past:"%sមុន",s:"ប៉ុន្មានវិនាទី",ss:"%d វិនាទី",m:"មួយនាទី",mm:"%d នាទី",h:"មួយម៉ោង",hh:"%d ម៉ោង",d:"មួយថ្ងៃ",dd:"%d ថ្ងៃ",M:"មួយខែ",MM:"%d ខែ",y:"មួយឆ្នាំ",yy:"%d ឆ្នាំ"},dayOfMonthOrdinalParse:/ទី\d{1,2}/,ordinal:"ទី%d",preparse:function(e){return e.replace(/[១២៣៤៥៦៧៨៩០]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},week:{dow:1,doy:4}})}(t(5093))},4451(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"೧",2:"೨",3:"೩",4:"೪",5:"೫",6:"೬",7:"೭",8:"೮",9:"೯",0:"೦"},t={"೧":"1","೨":"2","೩":"3","೪":"4","೫":"5","೬":"6","೭":"7","೮":"8","೯":"9","೦":"0"};e.defineLocale("kn",{months:"ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್".split("_"),monthsShort:"ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂ_ಅಕ್ಟೋ_ನವೆಂ_ಡಿಸೆಂ".split("_"),monthsParseExact:!0,weekdays:"ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ".split("_"),weekdaysShort:"ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ".split("_"),weekdaysMin:"ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[ಇಂದು] LT",nextDay:"[ನಾಳೆ] LT",nextWeek:"dddd, LT",lastDay:"[ನಿನ್ನೆ] LT",lastWeek:"[ಕೊನೆಯ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ನಂತರ",past:"%s ಹಿಂದೆ",s:"ಕೆಲವು ಕ್ಷಣಗಳು",ss:"%d ಸೆಕೆಂಡುಗಳು",m:"ಒಂದು ನಿಮಿಷ",mm:"%d ನಿಮಿಷ",h:"ಒಂದು ಗಂಟೆ",hh:"%d ಗಂಟೆ",d:"ಒಂದು ದಿನ",dd:"%d ದಿನ",M:"ಒಂದು ತಿಂಗಳು",MM:"%d ತಿಂಗಳು",y:"ಒಂದು ವರ್ಷ",yy:"%d ವರ್ಷ"},preparse:function(e){return e.replace(/[೧೨೩೪೫೬೭೮೯೦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,meridiemHour:function(e,a){return 12===e&&(e=0),"ರಾತ್ರಿ"===a?e<4?e:e+12:"ಬೆಳಿಗ್ಗೆ"===a?e:"ಮಧ್ಯಾಹ್ನ"===a?e>=10?e:e+12:"ಸಂಜೆ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"ರಾತ್ರಿ":e<10?"ಬೆಳಿಗ್ಗೆ":e<17?"ಮಧ್ಯಾಹ್ನ":e<20?"ಸಂಜೆ":"ರಾತ್ರಿ"},dayOfMonthOrdinalParse:/\d{1,2}(ನೇ)/,ordinal:function(e){return e+"ನೇ"},week:{dow:0,doy:6}})}(t(5093))},3164:function(e,a,t){!function(e){"use strict"; +var a={1:"೧",2:"೨",3:"೩",4:"೪",5:"೫",6:"೬",7:"೭",8:"೮",9:"೯",0:"೦"},t={"೧":"1","೨":"2","೩":"3","೪":"4","೫":"5","೬":"6","೭":"7","೮":"8","೯":"9","೦":"0"};e.defineLocale("kn",{months:"ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್".split("_"),monthsShort:"ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂ_ಅಕ್ಟೋ_ನವೆಂ_ಡಿಸೆಂ".split("_"),monthsParseExact:!0,weekdays:"ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ".split("_"),weekdaysShort:"ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ".split("_"),weekdaysMin:"ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[ಇಂದು] LT",nextDay:"[ನಾಳೆ] LT",nextWeek:"dddd, LT",lastDay:"[ನಿನ್ನೆ] LT",lastWeek:"[ಕೊನೆಯ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ನಂತರ",past:"%s ಹಿಂದೆ",s:"ಕೆಲವು ಕ್ಷಣಗಳು",ss:"%d ಸೆಕೆಂಡುಗಳು",m:"ಒಂದು ನಿಮಿಷ",mm:"%d ನಿಮಿಷ",h:"ಒಂದು ಗಂಟೆ",hh:"%d ಗಂಟೆ",d:"ಒಂದು ದಿನ",dd:"%d ದಿನ",M:"ಒಂದು ತಿಂಗಳು",MM:"%d ತಿಂಗಳು",y:"ಒಂದು ವರ್ಷ",yy:"%d ವರ್ಷ"},preparse:function(e){return e.replace(/[೧೨೩೪೫೬೭೮೯೦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,meridiemHour:function(e,a){return 12===e&&(e=0),"ರಾತ್ರಿ"===a?e<4?e:e+12:"ಬೆಳಿಗ್ಗೆ"===a?e:"ಮಧ್ಯಾಹ್ನ"===a?e>=10?e:e+12:"ಸಂಜೆ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"ರಾತ್ರಿ":e<10?"ಬೆಳಿಗ್ಗೆ":e<17?"ಮಧ್ಯಾಹ್ನ":e<20?"ಸಂಜೆ":"ರಾತ್ರಿ"},dayOfMonthOrdinalParse:/\d{1,2}(ನೇ)/,ordinal:function(e){return e+"ನೇ"},week:{dow:0,doy:6}})}(t(5093))},3164(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h:mm",LLLL:"YYYY년 MMMM D일 dddd A h:mm",l:"YYYY.MM.DD.",ll:"YYYY년 MMMM D일",lll:"YYYY년 MMMM D일 A h:mm",llll:"YYYY년 MMMM D일 dddd A h:mm"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"1분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},dayOfMonthOrdinalParse:/\d{1,2}(일|월|주)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"일";case"M":return e+"월";case"w":case"W":return e+"주";default:return e}},meridiemParse:/오전|오후/,isPM:function(e){return"오후"===e},meridiem:function(e,a,t){return e<12?"오전":"오후"}})}(t(5093))},6181:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h:mm",LLLL:"YYYY년 MMMM D일 dddd A h:mm",l:"YYYY.MM.DD.",ll:"YYYY년 MMMM D일",lll:"YYYY년 MMMM D일 A h:mm",llll:"YYYY년 MMMM D일 dddd A h:mm"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"1분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},dayOfMonthOrdinalParse:/\d{1,2}(일|월|주)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"일";case"M":return e+"월";case"w":case"W":return e+"주";default:return e}},meridiemParse:/오전|오후/,isPM:function(e){return"오후"===e},meridiem:function(e,a,t){return e<12?"오전":"오후"}})}(t(5093))},6181(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={s:["çend sanîye","çend sanîyeyan"],ss:[e+" sanîye",e+" sanîyeyan"],m:["deqîqeyek","deqîqeyekê"],mm:[e+" deqîqe",e+" deqîqeyan"],h:["saetek","saetekê"],hh:[e+" saet",e+" saetan"],d:["rojek","rojekê"],dd:[e+" roj",e+" rojan"],w:["hefteyek","hefteyekê"],ww:[e+" hefte",e+" hefteyan"],M:["mehek","mehekê"],MM:[e+" meh",e+" mehan"],y:["salek","salekê"],yy:[e+" sal",e+" salan"]};return a?n[t][0]:n[t][1]}function t(e){var a=(e=""+e).substring(e.length-1),t=e.length>1?e.substring(e.length-2):"";return 12==t||13==t||"2"!=a&&"3"!=a&&"50"!=t&&"70"!=a&&"80"!=a?"ê":"yê"}e.defineLocale("ku-kmr",{months:"Rêbendan_Sibat_Adar_Nîsan_Gulan_Hezîran_Tîrmeh_Tebax_Îlon_Cotmeh_Mijdar_Berfanbar".split("_"),monthsShort:"Rêb_Sib_Ada_Nîs_Gul_Hez_Tîr_Teb_Îlo_Cot_Mij_Ber".split("_"),monthsParseExact:!0,weekdays:"Yekşem_Duşem_Sêşem_Çarşem_Pêncşem_În_Şemî".split("_"),weekdaysShort:"Yek_Du_Sê_Çar_Pên_În_Şem".split("_"),weekdaysMin:"Ye_Du_Sê_Ça_Pê_În_Şe".split("_"),meridiem:function(e,a,t){return e<12?t?"bn":"BN":t?"pn":"PN"},meridiemParse:/bn|BN|pn|PN/,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"Do MMMM[a] YYYY[an]",LLL:"Do MMMM[a] YYYY[an] HH:mm",LLLL:"dddd, Do MMMM[a] YYYY[an] HH:mm",ll:"Do MMM[.] YYYY[an]",lll:"Do MMM[.] YYYY[an] HH:mm",llll:"ddd[.], Do MMM[.] YYYY[an] HH:mm"},calendar:{sameDay:"[Îro di saet] LT [de]",nextDay:"[Sibê di saet] LT [de]",nextWeek:"dddd [di saet] LT [de]",lastDay:"[Duh di saet] LT [de]",lastWeek:"dddd[a borî di saet] LT [de]",sameElse:"L"},relativeTime:{future:"di %s de",past:"berî %s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,w:a,ww:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}(?:yê|ê|\.)/,ordinal:function(e,a){var s=a.toLowerCase();return s.includes("w")||s.includes("m")?e+".":e+t(e)},week:{dow:1,doy:4}})}(t(5093))},8174:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={s:["çend sanîye","çend sanîyeyan"],ss:[e+" sanîye",e+" sanîyeyan"],m:["deqîqeyek","deqîqeyekê"],mm:[e+" deqîqe",e+" deqîqeyan"],h:["saetek","saetekê"],hh:[e+" saet",e+" saetan"],d:["rojek","rojekê"],dd:[e+" roj",e+" rojan"],w:["hefteyek","hefteyekê"],ww:[e+" hefte",e+" hefteyan"],M:["mehek","mehekê"],MM:[e+" meh",e+" mehan"],y:["salek","salekê"],yy:[e+" sal",e+" salan"]};return a?n[t][0]:n[t][1]}function t(e){var a=(e=""+e).substring(e.length-1),t=e.length>1?e.substring(e.length-2):"";return 12==t||13==t||"2"!=a&&"3"!=a&&"50"!=t&&"70"!=a&&"80"!=a?"ê":"yê"}e.defineLocale("ku-kmr",{months:"Rêbendan_Sibat_Adar_Nîsan_Gulan_Hezîran_Tîrmeh_Tebax_Îlon_Cotmeh_Mijdar_Berfanbar".split("_"),monthsShort:"Rêb_Sib_Ada_Nîs_Gul_Hez_Tîr_Teb_Îlo_Cot_Mij_Ber".split("_"),monthsParseExact:!0,weekdays:"Yekşem_Duşem_Sêşem_Çarşem_Pêncşem_În_Şemî".split("_"),weekdaysShort:"Yek_Du_Sê_Çar_Pên_În_Şem".split("_"),weekdaysMin:"Ye_Du_Sê_Ça_Pê_În_Şe".split("_"),meridiem:function(e,a,t){return e<12?t?"bn":"BN":t?"pn":"PN"},meridiemParse:/bn|BN|pn|PN/,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"Do MMMM[a] YYYY[an]",LLL:"Do MMMM[a] YYYY[an] HH:mm",LLLL:"dddd, Do MMMM[a] YYYY[an] HH:mm",ll:"Do MMM[.] YYYY[an]",lll:"Do MMM[.] YYYY[an] HH:mm",llll:"ddd[.], Do MMM[.] YYYY[an] HH:mm"},calendar:{sameDay:"[Îro di saet] LT [de]",nextDay:"[Sibê di saet] LT [de]",nextWeek:"dddd [di saet] LT [de]",lastDay:"[Duh di saet] LT [de]",lastWeek:"dddd[a borî di saet] LT [de]",sameElse:"L"},relativeTime:{future:"di %s de",past:"berî %s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,w:a,ww:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}(?:yê|ê|\.)/,ordinal:function(e,a){var s=a.toLowerCase();return s.includes("w")||s.includes("m")?e+".":e+t(e)},week:{dow:1,doy:4}})}(t(5093))},8174(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},s=["کانونی دووەم","شوبات","ئازار","نیسان","ئایار","حوزەیران","تەمموز","ئاب","ئەیلوول","تشرینی یەكەم","تشرینی دووەم","كانونی یەکەم"];e.defineLocale("ku",{months:s,monthsShort:s,weekdays:"یه‌كشه‌ممه‌_دووشه‌ممه‌_سێشه‌ممه‌_چوارشه‌ممه‌_پێنجشه‌ممه‌_هه‌ینی_شه‌ممه‌".split("_"),weekdaysShort:"یه‌كشه‌م_دووشه‌م_سێشه‌م_چوارشه‌م_پێنجشه‌م_هه‌ینی_شه‌ممه‌".split("_"),weekdaysMin:"ی_د_س_چ_پ_ه_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/ئێواره‌|به‌یانی/,isPM:function(e){return/ئێواره‌/.test(e)},meridiem:function(e,a,t){return e<12?"به‌یانی":"ئێواره‌"},calendar:{sameDay:"[ئه‌مرۆ كاتژمێر] LT",nextDay:"[به‌یانی كاتژمێر] LT",nextWeek:"dddd [كاتژمێر] LT",lastDay:"[دوێنێ كاتژمێر] LT",lastWeek:"dddd [كاتژمێر] LT",sameElse:"L"},relativeTime:{future:"له‌ %s",past:"%s",s:"چه‌ند چركه‌یه‌ك",ss:"چركه‌ %d",m:"یه‌ك خوله‌ك",mm:"%d خوله‌ك",h:"یه‌ك كاتژمێر",hh:"%d كاتژمێر",d:"یه‌ك ڕۆژ",dd:"%d ڕۆژ",M:"یه‌ك مانگ",MM:"%d مانگ",y:"یه‌ك ساڵ",yy:"%d ساڵ"},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:6,doy:12}})}(t(5093))},8474:function(e,a,t){!function(e){"use strict"; +var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},s=["کانونی دووەم","شوبات","ئازار","نیسان","ئایار","حوزەیران","تەمموز","ئاب","ئەیلوول","تشرینی یەكەم","تشرینی دووەم","كانونی یەکەم"];e.defineLocale("ku",{months:s,monthsShort:s,weekdays:"یه‌كشه‌ممه‌_دووشه‌ممه‌_سێشه‌ممه‌_چوارشه‌ممه‌_پێنجشه‌ممه‌_هه‌ینی_شه‌ممه‌".split("_"),weekdaysShort:"یه‌كشه‌م_دووشه‌م_سێشه‌م_چوارشه‌م_پێنجشه‌م_هه‌ینی_شه‌ممه‌".split("_"),weekdaysMin:"ی_د_س_چ_پ_ه_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/ئێواره‌|به‌یانی/,isPM:function(e){return/ئێواره‌/.test(e)},meridiem:function(e,a,t){return e<12?"به‌یانی":"ئێواره‌"},calendar:{sameDay:"[ئه‌مرۆ كاتژمێر] LT",nextDay:"[به‌یانی كاتژمێر] LT",nextWeek:"dddd [كاتژمێر] LT",lastDay:"[دوێنێ كاتژمێر] LT",lastWeek:"dddd [كاتژمێر] LT",sameElse:"L"},relativeTime:{future:"له‌ %s",past:"%s",s:"چه‌ند چركه‌یه‌ك",ss:"چركه‌ %d",m:"یه‌ك خوله‌ك",mm:"%d خوله‌ك",h:"یه‌ك كاتژمێر",hh:"%d كاتژمێر",d:"یه‌ك ڕۆژ",dd:"%d ڕۆژ",M:"یه‌ك مانگ",MM:"%d مانگ",y:"یه‌ك ساڵ",yy:"%d ساڵ"},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(e){return t[e]})).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]})).replace(/,/g,"،")},week:{dow:6,doy:12}})}(t(5093))},8474(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={0:"-чү",1:"-чи",2:"-чи",3:"-чү",4:"-чү",5:"-чи",6:"-чы",7:"-чи",8:"-чи",9:"-чу",10:"-чу",20:"-чы",30:"-чу",40:"-чы",50:"-чү",60:"-чы",70:"-чи",80:"-чи",90:"-чу",100:"-чү"};e.defineLocale("ky",{months:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),monthsShort:"янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),weekdays:"Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби".split("_"),weekdaysShort:"Жек_Дүй_Шей_Шар_Бей_Жум_Ише".split("_"),weekdaysMin:"Жк_Дй_Шй_Шр_Бй_Жм_Иш".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгүн саат] LT",nextDay:"[Эртең саат] LT",nextWeek:"dddd [саат] LT",lastDay:"[Кечээ саат] LT",lastWeek:"[Өткөн аптанын] dddd [күнү] [саат] LT",sameElse:"L"},relativeTime:{future:"%s ичинде",past:"%s мурун",s:"бирнече секунд",ss:"%d секунд",m:"бир мүнөт",mm:"%d мүнөт",h:"бир саат",hh:"%d саат",d:"бир күн",dd:"%d күн",M:"бир ай",MM:"%d ай",y:"бир жыл",yy:"%d жыл"},dayOfMonthOrdinalParse:/\d{1,2}-(чи|чы|чү|чу)/,ordinal:function(e){var t=e%10,s=e>=100?100:null;return e+(a[e]||a[t]||a[s])},week:{dow:1,doy:7}})}(t(5093))},9680:function(e,a,t){!function(e){"use strict"; +var a={0:"-чү",1:"-чи",2:"-чи",3:"-чү",4:"-чү",5:"-чи",6:"-чы",7:"-чи",8:"-чи",9:"-чу",10:"-чу",20:"-чы",30:"-чу",40:"-чы",50:"-чү",60:"-чы",70:"-чи",80:"-чи",90:"-чу",100:"-чү"};e.defineLocale("ky",{months:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),monthsShort:"янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),weekdays:"Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби".split("_"),weekdaysShort:"Жек_Дүй_Шей_Шар_Бей_Жум_Ише".split("_"),weekdaysMin:"Жк_Дй_Шй_Шр_Бй_Жм_Иш".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгүн саат] LT",nextDay:"[Эртең саат] LT",nextWeek:"dddd [саат] LT",lastDay:"[Кечээ саат] LT",lastWeek:"[Өткөн аптанын] dddd [күнү] [саат] LT",sameElse:"L"},relativeTime:{future:"%s ичинде",past:"%s мурун",s:"бирнече секунд",ss:"%d секунд",m:"бир мүнөт",mm:"%d мүнөт",h:"бир саат",hh:"%d саат",d:"бир күн",dd:"%d күн",M:"бир ай",MM:"%d ай",y:"бир жыл",yy:"%d жыл"},dayOfMonthOrdinalParse:/\d{1,2}-(чи|чы|чү|чу)/,ordinal:function(e){var t=e%10,s=e>=100?100:null;return e+(a[e]||a[t]||a[s])},week:{dow:1,doy:7}})}(t(5093))},9680(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return a?n[t][0]:n[t][1]}function t(e){return n(e.substr(0,e.indexOf(" ")))?"a "+e:"an "+e}function s(e){return n(e.substr(0,e.indexOf(" ")))?"viru "+e:"virun "+e}function n(e){if(e=parseInt(e,10),isNaN(e))return!1;if(e<0)return!0;if(e<10)return 4<=e&&e<=7;if(e<100){var a=e%10;return n(0===a?e/10:a)}if(e<1e4){for(;e>=10;)e/=10;return n(e)}return n(e/=1e3)}e.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:t,past:s,s:"e puer Sekonnen",ss:"%d Sekonnen",m:a,mm:"%d Minutten",h:a,hh:"%d Stonnen",d:a,dd:"%d Deeg",M:a,MM:"%d Méint",y:a,yy:"%d Joer"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},5867:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return a?n[t][0]:n[t][1]}function t(e){return n(e.substr(0,e.indexOf(" ")))?"a "+e:"an "+e}function s(e){return n(e.substr(0,e.indexOf(" ")))?"viru "+e:"virun "+e}function n(e){if(e=parseInt(e,10),isNaN(e))return!1;if(e<0)return!0;if(e<10)return 4<=e&&e<=7;if(e<100){var a=e%10;return n(0===a?e/10:a)}if(e<1e4){for(;e>=10;)e/=10;return n(e)}return n(e/=1e3)}e.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:t,past:s,s:"e puer Sekonnen",ss:"%d Sekonnen",m:a,mm:"%d Minutten",h:a,hh:"%d Stonnen",d:a,dd:"%d Deeg",M:a,MM:"%d Méint",y:a,yy:"%d Joer"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},5867(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("lo",{months:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),monthsShort:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),weekdays:"ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysShort:"ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysMin:"ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"ວັນdddd D MMMM YYYY HH:mm"},meridiemParse:/ຕອນເຊົ້າ|ຕອນແລງ/,isPM:function(e){return"ຕອນແລງ"===e},meridiem:function(e,a,t){return e<12?"ຕອນເຊົ້າ":"ຕອນແລງ"},calendar:{sameDay:"[ມື້ນີ້ເວລາ] LT",nextDay:"[ມື້ອື່ນເວລາ] LT",nextWeek:"[ວັນ]dddd[ໜ້າເວລາ] LT",lastDay:"[ມື້ວານນີ້ເວລາ] LT",lastWeek:"[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT",sameElse:"L"},relativeTime:{future:"ອີກ %s",past:"%sຜ່ານມາ",s:"ບໍ່ເທົ່າໃດວິນາທີ",ss:"%d ວິນາທີ",m:"1 ນາທີ",mm:"%d ນາທີ",h:"1 ຊົ່ວໂມງ",hh:"%d ຊົ່ວໂມງ",d:"1 ມື້",dd:"%d ມື້",M:"1 ເດືອນ",MM:"%d ເດືອນ",y:"1 ປີ",yy:"%d ປີ"},dayOfMonthOrdinalParse:/(ທີ່)\d{1,2}/,ordinal:function(e){return"ທີ່"+e}})}(t(5093))},5766:function(e,a,t){!function(e){"use strict"; +e.defineLocale("lo",{months:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),monthsShort:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),weekdays:"ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysShort:"ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysMin:"ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"ວັນdddd D MMMM YYYY HH:mm"},meridiemParse:/ຕອນເຊົ້າ|ຕອນແລງ/,isPM:function(e){return"ຕອນແລງ"===e},meridiem:function(e,a,t){return e<12?"ຕອນເຊົ້າ":"ຕອນແລງ"},calendar:{sameDay:"[ມື້ນີ້ເວລາ] LT",nextDay:"[ມື້ອື່ນເວລາ] LT",nextWeek:"[ວັນ]dddd[ໜ້າເວລາ] LT",lastDay:"[ມື້ວານນີ້ເວລາ] LT",lastWeek:"[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT",sameElse:"L"},relativeTime:{future:"ອີກ %s",past:"%sຜ່ານມາ",s:"ບໍ່ເທົ່າໃດວິນາທີ",ss:"%d ວິນາທີ",m:"1 ນາທີ",mm:"%d ນາທີ",h:"1 ຊົ່ວໂມງ",hh:"%d ຊົ່ວໂມງ",d:"1 ມື້",dd:"%d ມື້",M:"1 ເດືອນ",MM:"%d ເດືອນ",y:"1 ປີ",yy:"%d ປີ"},dayOfMonthOrdinalParse:/(ທີ່)\d{1,2}/,ordinal:function(e){return"ທີ່"+e}})}(t(5093))},5766(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={ss:"sekundė_sekundžių_sekundes",m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"};function t(e,a,t,s){return a?"kelios sekundės":s?"kelių sekundžių":"kelias sekundes"}function s(e,a,t,s){return a?r(t)[0]:s?r(t)[1]:r(t)[2]}function n(e){return e%10==0||e>10&&e<20}function r(e){return a[e].split("_")}function i(e,a,t,i){var d=e+" ";return 1===e?d+s(e,a,t[0],i):a?d+(n(e)?r(t)[1]:r(t)[0]):i?d+r(t)[1]:d+(n(e)?r(t)[1]:r(t)[2])}e.defineLocale("lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:t,ss:i,m:s,mm:i,h:s,hh:i,d:s,dd:i,M:s,MM:i,y:s,yy:i},dayOfMonthOrdinalParse:/\d{1,2}-oji/,ordinal:function(e){return e+"-oji"},week:{dow:1,doy:4}})}(t(5093))},9532:function(e,a,t){!function(e){"use strict"; +var a={ss:"sekundė_sekundžių_sekundes",m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"};function t(e,a,t,s){return a?"kelios sekundės":s?"kelių sekundžių":"kelias sekundes"}function s(e,a,t,s){return a?r(t)[0]:s?r(t)[1]:r(t)[2]}function n(e){return e%10==0||e>10&&e<20}function r(e){return a[e].split("_")}function d(e,a,t,d){var i=e+" ";return 1===e?i+s(e,a,t[0],d):a?i+(n(e)?r(t)[1]:r(t)[0]):d?i+r(t)[1]:i+(n(e)?r(t)[1]:r(t)[2])}e.defineLocale("lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:t,ss:d,m:s,mm:d,h:s,hh:d,d:s,dd:d,M:s,MM:d,y:s,yy:d},dayOfMonthOrdinalParse:/\d{1,2}-oji/,ordinal:function(e){return e+"-oji"},week:{dow:1,doy:4}})}(t(5093))},9532(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={ss:"sekundes_sekundēm_sekunde_sekundes".split("_"),m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")};function t(e,a,t){return t?a%10==1&&a%100!=11?e[2]:e[3]:a%10==1&&a%100!=11?e[0]:e[1]}function s(e,s,n){return e+" "+t(a[n],e,s)}function n(e,s,n){return t(a[n],e,s)}function r(e,a){return a?"dažas sekundes":"dažām sekundēm"}e.defineLocale("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:r,ss:s,m:n,mm:s,h:n,hh:s,d:n,dd:s,M:n,MM:s,y:n,yy:s},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},8076:function(e,a,t){!function(e){"use strict"; +var a={ss:"sekundes_sekundēm_sekunde_sekundes".split("_"),m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")};function t(e,a,t){return t?a%10==1&&a%100!=11?e[2]:e[3]:a%10==1&&a%100!=11?e[0]:e[1]}function s(e,s,n){return e+" "+t(a[n],e,s)}function n(e,s,n){return t(a[n],e,s)}function r(e,a){return a?"dažas sekundes":"dažām sekundēm"}e.defineLocale("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:r,ss:s,m:n,mm:s,h:n,hh:s,d:n,dd:s,M:n,MM:s,y:n,yy:s},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},8076(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={words:{ss:["sekund","sekunda","sekundi"],m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mjesec","mjeseca","mjeseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(e,a){return 1===e?a[0]:e>=2&&e<=4?a[1]:a[2]},translate:function(e,t,s){var n=a.words[s];return 1===s.length?t?n[0]:n[1]:e+" "+a.correctGrammaticalCase(e,n)}};e.defineLocale("me",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sjutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){return["[prošle] [nedjelje] [u] LT","[prošlog] [ponedjeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srijede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"nekoliko sekundi",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"dan",dd:a.translate,M:"mjesec",MM:a.translate,y:"godinu",yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},1848:function(e,a,t){!function(e){"use strict"; +var a={words:{ss:["sekund","sekunda","sekundi"],m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mjesec","mjeseca","mjeseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(e,a){return 1===e?a[0]:e>=2&&e<=4?a[1]:a[2]},translate:function(e,t,s){var n=a.words[s];return 1===s.length?t?n[0]:n[1]:e+" "+a.correctGrammaticalCase(e,n)}};e.defineLocale("me",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sjutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){return["[prošle] [nedjelje] [u] LT","[prošlog] [ponedjeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srijede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"nekoliko sekundi",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"dan",dd:a.translate,M:"mjesec",MM:a.translate,y:"godinu",yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},1848(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("mi",{months:"Kohi-tāte_Hui-tanguru_Poutū-te-rangi_Paenga-whāwhā_Haratua_Pipiri_Hōngoingoi_Here-turi-kōkā_Mahuru_Whiringa-ā-nuku_Whiringa-ā-rangi_Hakihea".split("_"),monthsShort:"Kohi_Hui_Pou_Pae_Hara_Pipi_Hōngoi_Here_Mahu_Whi-nu_Whi-ra_Haki".split("_"),monthsRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsStrictRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsShortRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsShortStrictRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,weekdays:"Rātapu_Mane_Tūrei_Wenerei_Tāite_Paraire_Hātarei".split("_"),weekdaysShort:"Ta_Ma_Tū_We_Tāi_Pa_Hā".split("_"),weekdaysMin:"Ta_Ma_Tū_We_Tāi_Pa_Hā".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [i] HH:mm",LLLL:"dddd, D MMMM YYYY [i] HH:mm"},calendar:{sameDay:"[i teie mahana, i] LT",nextDay:"[apopo i] LT",nextWeek:"dddd [i] LT",lastDay:"[inanahi i] LT",lastWeek:"dddd [whakamutunga i] LT",sameElse:"L"},relativeTime:{future:"i roto i %s",past:"%s i mua",s:"te hēkona ruarua",ss:"%d hēkona",m:"he meneti",mm:"%d meneti",h:"te haora",hh:"%d haora",d:"he ra",dd:"%d ra",M:"he marama",MM:"%d marama",y:"he tau",yy:"%d tau"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},306:function(e,a,t){!function(e){"use strict"; +e.defineLocale("mi",{months:"Kohi-tāte_Hui-tanguru_Poutū-te-rangi_Paenga-whāwhā_Haratua_Pipiri_Hōngoingoi_Here-turi-kōkā_Mahuru_Whiringa-ā-nuku_Whiringa-ā-rangi_Hakihea".split("_"),monthsShort:"Kohi_Hui_Pou_Pae_Hara_Pipi_Hōngoi_Here_Mahu_Whi-nu_Whi-ra_Haki".split("_"),monthsRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsStrictRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsShortRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsShortStrictRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,weekdays:"Rātapu_Mane_Tūrei_Wenerei_Tāite_Paraire_Hātarei".split("_"),weekdaysShort:"Ta_Ma_Tū_We_Tāi_Pa_Hā".split("_"),weekdaysMin:"Ta_Ma_Tū_We_Tāi_Pa_Hā".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [i] HH:mm",LLLL:"dddd, D MMMM YYYY [i] HH:mm"},calendar:{sameDay:"[i teie mahana, i] LT",nextDay:"[apopo i] LT",nextWeek:"dddd [i] LT",lastDay:"[inanahi i] LT",lastWeek:"dddd [whakamutunga i] LT",sameElse:"L"},relativeTime:{future:"i roto i %s",past:"%s i mua",s:"te hēkona ruarua",ss:"%d hēkona",m:"he meneti",mm:"%d meneti",h:"te haora",hh:"%d haora",d:"he ra",dd:"%d ra",M:"he marama",MM:"%d marama",y:"he tau",yy:"%d tau"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},306(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"[Во] dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"за %s",past:"пред %s",s:"неколку секунди",ss:"%d секунди",m:"една минута",mm:"%d минути",h:"еден час",hh:"%d часа",d:"еден ден",dd:"%d дена",M:"еден месец",MM:"%d месеци",y:"една година",yy:"%d години"},dayOfMonthOrdinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var a=e%10,t=e%100;return 0===e?e+"-ев":0===t?e+"-ен":t>10&&t<20?e+"-ти":1===a?e+"-ви":2===a?e+"-ри":7===a||8===a?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})}(t(5093))},3739:function(e,a,t){!function(e){"use strict"; +e.defineLocale("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"[Во] dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"за %s",past:"пред %s",s:"неколку секунди",ss:"%d секунди",m:"една минута",mm:"%d минути",h:"еден час",hh:"%d часа",d:"еден ден",dd:"%d дена",M:"еден месец",MM:"%d месеци",y:"една година",yy:"%d години"},dayOfMonthOrdinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var a=e%10,t=e%100;return 0===e?e+"-ев":0===t?e+"-ен":t>10&&t<20?e+"-ти":1===a?e+"-ви":2===a?e+"-ри":7===a||8===a?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})}(t(5093))},3739(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ml",{months:"ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ".split("_"),monthsShort:"ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.".split("_"),monthsParseExact:!0,weekdays:"ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച".split("_"),weekdaysShort:"ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി".split("_"),weekdaysMin:"ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ".split("_"),longDateFormat:{LT:"A h:mm -നു",LTS:"A h:mm:ss -നു",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm -നു",LLLL:"dddd, D MMMM YYYY, A h:mm -നു"},calendar:{sameDay:"[ഇന്ന്] LT",nextDay:"[നാളെ] LT",nextWeek:"dddd, LT",lastDay:"[ഇന്നലെ] LT",lastWeek:"[കഴിഞ്ഞ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s കഴിഞ്ഞ്",past:"%s മുൻപ്",s:"അൽപ നിമിഷങ്ങൾ",ss:"%d സെക്കൻഡ്",m:"ഒരു മിനിറ്റ്",mm:"%d മിനിറ്റ്",h:"ഒരു മണിക്കൂർ",hh:"%d മണിക്കൂർ",d:"ഒരു ദിവസം",dd:"%d ദിവസം",M:"ഒരു മാസം",MM:"%d മാസം",y:"ഒരു വർഷം",yy:"%d വർഷം"},meridiemParse:/രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,meridiemHour:function(e,a){return 12===e&&(e=0),"രാത്രി"===a&&e>=4||"ഉച്ച കഴിഞ്ഞ്"===a||"വൈകുന്നേരം"===a?e+12:e},meridiem:function(e,a,t){return e<4?"രാത്രി":e<12?"രാവിലെ":e<17?"ഉച്ച കഴിഞ്ഞ്":e<20?"വൈകുന്നേരം":"രാത്രി"}})}(t(5093))},9053:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ml",{months:"ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ".split("_"),monthsShort:"ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.".split("_"),monthsParseExact:!0,weekdays:"ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച".split("_"),weekdaysShort:"ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി".split("_"),weekdaysMin:"ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ".split("_"),longDateFormat:{LT:"A h:mm -നു",LTS:"A h:mm:ss -നു",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm -നു",LLLL:"dddd, D MMMM YYYY, A h:mm -നു"},calendar:{sameDay:"[ഇന്ന്] LT",nextDay:"[നാളെ] LT",nextWeek:"dddd, LT",lastDay:"[ഇന്നലെ] LT",lastWeek:"[കഴിഞ്ഞ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s കഴിഞ്ഞ്",past:"%s മുൻപ്",s:"അൽപ നിമിഷങ്ങൾ",ss:"%d സെക്കൻഡ്",m:"ഒരു മിനിറ്റ്",mm:"%d മിനിറ്റ്",h:"ഒരു മണിക്കൂർ",hh:"%d മണിക്കൂർ",d:"ഒരു ദിവസം",dd:"%d ദിവസം",M:"ഒരു മാസം",MM:"%d മാസം",y:"ഒരു വർഷം",yy:"%d വർഷം"},meridiemParse:/രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,meridiemHour:function(e,a){return 12===e&&(e=0),"രാത്രി"===a&&e>=4||"ഉച്ച കഴിഞ്ഞ്"===a||"വൈകുന്നേരം"===a?e+12:e},meridiem:function(e,a,t){return e<4?"രാത്രി":e<12?"രാവിലെ":e<17?"ഉച്ച കഴിഞ്ഞ്":e<20?"വൈകുന്നേരം":"രാത്രി"}})}(t(5093))},9053(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){switch(t){case"s":return a?"хэдхэн секунд":"хэдхэн секундын";case"ss":return e+(a?" секунд":" секундын");case"m":case"mm":return e+(a?" минут":" минутын");case"h":case"hh":return e+(a?" цаг":" цагийн");case"d":case"dd":return e+(a?" өдөр":" өдрийн");case"M":case"MM":return e+(a?" сар":" сарын");case"y":case"yy":return e+(a?" жил":" жилийн");default:return e}}e.defineLocale("mn",{months:"Нэгдүгээр сар_Хоёрдугаар сар_Гуравдугаар сар_Дөрөвдүгээр сар_Тавдугаар сар_Зургадугаар сар_Долдугаар сар_Наймдугаар сар_Есдүгээр сар_Аравдугаар сар_Арван нэгдүгээр сар_Арван хоёрдугаар сар".split("_"),monthsShort:"1 сар_2 сар_3 сар_4 сар_5 сар_6 сар_7 сар_8 сар_9 сар_10 сар_11 сар_12 сар".split("_"),monthsParseExact:!0,weekdays:"Ням_Даваа_Мягмар_Лхагва_Пүрэв_Баасан_Бямба".split("_"),weekdaysShort:"Ням_Дав_Мяг_Лха_Пүр_Баа_Бям".split("_"),weekdaysMin:"Ня_Да_Мя_Лх_Пү_Ба_Бя".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY оны MMMMын D",LLL:"YYYY оны MMMMын D HH:mm",LLLL:"dddd, YYYY оны MMMMын D HH:mm"},meridiemParse:/ҮӨ|ҮХ/i,isPM:function(e){return"ҮХ"===e},meridiem:function(e,a,t){return e<12?"ҮӨ":"ҮХ"},calendar:{sameDay:"[Өнөөдөр] LT",nextDay:"[Маргааш] LT",nextWeek:"[Ирэх] dddd LT",lastDay:"[Өчигдөр] LT",lastWeek:"[Өнгөрсөн] dddd LT",sameElse:"L"},relativeTime:{future:"%s дараа",past:"%s өмнө",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2} өдөр/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+" өдөр";default:return e}}})}(t(5093))},6169:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){switch(t){case"s":return a?"хэдхэн секунд":"хэдхэн секундын";case"ss":return e+(a?" секунд":" секундын");case"m":case"mm":return e+(a?" минут":" минутын");case"h":case"hh":return e+(a?" цаг":" цагийн");case"d":case"dd":return e+(a?" өдөр":" өдрийн");case"M":case"MM":return e+(a?" сар":" сарын");case"y":case"yy":return e+(a?" жил":" жилийн");default:return e}}e.defineLocale("mn",{months:"Нэгдүгээр сар_Хоёрдугаар сар_Гуравдугаар сар_Дөрөвдүгээр сар_Тавдугаар сар_Зургадугаар сар_Долдугаар сар_Наймдугаар сар_Есдүгээр сар_Аравдугаар сар_Арван нэгдүгээр сар_Арван хоёрдугаар сар".split("_"),monthsShort:"1 сар_2 сар_3 сар_4 сар_5 сар_6 сар_7 сар_8 сар_9 сар_10 сар_11 сар_12 сар".split("_"),monthsParseExact:!0,weekdays:"Ням_Даваа_Мягмар_Лхагва_Пүрэв_Баасан_Бямба".split("_"),weekdaysShort:"Ням_Дав_Мяг_Лха_Пүр_Баа_Бям".split("_"),weekdaysMin:"Ня_Да_Мя_Лх_Пү_Ба_Бя".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY оны MMMMын D",LLL:"YYYY оны MMMMын D HH:mm",LLLL:"dddd, YYYY оны MMMMын D HH:mm"},meridiemParse:/ҮӨ|ҮХ/i,isPM:function(e){return"ҮХ"===e},meridiem:function(e,a,t){return e<12?"ҮӨ":"ҮХ"},calendar:{sameDay:"[Өнөөдөр] LT",nextDay:"[Маргааш] LT",nextWeek:"[Ирэх] dddd LT",lastDay:"[Өчигдөр] LT",lastWeek:"[Өнгөрсөн] dddd LT",sameElse:"L"},relativeTime:{future:"%s дараа",past:"%s өмнө",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2} өдөр/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+" өдөр";default:return e}}})}(t(5093))},6169(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};function s(e,a,t,s){var n="";if(a)switch(t){case"s":n="काही सेकंद";break;case"ss":n="%d सेकंद";break;case"m":n="एक मिनिट";break;case"mm":n="%d मिनिटे";break;case"h":n="एक तास";break;case"hh":n="%d तास";break;case"d":n="एक दिवस";break;case"dd":n="%d दिवस";break;case"M":n="एक महिना";break;case"MM":n="%d महिने";break;case"y":n="एक वर्ष";break;case"yy":n="%d वर्षे"}else switch(t){case"s":n="काही सेकंदां";break;case"ss":n="%d सेकंदां";break;case"m":n="एका मिनिटा";break;case"mm":n="%d मिनिटां";break;case"h":n="एका तासा";break;case"hh":n="%d तासां";break;case"d":n="एका दिवसा";break;case"dd":n="%d दिवसां";break;case"M":n="एका महिन्या";break;case"MM":n="%d महिन्यां";break;case"y":n="एका वर्षा";break;case"yy":n="%d वर्षां"}return n.replace(/%d/i,e)}e.defineLocale("mr",{months:"जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),monthsShort:"जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm वाजता",LTS:"A h:mm:ss वाजता",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm वाजता",LLLL:"dddd, D MMMM YYYY, A h:mm वाजता"},calendar:{sameDay:"[आज] LT",nextDay:"[उद्या] LT",nextWeek:"dddd, LT",lastDay:"[काल] LT",lastWeek:"[मागील] dddd, LT",sameElse:"L"},relativeTime:{future:"%sमध्ये",past:"%sपूर्वी",s,ss:s,m:s,mm:s,h:s,hh:s,d:s,dd:s,M:s,MM:s,y:s,yy:s},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/पहाटे|सकाळी|दुपारी|सायंकाळी|रात्री/,meridiemHour:function(e,a){return 12===e&&(e=0),"पहाटे"===a||"सकाळी"===a?e:"दुपारी"===a||"सायंकाळी"===a||"रात्री"===a?e>=12?e:e+12:void 0},meridiem:function(e,a,t){return e>=0&&e<6?"पहाटे":e<12?"सकाळी":e<17?"दुपारी":e<20?"सायंकाळी":"रात्री"},week:{dow:0,doy:6}})}(t(5093))},2297:function(e,a,t){!function(e){"use strict"; +var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};function s(e,a,t,s){var n="";if(a)switch(t){case"s":n="काही सेकंद";break;case"ss":n="%d सेकंद";break;case"m":n="एक मिनिट";break;case"mm":n="%d मिनिटे";break;case"h":n="एक तास";break;case"hh":n="%d तास";break;case"d":n="एक दिवस";break;case"dd":n="%d दिवस";break;case"M":n="एक महिना";break;case"MM":n="%d महिने";break;case"y":n="एक वर्ष";break;case"yy":n="%d वर्षे"}else switch(t){case"s":n="काही सेकंदां";break;case"ss":n="%d सेकंदां";break;case"m":n="एका मिनिटा";break;case"mm":n="%d मिनिटां";break;case"h":n="एका तासा";break;case"hh":n="%d तासां";break;case"d":n="एका दिवसा";break;case"dd":n="%d दिवसां";break;case"M":n="एका महिन्या";break;case"MM":n="%d महिन्यां";break;case"y":n="एका वर्षा";break;case"yy":n="%d वर्षां"}return n.replace(/%d/i,e)}e.defineLocale("mr",{months:"जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),monthsShort:"जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm वाजता",LTS:"A h:mm:ss वाजता",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm वाजता",LLLL:"dddd, D MMMM YYYY, A h:mm वाजता"},calendar:{sameDay:"[आज] LT",nextDay:"[उद्या] LT",nextWeek:"dddd, LT",lastDay:"[काल] LT",lastWeek:"[मागील] dddd, LT",sameElse:"L"},relativeTime:{future:"%sमध्ये",past:"%sपूर्वी",s,ss:s,m:s,mm:s,h:s,hh:s,d:s,dd:s,M:s,MM:s,y:s,yy:s},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/पहाटे|सकाळी|दुपारी|सायंकाळी|रात्री/,meridiemHour:function(e,a){return 12===e&&(e=0),"पहाटे"===a||"सकाळी"===a?e:"दुपारी"===a||"सायंकाळी"===a||"रात्री"===a?e>=12?e:e+12:void 0},meridiem:function(e,a,t){return e>=0&&e<6?"पहाटे":e<12?"सकाळी":e<17?"दुपारी":e<20?"सायंकाळी":"रात्री"},week:{dow:0,doy:6}})}(t(5093))},2297(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"tengahari"===a?e>=11?e:e+12:"petang"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"tengahari":e<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}(t(5093))},3386:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"tengahari"===a?e>=11?e:e+12:"petang"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"tengahari":e<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}(t(5093))},3386(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ms",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"tengahari"===a?e>=11?e:e+12:"petang"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"tengahari":e<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}(t(5093))},7075:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ms",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"tengahari"===a?e>=11?e:e+12:"petang"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"tengahari":e<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}(t(5093))},7075(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("mt",{months:"Jannar_Frar_Marzu_April_Mejju_Ġunju_Lulju_Awwissu_Settembru_Ottubru_Novembru_Diċembru".split("_"),monthsShort:"Jan_Fra_Mar_Apr_Mej_Ġun_Lul_Aww_Set_Ott_Nov_Diċ".split("_"),weekdays:"Il-Ħadd_It-Tnejn_It-Tlieta_L-Erbgħa_Il-Ħamis_Il-Ġimgħa_Is-Sibt".split("_"),weekdaysShort:"Ħad_Tne_Tli_Erb_Ħam_Ġim_Sib".split("_"),weekdaysMin:"Ħa_Tn_Tl_Er_Ħa_Ġi_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Illum fil-]LT",nextDay:"[Għada fil-]LT",nextWeek:"dddd [fil-]LT",lastDay:"[Il-bieraħ fil-]LT",lastWeek:"dddd [li għadda] [fil-]LT",sameElse:"L"},relativeTime:{future:"f’ %s",past:"%s ilu",s:"ftit sekondi",ss:"%d sekondi",m:"minuta",mm:"%d minuti",h:"siegħa",hh:"%d siegħat",d:"ġurnata",dd:"%d ġranet",M:"xahar",MM:"%d xhur",y:"sena",yy:"%d sni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},2264:function(e,a,t){!function(e){"use strict"; +e.defineLocale("mt",{months:"Jannar_Frar_Marzu_April_Mejju_Ġunju_Lulju_Awwissu_Settembru_Ottubru_Novembru_Diċembru".split("_"),monthsShort:"Jan_Fra_Mar_Apr_Mej_Ġun_Lul_Aww_Set_Ott_Nov_Diċ".split("_"),weekdays:"Il-Ħadd_It-Tnejn_It-Tlieta_L-Erbgħa_Il-Ħamis_Il-Ġimgħa_Is-Sibt".split("_"),weekdaysShort:"Ħad_Tne_Tli_Erb_Ħam_Ġim_Sib".split("_"),weekdaysMin:"Ħa_Tn_Tl_Er_Ħa_Ġi_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Illum fil-]LT",nextDay:"[Għada fil-]LT",nextWeek:"dddd [fil-]LT",lastDay:"[Il-bieraħ fil-]LT",lastWeek:"dddd [li għadda] [fil-]LT",sameElse:"L"},relativeTime:{future:"f’ %s",past:"%s ilu",s:"ftit sekondi",ss:"%d sekondi",m:"minuta",mm:"%d minuti",h:"siegħa",hh:"%d siegħat",d:"ġurnata",dd:"%d ġranet",M:"xahar",MM:"%d xhur",y:"sena",yy:"%d sni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},2264(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"၁",2:"၂",3:"၃",4:"၄",5:"၅",6:"၆",7:"၇",8:"၈",9:"၉",0:"၀"},t={"၁":"1","၂":"2","၃":"3","၄":"4","၅":"5","၆":"6","၇":"7","၈":"8","၉":"9","၀":"0"};e.defineLocale("my",{months:"ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ".split("_"),monthsShort:"ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ".split("_"),weekdays:"တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ".split("_"),weekdaysShort:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),weekdaysMin:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ယနေ.] LT [မှာ]",nextDay:"[မနက်ဖြန်] LT [မှာ]",nextWeek:"dddd LT [မှာ]",lastDay:"[မနေ.က] LT [မှာ]",lastWeek:"[ပြီးခဲ့သော] dddd LT [မှာ]",sameElse:"L"},relativeTime:{future:"လာမည့် %s မှာ",past:"လွန်ခဲ့သော %s က",s:"စက္ကန်.အနည်းငယ်",ss:"%d စက္ကန့်",m:"တစ်မိနစ်",mm:"%d မိနစ်",h:"တစ်နာရီ",hh:"%d နာရီ",d:"တစ်ရက်",dd:"%d ရက်",M:"တစ်လ",MM:"%d လ",y:"တစ်နှစ်",yy:"%d နှစ်"},preparse:function(e){return e.replace(/[၁၂၃၄၅၆၇၈၉၀]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},week:{dow:1,doy:4}})}(t(5093))},2274:function(e,a,t){!function(e){"use strict"; +var a={1:"၁",2:"၂",3:"၃",4:"၄",5:"၅",6:"၆",7:"၇",8:"၈",9:"၉",0:"၀"},t={"၁":"1","၂":"2","၃":"3","၄":"4","၅":"5","၆":"6","၇":"7","၈":"8","၉":"9","၀":"0"};e.defineLocale("my",{months:"ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ".split("_"),monthsShort:"ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ".split("_"),weekdays:"တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ".split("_"),weekdaysShort:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),weekdaysMin:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ယနေ.] LT [မှာ]",nextDay:"[မနက်ဖြန်] LT [မှာ]",nextWeek:"dddd LT [မှာ]",lastDay:"[မနေ.က] LT [မှာ]",lastWeek:"[ပြီးခဲ့သော] dddd LT [မှာ]",sameElse:"L"},relativeTime:{future:"လာမည့် %s မှာ",past:"လွန်ခဲ့သော %s က",s:"စက္ကန်.အနည်းငယ်",ss:"%d စက္ကန့်",m:"တစ်မိနစ်",mm:"%d မိနစ်",h:"တစ်နာရီ",hh:"%d နာရီ",d:"တစ်ရက်",dd:"%d ရက်",M:"တစ်လ",MM:"%d လ",y:"တစ်နှစ်",yy:"%d နှစ်"},preparse:function(e){return e.replace(/[၁၂၃၄၅၆၇၈၉၀]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},week:{dow:1,doy:4}})}(t(5093))},2274(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",ss:"%d sekunder",m:"ett minutt",mm:"%d minutter",h:"én time",hh:"%d timer",d:"én dag",dd:"%d dager",w:"én uke",ww:"%d uker",M:"én måned",MM:"%d måneder",y:"ett år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},8235:function(e,a,t){!function(e){"use strict"; +e.defineLocale("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",ss:"%d sekunder",m:"ett minutt",mm:"%d minutter",h:"én time",hh:"%d timer",d:"én dag",dd:"%d dager",w:"én uke",ww:"%d uker",M:"én måned",MM:"%d måneder",y:"ett år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},8235(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};e.defineLocale("ne",{months:"जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर".split("_"),monthsShort:"जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.".split("_"),monthsParseExact:!0,weekdays:"आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार".split("_"),weekdaysShort:"आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.".split("_"),weekdaysMin:"आ._सो._मं._बु._बि._शु._श.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"Aको h:mm बजे",LTS:"Aको h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, Aको h:mm बजे",LLLL:"dddd, D MMMM YYYY, Aको h:mm बजे"},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/राति|बिहान|दिउँसो|साँझ/,meridiemHour:function(e,a){return 12===e&&(e=0),"राति"===a?e<4?e:e+12:"बिहान"===a?e:"दिउँसो"===a?e>=10?e:e+12:"साँझ"===a?e+12:void 0},meridiem:function(e,a,t){return e<3?"राति":e<12?"बिहान":e<16?"दिउँसो":e<20?"साँझ":"राति"},calendar:{sameDay:"[आज] LT",nextDay:"[भोलि] LT",nextWeek:"[आउँदो] dddd[,] LT",lastDay:"[हिजो] LT",lastWeek:"[गएको] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%sमा",past:"%s अगाडि",s:"केही क्षण",ss:"%d सेकेण्ड",m:"एक मिनेट",mm:"%d मिनेट",h:"एक घण्टा",hh:"%d घण्टा",d:"एक दिन",dd:"%d दिन",M:"एक महिना",MM:"%d महिना",y:"एक बर्ष",yy:"%d बर्ष"},week:{dow:0,doy:6}})}(t(5093))},3784:function(e,a,t){!function(e){"use strict"; +var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};e.defineLocale("ne",{months:"जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर".split("_"),monthsShort:"जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.".split("_"),monthsParseExact:!0,weekdays:"आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार".split("_"),weekdaysShort:"आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.".split("_"),weekdaysMin:"आ._सो._मं._बु._बि._शु._श.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"Aको h:mm बजे",LTS:"Aको h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, Aको h:mm बजे",LLLL:"dddd, D MMMM YYYY, Aको h:mm बजे"},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/राति|बिहान|दिउँसो|साँझ/,meridiemHour:function(e,a){return 12===e&&(e=0),"राति"===a?e<4?e:e+12:"बिहान"===a?e:"दिउँसो"===a?e>=10?e:e+12:"साँझ"===a?e+12:void 0},meridiem:function(e,a,t){return e<3?"राति":e<12?"बिहान":e<16?"दिउँसो":e<20?"साँझ":"राति"},calendar:{sameDay:"[आज] LT",nextDay:"[भोलि] LT",nextWeek:"[आउँदो] dddd[,] LT",lastDay:"[हिजो] LT",lastWeek:"[गएको] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%sमा",past:"%s अगाडि",s:"केही क्षण",ss:"%d सेकेण्ड",m:"एक मिनेट",mm:"%d मिनेट",h:"एक घण्टा",hh:"%d घण्टा",d:"एक दिन",dd:"%d दिन",M:"एक महिना",MM:"%d महिना",y:"एक बर्ष",yy:"%d बर्ष"},week:{dow:0,doy:6}})}(t(5093))},3784(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),t="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),s=[/^jan/i,/^feb/i,/^(maart|mrt\.?)$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],n=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;e.defineLocale("nl-be",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},2572:function(e,a,t){!function(e){"use strict"; +var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),t="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),s=[/^jan/i,/^feb/i,/^(maart|mrt\.?)$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],n=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;e.defineLocale("nl-be",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},2572(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),t="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),s=[/^jan/i,/^feb/i,/^(maart|mrt\.?)$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],n=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;e.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",w:"één week",ww:"%d weken",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},4566:function(e,a,t){!function(e){"use strict"; +var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),t="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),s=[/^jan/i,/^feb/i,/^(maart|mrt\.?)$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],n=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;e.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,s){return e?/-MMM-/.test(s)?t[e.month()]:a[e.month()]:a},monthsRegex:n,monthsShortRegex:n,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",w:"één week",ww:"%d weken",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(t(5093))},4566(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"su._må._ty._on._to._fr._lau.".split("_"),weekdaysMin:"su_må_ty_on_to_fr_la".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",ss:"%d sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",w:"ei veke",ww:"%d veker",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},9330:function(e,a,t){!function(e){"use strict"; +e.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"su._må._ty._on._to._fr._lau.".split("_"),weekdaysMin:"su_må_ty_on_to_fr_la".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",ss:"%d sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",w:"ei veke",ww:"%d veker",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},9330(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("oc-lnc",{months:{standalone:"genièr_febrièr_març_abril_mai_junh_julhet_agost_setembre_octòbre_novembre_decembre".split("_"),format:"de genièr_de febrièr_de març_d'abril_de mai_de junh_de julhet_d'agost_de setembre_d'octòbre_de novembre_de decembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._mai_junh_julh._ago._set._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"dimenge_diluns_dimars_dimècres_dijòus_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dm._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dm_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:"[uèi a] LT",nextDay:"[deman a] LT",nextWeek:"dddd [a] LT",lastDay:"[ièr a] LT",lastWeek:"dddd [passat a] LT",sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"unas segondas",ss:"%d segondas",m:"una minuta",mm:"%d minutas",h:"una ora",hh:"%d oras",d:"un jorn",dd:"%d jorns",M:"un mes",MM:"%d meses",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(e,a){var t=1===e?"r":2===e?"n":3===e?"r":4===e?"t":"è";return"w"!==a&&"W"!==a||(t="a"),e+t},week:{dow:1,doy:4}})}(t(5093))},9849:function(e,a,t){!function(e){"use strict"; +e.defineLocale("oc-lnc",{months:{standalone:"genièr_febrièr_març_abril_mai_junh_julhet_agost_setembre_octòbre_novembre_decembre".split("_"),format:"de genièr_de febrièr_de març_d'abril_de mai_de junh_de julhet_d'agost_de setembre_d'octòbre_de novembre_de decembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._mai_junh_julh._ago._set._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"dimenge_diluns_dimars_dimècres_dijòus_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dm._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dm_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:"[uèi a] LT",nextDay:"[deman a] LT",nextWeek:"dddd [a] LT",lastDay:"[ièr a] LT",lastWeek:"dddd [passat a] LT",sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"unas segondas",ss:"%d segondas",m:"una minuta",mm:"%d minutas",h:"una ora",hh:"%d oras",d:"un jorn",dd:"%d jorns",M:"un mes",MM:"%d meses",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(e,a){var t=1===e?"r":2===e?"n":3===e?"r":4===e?"t":"è";return"w"!==a&&"W"!==a||(t="a"),e+t},week:{dow:1,doy:4}})}(t(5093))},9849(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"੧",2:"੨",3:"੩",4:"੪",5:"੫",6:"੬",7:"੭",8:"੮",9:"੯",0:"੦"},t={"੧":"1","੨":"2","੩":"3","੪":"4","੫":"5","੬":"6","੭":"7","੮":"8","੯":"9","੦":"0"};e.defineLocale("pa-in",{months:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),monthsShort:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),weekdays:"ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ".split("_"),weekdaysShort:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),weekdaysMin:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),longDateFormat:{LT:"A h:mm ਵਜੇ",LTS:"A h:mm:ss ਵਜੇ",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm ਵਜੇ",LLLL:"dddd, D MMMM YYYY, A h:mm ਵਜੇ"},calendar:{sameDay:"[ਅਜ] LT",nextDay:"[ਕਲ] LT",nextWeek:"[ਅਗਲਾ] dddd, LT",lastDay:"[ਕਲ] LT",lastWeek:"[ਪਿਛਲੇ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ਵਿੱਚ",past:"%s ਪਿਛਲੇ",s:"ਕੁਝ ਸਕਿੰਟ",ss:"%d ਸਕਿੰਟ",m:"ਇਕ ਮਿੰਟ",mm:"%d ਮਿੰਟ",h:"ਇੱਕ ਘੰਟਾ",hh:"%d ਘੰਟੇ",d:"ਇੱਕ ਦਿਨ",dd:"%d ਦਿਨ",M:"ਇੱਕ ਮਹੀਨਾ",MM:"%d ਮਹੀਨੇ",y:"ਇੱਕ ਸਾਲ",yy:"%d ਸਾਲ"},preparse:function(e){return e.replace(/[੧੨੩੪੫੬੭੮੯੦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,meridiemHour:function(e,a){return 12===e&&(e=0),"ਰਾਤ"===a?e<4?e:e+12:"ਸਵੇਰ"===a?e:"ਦੁਪਹਿਰ"===a?e>=10?e:e+12:"ਸ਼ਾਮ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"ਰਾਤ":e<10?"ਸਵੇਰ":e<17?"ਦੁਪਹਿਰ":e<20?"ਸ਼ਾਮ":"ਰਾਤ"},week:{dow:0,doy:6}})}(t(5093))},4418:function(e,a,t){!function(e){"use strict"; +var a={1:"੧",2:"੨",3:"੩",4:"੪",5:"੫",6:"੬",7:"੭",8:"੮",9:"੯",0:"੦"},t={"੧":"1","੨":"2","੩":"3","੪":"4","੫":"5","੬":"6","੭":"7","੮":"8","੯":"9","੦":"0"};e.defineLocale("pa-in",{months:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),monthsShort:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),weekdays:"ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ".split("_"),weekdaysShort:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),weekdaysMin:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),longDateFormat:{LT:"A h:mm ਵਜੇ",LTS:"A h:mm:ss ਵਜੇ",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm ਵਜੇ",LLLL:"dddd, D MMMM YYYY, A h:mm ਵਜੇ"},calendar:{sameDay:"[ਅਜ] LT",nextDay:"[ਕਲ] LT",nextWeek:"[ਅਗਲਾ] dddd, LT",lastDay:"[ਕਲ] LT",lastWeek:"[ਪਿਛਲੇ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ਵਿੱਚ",past:"%s ਪਿਛਲੇ",s:"ਕੁਝ ਸਕਿੰਟ",ss:"%d ਸਕਿੰਟ",m:"ਇਕ ਮਿੰਟ",mm:"%d ਮਿੰਟ",h:"ਇੱਕ ਘੰਟਾ",hh:"%d ਘੰਟੇ",d:"ਇੱਕ ਦਿਨ",dd:"%d ਦਿਨ",M:"ਇੱਕ ਮਹੀਨਾ",MM:"%d ਮਹੀਨੇ",y:"ਇੱਕ ਸਾਲ",yy:"%d ਸਾਲ"},preparse:function(e){return e.replace(/[੧੨੩੪੫੬੭੮੯੦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,meridiemHour:function(e,a){return 12===e&&(e=0),"ਰਾਤ"===a?e<4?e:e+12:"ਸਵੇਰ"===a?e:"ਦੁਪਹਿਰ"===a?e>=10?e:e+12:"ਸ਼ਾਮ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"ਰਾਤ":e<10?"ਸਵੇਰ":e<17?"ਦੁਪਹਿਰ":e<20?"ਸ਼ਾਮ":"ਰਾਤ"},week:{dow:0,doy:6}})}(t(5093))},4418(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),t="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),s=[/^sty/i,/^lut/i,/^mar/i,/^kwi/i,/^maj/i,/^cze/i,/^lip/i,/^sie/i,/^wrz/i,/^paź/i,/^lis/i,/^gru/i];function n(e){return e%10<5&&e%10>1&&~~(e/10)%10!=1}function r(e,a,t){var s=e+" ";switch(t){case"ss":return s+(n(e)?"sekundy":"sekund");case"m":return a?"minuta":"minutę";case"mm":return s+(n(e)?"minuty":"minut");case"h":return a?"godzina":"godzinę";case"hh":return s+(n(e)?"godziny":"godzin");case"ww":return s+(n(e)?"tygodnie":"tygodni");case"MM":return s+(n(e)?"miesiące":"miesięcy");case"yy":return s+(n(e)?"lata":"lat")}}e.defineLocale("pl",{months:function(e,s){return e?/D MMMM/.test(s)?t[e.month()]:a[e.month()]:a},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_śr_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedzielę o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W środę o] LT";case 6:return"[W sobotę o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:r,m:r,mm:r,h:r,hh:r,d:"1 dzień",dd:"%d dni",w:"tydzień",ww:r,M:"miesiąc",MM:r,y:"rok",yy:r},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},8303:function(e,a,t){!function(e){"use strict"; +var a="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),t="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),s=[/^sty/i,/^lut/i,/^mar/i,/^kwi/i,/^maj/i,/^cze/i,/^lip/i,/^sie/i,/^wrz/i,/^paź/i,/^lis/i,/^gru/i];function n(e){return e%10<5&&e%10>1&&~~(e/10)%10!=1}function r(e,a,t){var s=e+" ";switch(t){case"ss":return s+(n(e)?"sekundy":"sekund");case"m":return a?"minuta":"minutę";case"mm":return s+(n(e)?"minuty":"minut");case"h":return a?"godzina":"godzinę";case"hh":return s+(n(e)?"godziny":"godzin");case"ww":return s+(n(e)?"tygodnie":"tygodni");case"MM":return s+(n(e)?"miesiące":"miesięcy");case"yy":return s+(n(e)?"lata":"lat")}}e.defineLocale("pl",{months:function(e,s){return e?/D MMMM/.test(s)?t[e.month()]:a[e.month()]:a},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_śr_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedzielę o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W środę o] LT";case 6:return"[W sobotę o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:r,m:r,mm:r,h:r,hh:r,d:"1 dzień",dd:"%d dni",w:"tydzień",ww:r,M:"miesiąc",MM:r,y:"rok",yy:r},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},8303(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("pt-br",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),weekdaysShort:"dom_seg_ter_qua_qui_sex_sáb".split("_"),weekdaysMin:"do_2ª_3ª_4ª_5ª_6ª_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"poucos segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",invalidDate:"Data inválida"})}(t(5093))},9834:function(e,a,t){!function(e){"use strict"; +e.defineLocale("pt-br",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),weekdaysShort:"dom_seg_ter_qua_qui_sex_sáb".split("_"),weekdaysMin:"do_2ª_3ª_4ª_5ª_6ª_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"poucos segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",invalidDate:"Data inválida"})}(t(5093))},9834(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("pt",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Do_2ª_3ª_4ª_5ª_6ª_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",w:"uma semana",ww:"%d semanas",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},4457:function(e,a,t){!function(e){"use strict"; +e.defineLocale("pt",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Do_2ª_3ª_4ª_5ª_6ª_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",w:"uma semana",ww:"%d semanas",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(t(5093))},4457(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t){var s=" ";return(e%100>=20||e>=100&&e%100==0)&&(s=" de "),e+s+{ss:"secunde",mm:"minute",hh:"ore",dd:"zile",ww:"săptămâni",MM:"luni",yy:"ani"}[t]}e.defineLocale("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._feb._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",ss:a,m:"un minut",mm:a,h:"o oră",hh:a,d:"o zi",dd:a,w:"o săptămână",ww:a,M:"o lună",MM:a,y:"un an",yy:a},week:{dow:1,doy:7}})}(t(5093))},2271:function(e,a,t){!function(e){"use strict"; +function a(e,a,t){var s=" ";return(e%100>=20||e>=100&&e%100==0)&&(s=" de "),e+s+{ss:"secunde",mm:"minute",hh:"ore",dd:"zile",ww:"săptămâni",MM:"luni",yy:"ani"}[t]}e.defineLocale("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._feb._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",ss:a,m:"un minut",mm:a,h:"o oră",hh:a,d:"o zi",dd:a,w:"o săptămână",ww:a,M:"o lună",MM:a,y:"un an",yy:a},week:{dow:1,doy:7}})}(t(5093))},2271(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,s){return"m"===s?t?"минута":"минуту":e+" "+a({ss:t?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:t?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",ww:"неделя_недели_недель",MM:"месяц_месяца_месяцев",yy:"год_года_лет"}[s],+e)}var s=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i];e.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:s,longMonthsParse:s,shortMonthsParse:s,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:t,m:t,mm:t,h:"час",hh:t,d:"день",dd:t,w:"неделя",ww:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(e){return/^(дня|вечера)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночи":e<12?"утра":e<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":return e+"-й";case"D":return e+"-го";case"w":case"W":return e+"-я";default:return e}},week:{dow:1,doy:4}})}(t(5093))},1221:function(e,a,t){!function(e){"use strict"; +function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,s){return"m"===s?t?"минута":"минуту":e+" "+a({ss:t?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:t?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",ww:"неделя_недели_недель",MM:"месяц_месяца_месяцев",yy:"год_года_лет"}[s],+e)}var s=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i];e.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:s,longMonthsParse:s,shortMonthsParse:s,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:t,m:t,mm:t,h:"час",hh:t,d:"день",dd:t,w:"неделя",ww:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(e){return/^(дня|вечера)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночи":e<12?"утра":e<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":return e+"-й";case"D":return e+"-го";case"w":case"W":return e+"-я";default:return e}},week:{dow:1,doy:4}})}(t(5093))},1221(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=["جنوري","فيبروري","مارچ","اپريل","مئي","جون","جولاءِ","آگسٽ","سيپٽمبر","آڪٽوبر","نومبر","ڊسمبر"],t=["آچر","سومر","اڱارو","اربع","خميس","جمع","ڇنڇر"];e.defineLocale("sd",{months:a,monthsShort:a,weekdays:t,weekdaysShort:t,weekdaysMin:t,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd، D MMMM YYYY HH:mm"},meridiemParse:/صبح|شام/,isPM:function(e){return"شام"===e},meridiem:function(e,a,t){return e<12?"صبح":"شام"},calendar:{sameDay:"[اڄ] LT",nextDay:"[سڀاڻي] LT",nextWeek:"dddd [اڳين هفتي تي] LT",lastDay:"[ڪالهه] LT",lastWeek:"[گزريل هفتي] dddd [تي] LT",sameElse:"L"},relativeTime:{future:"%s پوء",past:"%s اڳ",s:"چند سيڪنڊ",ss:"%d سيڪنڊ",m:"هڪ منٽ",mm:"%d منٽ",h:"هڪ ڪلاڪ",hh:"%d ڪلاڪ",d:"هڪ ڏينهن",dd:"%d ڏينهن",M:"هڪ مهينو",MM:"%d مهينا",y:"هڪ سال",yy:"%d سال"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:1,doy:4}})}(t(5093))},3478:function(e,a,t){!function(e){"use strict"; +var a=["جنوري","فيبروري","مارچ","اپريل","مئي","جون","جولاءِ","آگسٽ","سيپٽمبر","آڪٽوبر","نومبر","ڊسمبر"],t=["آچر","سومر","اڱارو","اربع","خميس","جمع","ڇنڇر"];e.defineLocale("sd",{months:a,monthsShort:a,weekdays:t,weekdaysShort:t,weekdaysMin:t,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd، D MMMM YYYY HH:mm"},meridiemParse:/صبح|شام/,isPM:function(e){return"شام"===e},meridiem:function(e,a,t){return e<12?"صبح":"شام"},calendar:{sameDay:"[اڄ] LT",nextDay:"[سڀاڻي] LT",nextWeek:"dddd [اڳين هفتي تي] LT",lastDay:"[ڪالهه] LT",lastWeek:"[گزريل هفتي] dddd [تي] LT",sameElse:"L"},relativeTime:{future:"%s پوء",past:"%s اڳ",s:"چند سيڪنڊ",ss:"%d سيڪنڊ",m:"هڪ منٽ",mm:"%d منٽ",h:"هڪ ڪلاڪ",hh:"%d ڪلاڪ",d:"هڪ ڏينهن",dd:"%d ڏينهن",M:"هڪ مهينو",MM:"%d مهينا",y:"هڪ سال",yy:"%d سال"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:1,doy:4}})}(t(5093))},3478(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("se",{months:"ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu".split("_"),monthsShort:"ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov".split("_"),weekdays:"sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat".split("_"),weekdaysShort:"sotn_vuos_maŋ_gask_duor_bear_láv".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s geažes",past:"maŋit %s",s:"moadde sekunddat",ss:"%d sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta mánnu",MM:"%d mánut",y:"okta jahki",yy:"%d jagit"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7538:function(e,a,t){!function(e){"use strict"; +e.defineLocale("se",{months:"ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu".split("_"),monthsShort:"ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov".split("_"),weekdays:"sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat".split("_"),weekdaysShort:"sotn_vuos_maŋ_gask_duor_bear_láv".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s geažes",past:"maŋit %s",s:"moadde sekunddat",ss:"%d sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta mánnu",MM:"%d mánut",y:"okta jahki",yy:"%d jagit"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7538(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("si",{months:"ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්".split("_"),monthsShort:"ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ".split("_"),weekdays:"ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා".split("_"),weekdaysShort:"ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන".split("_"),weekdaysMin:"ඉ_ස_අ_බ_බ්‍ර_සි_සෙ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"a h:mm",LTS:"a h:mm:ss",L:"YYYY/MM/DD",LL:"YYYY MMMM D",LLL:"YYYY MMMM D, a h:mm",LLLL:"YYYY MMMM D [වැනි] dddd, a h:mm:ss"},calendar:{sameDay:"[අද] LT[ට]",nextDay:"[හෙට] LT[ට]",nextWeek:"dddd LT[ට]",lastDay:"[ඊයේ] LT[ට]",lastWeek:"[පසුගිය] dddd LT[ට]",sameElse:"L"},relativeTime:{future:"%sකින්",past:"%sකට පෙර",s:"තත්පර කිහිපය",ss:"තත්පර %d",m:"මිනිත්තුව",mm:"මිනිත්තු %d",h:"පැය",hh:"පැය %d",d:"දිනය",dd:"දින %d",M:"මාසය",MM:"මාස %d",y:"වසර",yy:"වසර %d"},dayOfMonthOrdinalParse:/\d{1,2} වැනි/,ordinal:function(e){return e+" වැනි"},meridiemParse:/පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,isPM:function(e){return"ප.ව."===e||"පස් වරු"===e},meridiem:function(e,a,t){return e>11?t?"ප.ව.":"පස් වරු":t?"පෙ.ව.":"පෙර වරු"}})}(t(5093))},5784:function(e,a,t){!function(e){"use strict"; +e.defineLocale("si",{months:"ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්".split("_"),monthsShort:"ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ".split("_"),weekdays:"ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා".split("_"),weekdaysShort:"ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන".split("_"),weekdaysMin:"ඉ_ස_අ_බ_බ්‍ර_සි_සෙ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"a h:mm",LTS:"a h:mm:ss",L:"YYYY/MM/DD",LL:"YYYY MMMM D",LLL:"YYYY MMMM D, a h:mm",LLLL:"YYYY MMMM D [වැනි] dddd, a h:mm:ss"},calendar:{sameDay:"[අද] LT[ට]",nextDay:"[හෙට] LT[ට]",nextWeek:"dddd LT[ට]",lastDay:"[ඊයේ] LT[ට]",lastWeek:"[පසුගිය] dddd LT[ට]",sameElse:"L"},relativeTime:{future:"%sකින්",past:"%sකට පෙර",s:"තත්පර කිහිපය",ss:"තත්පර %d",m:"මිනිත්තුව",mm:"මිනිත්තු %d",h:"පැය",hh:"පැය %d",d:"දිනය",dd:"දින %d",M:"මාසය",MM:"මාස %d",y:"වසර",yy:"වසර %d"},dayOfMonthOrdinalParse:/\d{1,2} වැනි/,ordinal:function(e){return e+" වැනි"},meridiemParse:/පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,isPM:function(e){return"ප.ව."===e||"පස් වරු"===e},meridiem:function(e,a,t){return e>11?t?"ප.ව.":"පස් වරු":t?"පෙ.ව.":"පෙර වරු"}})}(t(5093))},5784(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),t="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");function s(e){return e>1&&e<5}function n(e,a,t,n){var r=e+" ";switch(t){case"s":return a||n?"pár sekúnd":"pár sekundami";case"ss":return a||n?r+(s(e)?"sekundy":"sekúnd"):r+"sekundami";case"m":return a?"minúta":n?"minútu":"minútou";case"mm":return a||n?r+(s(e)?"minúty":"minút"):r+"minútami";case"h":return a?"hodina":n?"hodinu":"hodinou";case"hh":return a||n?r+(s(e)?"hodiny":"hodín"):r+"hodinami";case"d":return a||n?"deň":"dňom";case"dd":return a||n?r+(s(e)?"dni":"dní"):r+"dňami";case"M":return a||n?"mesiac":"mesiacom";case"MM":return a||n?r+(s(e)?"mesiace":"mesiacov"):r+"mesiacmi";case"y":return a||n?"rok":"rokom";case"yy":return a||n?r+(s(e)?"roky":"rokov"):r+"rokmi"}}e.defineLocale("sk",{months:a,monthsShort:t,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:case 4:case 5:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:n,ss:n,m:n,mm:n,h:n,hh:n,d:n,dd:n,M:n,MM:n,y:n,yy:n},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},6637:function(e,a,t){!function(e){"use strict"; +var a="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),t="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");function s(e){return e>1&&e<5}function n(e,a,t,n){var r=e+" ";switch(t){case"s":return a||n?"pár sekúnd":"pár sekundami";case"ss":return a||n?r+(s(e)?"sekundy":"sekúnd"):r+"sekundami";case"m":return a?"minúta":n?"minútu":"minútou";case"mm":return a||n?r+(s(e)?"minúty":"minút"):r+"minútami";case"h":return a?"hodina":n?"hodinu":"hodinou";case"hh":return a||n?r+(s(e)?"hodiny":"hodín"):r+"hodinami";case"d":return a||n?"deň":"dňom";case"dd":return a||n?r+(s(e)?"dni":"dní"):r+"dňami";case"M":return a||n?"mesiac":"mesiacom";case"MM":return a||n?r+(s(e)?"mesiace":"mesiacov"):r+"mesiacmi";case"y":return a||n?"rok":"rokom";case"yy":return a||n?r+(s(e)?"roky":"rokov"):r+"rokmi"}}e.defineLocale("sk",{months:a,monthsShort:t,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:case 4:case 5:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:n,ss:n,m:n,mm:n,h:n,hh:n,d:n,dd:n,M:n,MM:n,y:n,yy:n},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},6637(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n=e+" ";switch(t){case"s":return a||s?"nekaj sekund":"nekaj sekundami";case"ss":return n+=1===e?a?"sekundo":"sekundi":2===e?a||s?"sekundi":"sekundah":e<5?a||s?"sekunde":"sekundah":"sekund";case"m":return a?"ena minuta":"eno minuto";case"mm":return n+=1===e?a?"minuta":"minuto":2===e?a||s?"minuti":"minutama":e<5?a||s?"minute":"minutami":a||s?"minut":"minutami";case"h":return a?"ena ura":"eno uro";case"hh":return n+=1===e?a?"ura":"uro":2===e?a||s?"uri":"urama":e<5?a||s?"ure":"urami":a||s?"ur":"urami";case"d":return a||s?"en dan":"enim dnem";case"dd":return n+=1===e?a||s?"dan":"dnem":2===e?a||s?"dni":"dnevoma":a||s?"dni":"dnevi";case"M":return a||s?"en mesec":"enim mesecem";case"MM":return n+=1===e?a||s?"mesec":"mesecem":2===e?a||s?"meseca":"mesecema":e<5?a||s?"mesece":"meseci":a||s?"mesecev":"meseci";case"y":return a||s?"eno leto":"enim letom";case"yy":return n+=1===e?a||s?"leto":"letom":2===e?a||s?"leti":"letoma":e<5?a||s?"leta":"leti":a||s?"let":"leti"}}e.defineLocale("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},6794:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n=e+" ";switch(t){case"s":return a||s?"nekaj sekund":"nekaj sekundami";case"ss":return n+=1===e?a?"sekundo":"sekundi":2===e?a||s?"sekundi":"sekundah":e<5?a||s?"sekunde":"sekundah":"sekund";case"m":return a?"ena minuta":"eno minuto";case"mm":return n+=1===e?a?"minuta":"minuto":2===e?a||s?"minuti":"minutama":e<5?a||s?"minute":"minutami":a||s?"minut":"minutami";case"h":return a?"ena ura":"eno uro";case"hh":return n+=1===e?a?"ura":"uro":2===e?a||s?"uri":"urama":e<5?a||s?"ure":"urami":a||s?"ur":"urami";case"d":return a||s?"en dan":"enim dnem";case"dd":return n+=1===e?a||s?"dan":"dnem":2===e?a||s?"dni":"dnevoma":a||s?"dni":"dnevi";case"M":return a||s?"en mesec":"enim mesecem";case"MM":return n+=1===e?a||s?"mesec":"mesecem":2===e?a||s?"meseca":"mesecema":e<5?a||s?"mesece":"meseci":a||s?"mesecev":"meseci";case"y":return a||s?"eno leto":"enim letom";case"yy":return n+=1===e?a||s?"leto":"letom":2===e?a||s?"leti":"letoma":e<5?a||s?"leta":"leti":a||s?"let":"leti"}}e.defineLocale("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},6794(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(e){return"M"===e.charAt(0)},meridiem:function(e,a,t){return e<12?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Nesër në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s më parë",s:"disa sekonda",ss:"%d sekonda",m:"një minutë",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},3322:function(e,a,t){!function(e){"use strict"; +e.defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(e){return"M"===e.charAt(0)},meridiem:function(e,a,t){return e<12?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Nesër në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s më parë",s:"disa sekonda",ss:"%d sekonda",m:"një minutë",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},3322(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={words:{ss:["секунда","секунде","секунди"],m:["један минут","једног минута"],mm:["минут","минута","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],d:["један дан","једног дана"],dd:["дан","дана","дана"],M:["један месец","једног месеца"],MM:["месец","месеца","месеци"],y:["једну годину","једне године"],yy:["годину","године","година"]},correctGrammaticalCase:function(e,a){return e%10>=1&&e%10<=4&&(e%100<10||e%100>=20)?e%10==1?a[0]:a[1]:a[2]},translate:function(e,t,s,n){var r,i=a.words[s];return 1===s.length?"y"===s&&t?"једна година":n||t?i[0]:i[1]:(r=a.correctGrammaticalCase(e,i),"yy"===s&&t&&"годину"===r?e+" година":e+" "+r)}};e.defineLocale("sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D. M. YYYY.",LL:"D. MMMM YYYY.",LLL:"D. MMMM YYYY. H:mm",LLLL:"dddd, D. MMMM YYYY. H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){return["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:a.translate,dd:a.translate,M:a.translate,MM:a.translate,y:a.translate,yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},5719:function(e,a,t){!function(e){"use strict"; +var a={words:{ss:["секунда","секунде","секунди"],m:["један минут","једног минута"],mm:["минут","минута","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],d:["један дан","једног дана"],dd:["дан","дана","дана"],M:["један месец","једног месеца"],MM:["месец","месеца","месеци"],y:["једну годину","једне године"],yy:["годину","године","година"]},correctGrammaticalCase:function(e,a){return e%10>=1&&e%10<=4&&(e%100<10||e%100>=20)?e%10==1?a[0]:a[1]:a[2]},translate:function(e,t,s,n){var r,d=a.words[s];return 1===s.length?"y"===s&&t?"једна година":n||t?d[0]:d[1]:(r=a.correctGrammaticalCase(e,d),"yy"===s&&t&&"годину"===r?e+" година":e+" "+r)}};e.defineLocale("sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D. M. YYYY.",LL:"D. MMMM YYYY.",LLL:"D. MMMM YYYY. H:mm",LLLL:"dddd, D. MMMM YYYY. H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){return["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:a.translate,dd:a.translate,M:a.translate,MM:a.translate,y:a.translate,yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},5719(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={words:{ss:["sekunda","sekunde","sekundi"],m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],d:["jedan dan","jednog dana"],dd:["dan","dana","dana"],M:["jedan mesec","jednog meseca"],MM:["mesec","meseca","meseci"],y:["jednu godinu","jedne godine"],yy:["godinu","godine","godina"]},correctGrammaticalCase:function(e,a){return e%10>=1&&e%10<=4&&(e%100<10||e%100>=20)?e%10==1?a[0]:a[1]:a[2]},translate:function(e,t,s,n){var r,i=a.words[s];return 1===s.length?"y"===s&&t?"jedna godina":n||t?i[0]:i[1]:(r=a.correctGrammaticalCase(e,i),"yy"===s&&t&&"godinu"===r?e+" godina":e+" "+r)}};e.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D. M. YYYY.",LL:"D. MMMM YYYY.",LLL:"D. MMMM YYYY. H:mm",LLLL:"dddd, D. MMMM YYYY. H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){return["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:a.translate,dd:a.translate,M:a.translate,MM:a.translate,y:a.translate,yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},6e3:function(e,a,t){!function(e){"use strict"; +var a={words:{ss:["sekunda","sekunde","sekundi"],m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],d:["jedan dan","jednog dana"],dd:["dan","dana","dana"],M:["jedan mesec","jednog meseca"],MM:["mesec","meseca","meseci"],y:["jednu godinu","jedne godine"],yy:["godinu","godine","godina"]},correctGrammaticalCase:function(e,a){return e%10>=1&&e%10<=4&&(e%100<10||e%100>=20)?e%10==1?a[0]:a[1]:a[2]},translate:function(e,t,s,n){var r,d=a.words[s];return 1===s.length?"y"===s&&t?"jedna godina":n||t?d[0]:d[1]:(r=a.correctGrammaticalCase(e,d),"yy"===s&&t&&"godinu"===r?e+" godina":e+" "+r)}};e.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D. M. YYYY.",LL:"D. MMMM YYYY.",LLL:"D. MMMM YYYY. H:mm",LLLL:"dddd, D. MMMM YYYY. H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){return["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:a.translate,dd:a.translate,M:a.translate,MM:a.translate,y:a.translate,yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(t(5093))},6e3(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ss",{months:"Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split("_"),monthsShort:"Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo".split("_"),weekdays:"Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo".split("_"),weekdaysShort:"Lis_Umb_Lsb_Les_Lsi_Lsh_Umg".split("_"),weekdaysMin:"Li_Us_Lb_Lt_Ls_Lh_Ug".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Namuhla nga] LT",nextDay:"[Kusasa nga] LT",nextWeek:"dddd [nga] LT",lastDay:"[Itolo nga] LT",lastWeek:"dddd [leliphelile] [nga] LT",sameElse:"L"},relativeTime:{future:"nga %s",past:"wenteka nga %s",s:"emizuzwana lomcane",ss:"%d mzuzwana",m:"umzuzu",mm:"%d emizuzu",h:"lihora",hh:"%d emahora",d:"lilanga",dd:"%d emalanga",M:"inyanga",MM:"%d tinyanga",y:"umnyaka",yy:"%d iminyaka"},meridiemParse:/ekuseni|emini|entsambama|ebusuku/,meridiem:function(e,a,t){return e<11?"ekuseni":e<15?"emini":e<19?"entsambama":"ebusuku"},meridiemHour:function(e,a){return 12===e&&(e=0),"ekuseni"===a?e:"emini"===a?e>=11?e:e+12:"entsambama"===a||"ebusuku"===a?0===e?0:e+12:void 0},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:"%d",week:{dow:1,doy:4}})}(t(5093))},1011:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ss",{months:"Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split("_"),monthsShort:"Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo".split("_"),weekdays:"Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo".split("_"),weekdaysShort:"Lis_Umb_Lsb_Les_Lsi_Lsh_Umg".split("_"),weekdaysMin:"Li_Us_Lb_Lt_Ls_Lh_Ug".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Namuhla nga] LT",nextDay:"[Kusasa nga] LT",nextWeek:"dddd [nga] LT",lastDay:"[Itolo nga] LT",lastWeek:"dddd [leliphelile] [nga] LT",sameElse:"L"},relativeTime:{future:"nga %s",past:"wenteka nga %s",s:"emizuzwana lomcane",ss:"%d mzuzwana",m:"umzuzu",mm:"%d emizuzu",h:"lihora",hh:"%d emahora",d:"lilanga",dd:"%d emalanga",M:"inyanga",MM:"%d tinyanga",y:"umnyaka",yy:"%d iminyaka"},meridiemParse:/ekuseni|emini|entsambama|ebusuku/,meridiem:function(e,a,t){return e<11?"ekuseni":e<15?"emini":e<19?"entsambama":"ebusuku"},meridiemHour:function(e,a){return 12===e&&(e=0),"ekuseni"===a?e:"emini"===a?e>=11?e:e+12:"entsambama"===a||"ebusuku"===a?0===e?0:e+12:void 0},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:"%d",week:{dow:1,doy:4}})}(t(5093))},1011(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",ss:"%d sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}(\:e|\:a)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?":e":1===a||2===a?":a":":e")},week:{dow:1,doy:4}})}(t(5093))},748:function(e,a,t){!function(e){"use strict"; +e.defineLocale("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",ss:"%d sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}(\:e|\:a)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?":e":1===a||2===a?":a":":e")},week:{dow:1,doy:4}})}(t(5093))},748(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("sw",{months:"Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des".split("_"),weekdays:"Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi".split("_"),weekdaysShort:"Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos".split("_"),weekdaysMin:"J2_J3_J4_J5_Al_Ij_J1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"hh:mm A",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[leo saa] LT",nextDay:"[kesho saa] LT",nextWeek:"[wiki ijayo] dddd [saat] LT",lastDay:"[jana] LT",lastWeek:"[wiki iliyopita] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s baadaye",past:"tokea %s",s:"hivi punde",ss:"sekunde %d",m:"dakika moja",mm:"dakika %d",h:"saa limoja",hh:"masaa %d",d:"siku moja",dd:"siku %d",M:"mwezi mmoja",MM:"miezi %d",y:"mwaka mmoja",yy:"miaka %d"},week:{dow:1,doy:7}})}(t(5093))},1025:function(e,a,t){!function(e){"use strict"; +e.defineLocale("sw",{months:"Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des".split("_"),weekdays:"Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi".split("_"),weekdaysShort:"Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos".split("_"),weekdaysMin:"J2_J3_J4_J5_Al_Ij_J1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"hh:mm A",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[leo saa] LT",nextDay:"[kesho saa] LT",nextWeek:"[wiki ijayo] dddd [saat] LT",lastDay:"[jana] LT",lastWeek:"[wiki iliyopita] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s baadaye",past:"tokea %s",s:"hivi punde",ss:"sekunde %d",m:"dakika moja",mm:"dakika %d",h:"saa limoja",hh:"masaa %d",d:"siku moja",dd:"siku %d",M:"mwezi mmoja",MM:"miezi %d",y:"mwaka mmoja",yy:"miaka %d"},week:{dow:1,doy:7}})}(t(5093))},1025(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"௧",2:"௨",3:"௩",4:"௪",5:"௫",6:"௬",7:"௭",8:"௮",9:"௯",0:"௦"},t={"௧":"1","௨":"2","௩":"3","௪":"4","௫":"5","௬":"6","௭":"7","௮":"8","௯":"9","௦":"0"};e.defineLocale("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, HH:mm",LLLL:"dddd, D MMMM YYYY, HH:mm"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",ss:"%d விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},dayOfMonthOrdinalParse:/\d{1,2}வது/,ordinal:function(e){return e+"வது"},preparse:function(e){return e.replace(/[௧௨௩௪௫௬௭௮௯௦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,meridiem:function(e,a,t){return e<2?" யாமம்":e<6?" வைகறை":e<10?" காலை":e<14?" நண்பகல்":e<18?" எற்பாடு":e<22?" மாலை":" யாமம்"},meridiemHour:function(e,a){return 12===e&&(e=0),"யாமம்"===a?e<2?e:e+12:"வைகறை"===a||"காலை"===a||"நண்பகல்"===a&&e>=10?e:e+12},week:{dow:0,doy:6}})}(t(5093))},1885:function(e,a,t){!function(e){"use strict"; +var a={1:"௧",2:"௨",3:"௩",4:"௪",5:"௫",6:"௬",7:"௭",8:"௮",9:"௯",0:"௦"},t={"௧":"1","௨":"2","௩":"3","௪":"4","௫":"5","௬":"6","௭":"7","௮":"8","௯":"9","௦":"0"};e.defineLocale("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, HH:mm",LLLL:"dddd, D MMMM YYYY, HH:mm"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",ss:"%d விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},dayOfMonthOrdinalParse:/\d{1,2}வது/,ordinal:function(e){return e+"வது"},preparse:function(e){return e.replace(/[௧௨௩௪௫௬௭௮௯௦]/g,(function(e){return t[e]}))},postformat:function(e){return e.replace(/\d/g,(function(e){return a[e]}))},meridiemParse:/யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,meridiem:function(e,a,t){return e<2?" யாமம்":e<6?" வைகறை":e<10?" காலை":e<14?" நண்பகல்":e<18?" எற்பாடு":e<22?" மாலை":" யாமம்"},meridiemHour:function(e,a){return 12===e&&(e=0),"யாமம்"===a?e<2?e:e+12:"வைகறை"===a||"காலை"===a||"நண்பகல்"===a&&e>=10?e:e+12},week:{dow:0,doy:6}})}(t(5093))},1885(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("te",{months:"జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జులై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్".split("_"),monthsShort:"జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జులై_ఆగ._సెప్._అక్టో._నవ._డిసె.".split("_"),monthsParseExact:!0,weekdays:"ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం".split("_"),weekdaysShort:"ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని".split("_"),weekdaysMin:"ఆ_సో_మం_బు_గు_శు_శ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[నేడు] LT",nextDay:"[రేపు] LT",nextWeek:"dddd, LT",lastDay:"[నిన్న] LT",lastWeek:"[గత] dddd, LT",sameElse:"L"},relativeTime:{future:"%s లో",past:"%s క్రితం",s:"కొన్ని క్షణాలు",ss:"%d సెకన్లు",m:"ఒక నిమిషం",mm:"%d నిమిషాలు",h:"ఒక గంట",hh:"%d గంటలు",d:"ఒక రోజు",dd:"%d రోజులు",M:"ఒక నెల",MM:"%d నెలలు",y:"ఒక సంవత్సరం",yy:"%d సంవత్సరాలు"},dayOfMonthOrdinalParse:/\d{1,2}వ/,ordinal:"%dవ",meridiemParse:/రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,meridiemHour:function(e,a){return 12===e&&(e=0),"రాత్రి"===a?e<4?e:e+12:"ఉదయం"===a?e:"మధ్యాహ్నం"===a?e>=10?e:e+12:"సాయంత్రం"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"రాత్రి":e<10?"ఉదయం":e<17?"మధ్యాహ్నం":e<20?"సాయంత్రం":"రాత్రి"},week:{dow:0,doy:6}})}(t(5093))},8861:function(e,a,t){!function(e){"use strict"; +e.defineLocale("te",{months:"జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జులై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్".split("_"),monthsShort:"జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జులై_ఆగ._సెప్._అక్టో._నవ._డిసె.".split("_"),monthsParseExact:!0,weekdays:"ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం".split("_"),weekdaysShort:"ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని".split("_"),weekdaysMin:"ఆ_సో_మం_బు_గు_శు_శ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[నేడు] LT",nextDay:"[రేపు] LT",nextWeek:"dddd, LT",lastDay:"[నిన్న] LT",lastWeek:"[గత] dddd, LT",sameElse:"L"},relativeTime:{future:"%s లో",past:"%s క్రితం",s:"కొన్ని క్షణాలు",ss:"%d సెకన్లు",m:"ఒక నిమిషం",mm:"%d నిమిషాలు",h:"ఒక గంట",hh:"%d గంటలు",d:"ఒక రోజు",dd:"%d రోజులు",M:"ఒక నెల",MM:"%d నెలలు",y:"ఒక సంవత్సరం",yy:"%d సంవత్సరాలు"},dayOfMonthOrdinalParse:/\d{1,2}వ/,ordinal:"%dవ",meridiemParse:/రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,meridiemHour:function(e,a){return 12===e&&(e=0),"రాత్రి"===a?e<4?e:e+12:"ఉదయం"===a?e:"మధ్యాహ్నం"===a?e>=10?e:e+12:"సాయంత్రం"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"రాత్రి":e<10?"ఉదయం":e<17?"మధ్యాహ్నం":e<20?"సాయంత్రం":"రాత్రి"},week:{dow:0,doy:6}})}(t(5093))},8861(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("tet",{months:"Janeiru_Fevereiru_Marsu_Abril_Maiu_Juñu_Jullu_Agustu_Setembru_Outubru_Novembru_Dezembru".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingu_Segunda_Tersa_Kuarta_Kinta_Sesta_Sabadu".split("_"),weekdaysShort:"Dom_Seg_Ters_Kua_Kint_Sest_Sab".split("_"),weekdaysMin:"Do_Seg_Te_Ku_Ki_Ses_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Ohin iha] LT",nextDay:"[Aban iha] LT",nextWeek:"dddd [iha] LT",lastDay:"[Horiseik iha] LT",lastWeek:"dddd [semana kotuk] [iha] LT",sameElse:"L"},relativeTime:{future:"iha %s",past:"%s liuba",s:"segundu balun",ss:"segundu %d",m:"minutu ida",mm:"minutu %d",h:"oras ida",hh:"oras %d",d:"loron ida",dd:"loron %d",M:"fulan ida",MM:"fulan %d",y:"tinan ida",yy:"tinan %d"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},6571:function(e,a,t){!function(e){"use strict"; +e.defineLocale("tet",{months:"Janeiru_Fevereiru_Marsu_Abril_Maiu_Juñu_Jullu_Agustu_Setembru_Outubru_Novembru_Dezembru".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingu_Segunda_Tersa_Kuarta_Kinta_Sesta_Sabadu".split("_"),weekdaysShort:"Dom_Seg_Ters_Kua_Kint_Sest_Sab".split("_"),weekdaysMin:"Do_Seg_Te_Ku_Ki_Ses_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Ohin iha] LT",nextDay:"[Aban iha] LT",nextWeek:"dddd [iha] LT",lastDay:"[Horiseik iha] LT",lastWeek:"dddd [semana kotuk] [iha] LT",sameElse:"L"},relativeTime:{future:"iha %s",past:"%s liuba",s:"segundu balun",ss:"segundu %d",m:"minutu ida",mm:"minutu %d",h:"oras ida",hh:"oras %d",d:"loron ida",dd:"loron %d",M:"fulan ida",MM:"fulan %d",y:"tinan ida",yy:"tinan %d"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},6571(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={0:"-ум",1:"-ум",2:"-юм",3:"-юм",4:"-ум",5:"-ум",6:"-ум",7:"-ум",8:"-ум",9:"-ум",10:"-ум",12:"-ум",13:"-ум",20:"-ум",30:"-юм",40:"-ум",50:"-ум",60:"-ум",70:"-ум",80:"-ум",90:"-ум",100:"-ум"};e.defineLocale("tg",{months:{format:"январи_феврали_марти_апрели_майи_июни_июли_августи_сентябри_октябри_ноябри_декабри".split("_"),standalone:"январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр".split("_")},monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"якшанбе_душанбе_сешанбе_чоршанбе_панҷшанбе_ҷумъа_шанбе".split("_"),weekdaysShort:"яшб_дшб_сшб_чшб_пшб_ҷум_шнб".split("_"),weekdaysMin:"яш_дш_сш_чш_пш_ҷм_шб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Имрӯз соати] LT",nextDay:"[Фардо соати] LT",lastDay:"[Дирӯз соати] LT",nextWeek:"dddd[и] [ҳафтаи оянда соати] LT",lastWeek:"dddd[и] [ҳафтаи гузашта соати] LT",sameElse:"L"},relativeTime:{future:"баъди %s",past:"%s пеш",s:"якчанд сония",m:"як дақиқа",mm:"%d дақиқа",h:"як соат",hh:"%d соат",d:"як рӯз",dd:"%d рӯз",M:"як моҳ",MM:"%d моҳ",y:"як сол",yy:"%d сол"},meridiemParse:/шаб|субҳ|рӯз|бегоҳ/,meridiemHour:function(e,a){return 12===e&&(e=0),"шаб"===a?e<4?e:e+12:"субҳ"===a?e:"рӯз"===a?e>=11?e:e+12:"бегоҳ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"шаб":e<11?"субҳ":e<16?"рӯз":e<19?"бегоҳ":"шаб"},dayOfMonthOrdinalParse:/\d{1,2}-(ум|юм)/,ordinal:function(e){var t=e%10,s=e>=100?100:null;return e+(a[e]||a[t]||a[s])},week:{dow:1,doy:7}})}(t(5093))},5802:function(e,a,t){!function(e){"use strict"; +var a={0:"-ум",1:"-ум",2:"-юм",3:"-юм",4:"-ум",5:"-ум",6:"-ум",7:"-ум",8:"-ум",9:"-ум",10:"-ум",12:"-ум",13:"-ум",20:"-ум",30:"-юм",40:"-ум",50:"-ум",60:"-ум",70:"-ум",80:"-ум",90:"-ум",100:"-ум"};e.defineLocale("tg",{months:{format:"январи_феврали_марти_апрели_майи_июни_июли_августи_сентябри_октябри_ноябри_декабри".split("_"),standalone:"январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр".split("_")},monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"якшанбе_душанбе_сешанбе_чоршанбе_панҷшанбе_ҷумъа_шанбе".split("_"),weekdaysShort:"яшб_дшб_сшб_чшб_пшб_ҷум_шнб".split("_"),weekdaysMin:"яш_дш_сш_чш_пш_ҷм_шб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Имрӯз соати] LT",nextDay:"[Фардо соати] LT",lastDay:"[Дирӯз соати] LT",nextWeek:"dddd[и] [ҳафтаи оянда соати] LT",lastWeek:"dddd[и] [ҳафтаи гузашта соати] LT",sameElse:"L"},relativeTime:{future:"баъди %s",past:"%s пеш",s:"якчанд сония",m:"як дақиқа",mm:"%d дақиқа",h:"як соат",hh:"%d соат",d:"як рӯз",dd:"%d рӯз",M:"як моҳ",MM:"%d моҳ",y:"як сол",yy:"%d сол"},meridiemParse:/шаб|субҳ|рӯз|бегоҳ/,meridiemHour:function(e,a){return 12===e&&(e=0),"шаб"===a?e<4?e:e+12:"субҳ"===a?e:"рӯз"===a?e>=11?e:e+12:"бегоҳ"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"шаб":e<11?"субҳ":e<16?"рӯз":e<19?"бегоҳ":"шаб"},dayOfMonthOrdinalParse:/\d{1,2}-(ум|юм)/,ordinal:function(e){var t=e%10,s=e>=100?100:null;return e+(a[e]||a[t]||a[s])},week:{dow:1,doy:7}})}(t(5093))},5802(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H:mm",LLLL:"วันddddที่ D MMMM YYYY เวลา H:mm"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(e){return"หลังเที่ยง"===e},meridiem:function(e,a,t){return e<12?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",ss:"%d วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",w:"1 สัปดาห์",ww:"%d สัปดาห์",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}})}(t(5093))},9527:function(e,a,t){!function(e){"use strict"; +e.defineLocale("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H:mm",LLLL:"วันddddที่ D MMMM YYYY เวลา H:mm"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(e){return"หลังเที่ยง"===e},meridiem:function(e,a,t){return e<12?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",ss:"%d วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",w:"1 สัปดาห์",ww:"%d สัปดาห์",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}})}(t(5093))},9527(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"'inji",5:"'inji",8:"'inji",70:"'inji",80:"'inji",2:"'nji",7:"'nji",20:"'nji",50:"'nji",3:"'ünji",4:"'ünji",100:"'ünji",6:"'njy",9:"'unjy",10:"'unjy",30:"'unjy",60:"'ynjy",90:"'ynjy"};e.defineLocale("tk",{months:"Ýanwar_Fewral_Mart_Aprel_Maý_Iýun_Iýul_Awgust_Sentýabr_Oktýabr_Noýabr_Dekabr".split("_"),monthsShort:"Ýan_Few_Mar_Apr_Maý_Iýn_Iýl_Awg_Sen_Okt_Noý_Dek".split("_"),weekdays:"Ýekşenbe_Duşenbe_Sişenbe_Çarşenbe_Penşenbe_Anna_Şenbe".split("_"),weekdaysShort:"Ýek_Duş_Siş_Çar_Pen_Ann_Şen".split("_"),weekdaysMin:"Ýk_Dş_Sş_Çr_Pn_An_Şn".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün sagat] LT",nextDay:"[ertir sagat] LT",nextWeek:"[indiki] dddd [sagat] LT",lastDay:"[düýn] LT",lastWeek:"[geçen] dddd [sagat] LT",sameElse:"L"},relativeTime:{future:"%s soň",past:"%s öň",s:"birnäçe sekunt",m:"bir minut",mm:"%d minut",h:"bir sagat",hh:"%d sagat",d:"bir gün",dd:"%d gün",M:"bir aý",MM:"%d aý",y:"bir ýyl",yy:"%d ýyl"},ordinal:function(e,t){switch(t){case"d":case"D":case"Do":case"DD":return e;default:if(0===e)return e+"'unjy";var s=e%10,n=e%100-s,r=e>=100?100:null;return e+(a[s]||a[n]||a[r])}},week:{dow:1,doy:7}})}(t(5093))},9231:function(e,a,t){!function(e){"use strict"; +var a={1:"'inji",5:"'inji",8:"'inji",70:"'inji",80:"'inji",2:"'nji",7:"'nji",20:"'nji",50:"'nji",3:"'ünji",4:"'ünji",100:"'ünji",6:"'njy",9:"'unjy",10:"'unjy",30:"'unjy",60:"'ynjy",90:"'ynjy"};e.defineLocale("tk",{months:"Ýanwar_Fewral_Mart_Aprel_Maý_Iýun_Iýul_Awgust_Sentýabr_Oktýabr_Noýabr_Dekabr".split("_"),monthsShort:"Ýan_Few_Mar_Apr_Maý_Iýn_Iýl_Awg_Sen_Okt_Noý_Dek".split("_"),weekdays:"Ýekşenbe_Duşenbe_Sişenbe_Çarşenbe_Penşenbe_Anna_Şenbe".split("_"),weekdaysShort:"Ýek_Duş_Siş_Çar_Pen_Ann_Şen".split("_"),weekdaysMin:"Ýk_Dş_Sş_Çr_Pn_An_Şn".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün sagat] LT",nextDay:"[ertir sagat] LT",nextWeek:"[indiki] dddd [sagat] LT",lastDay:"[düýn] LT",lastWeek:"[geçen] dddd [sagat] LT",sameElse:"L"},relativeTime:{future:"%s soň",past:"%s öň",s:"birnäçe sekunt",m:"bir minut",mm:"%d minut",h:"bir sagat",hh:"%d sagat",d:"bir gün",dd:"%d gün",M:"bir aý",MM:"%d aý",y:"bir ýyl",yy:"%d ýyl"},ordinal:function(e,t){switch(t){case"d":case"D":case"Do":case"DD":return e;default:if(0===e)return e+"'unjy";var s=e%10,n=e%100-s,r=e>=100?100:null;return e+(a[s]||a[n]||a[r])}},week:{dow:1,doy:7}})}(t(5093))},9231(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"LT [ngayong araw]",nextDay:"[Bukas ng] LT",nextWeek:"LT [sa susunod na] dddd",lastDay:"LT [kahapon]",lastWeek:"LT [noong nakaraang] dddd",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",ss:"%d segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})}(t(5093))},1052:function(e,a,t){!function(e){"use strict"; +e.defineLocale("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"LT [ngayong araw]",nextDay:"[Bukas ng] LT",nextWeek:"LT [sa susunod na] dddd",lastDay:"LT [kahapon]",lastWeek:"LT [noong nakaraang] dddd",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",ss:"%d segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})}(t(5093))},1052(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a="pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut".split("_");function t(e){var a=e;return a=-1!==e.indexOf("jaj")?a.slice(0,-3)+"leS":-1!==e.indexOf("jar")?a.slice(0,-3)+"waQ":-1!==e.indexOf("DIS")?a.slice(0,-3)+"nem":a+" pIq"}function s(e){var a=e;return a=-1!==e.indexOf("jaj")?a.slice(0,-3)+"Hu’":-1!==e.indexOf("jar")?a.slice(0,-3)+"wen":-1!==e.indexOf("DIS")?a.slice(0,-3)+"ben":a+" ret"}function n(e,a,t,s){var n=r(e);switch(t){case"ss":return n+" lup";case"mm":return n+" tup";case"hh":return n+" rep";case"dd":return n+" jaj";case"MM":return n+" jar";case"yy":return n+" DIS"}}function r(e){var t=Math.floor(e%1e3/100),s=Math.floor(e%100/10),n=e%10,r="";return t>0&&(r+=a[t]+"vatlh"),s>0&&(r+=(""!==r?" ":"")+a[s]+"maH"),n>0&&(r+=(""!==r?" ":"")+a[n]),""===r?"pagh":r}e.defineLocale("tlh",{months:"tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’".split("_"),monthsShort:"jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’".split("_"),monthsParseExact:!0,weekdays:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysShort:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysMin:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[DaHjaj] LT",nextDay:"[wa’leS] LT",nextWeek:"LLL",lastDay:"[wa’Hu’] LT",lastWeek:"LLL",sameElse:"L"},relativeTime:{future:t,past:s,s:"puS lup",ss:n,m:"wa’ tup",mm:n,h:"wa’ rep",hh:n,d:"wa’ jaj",dd:n,M:"wa’ jar",MM:n,y:"wa’ DIS",yy:n},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},5096:function(e,a,t){!function(e){"use strict"; +var a="pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut".split("_");function t(e){var a=e;return a=-1!==e.indexOf("jaj")?a.slice(0,-3)+"leS":-1!==e.indexOf("jar")?a.slice(0,-3)+"waQ":-1!==e.indexOf("DIS")?a.slice(0,-3)+"nem":a+" pIq"}function s(e){var a=e;return a=-1!==e.indexOf("jaj")?a.slice(0,-3)+"Hu’":-1!==e.indexOf("jar")?a.slice(0,-3)+"wen":-1!==e.indexOf("DIS")?a.slice(0,-3)+"ben":a+" ret"}function n(e,a,t,s){var n=r(e);switch(t){case"ss":return n+" lup";case"mm":return n+" tup";case"hh":return n+" rep";case"dd":return n+" jaj";case"MM":return n+" jar";case"yy":return n+" DIS"}}function r(e){var t=Math.floor(e%1e3/100),s=Math.floor(e%100/10),n=e%10,r="";return t>0&&(r+=a[t]+"vatlh"),s>0&&(r+=(""!==r?" ":"")+a[s]+"maH"),n>0&&(r+=(""!==r?" ":"")+a[n]),""===r?"pagh":r}e.defineLocale("tlh",{months:"tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’".split("_"),monthsShort:"jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’".split("_"),monthsParseExact:!0,weekdays:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysShort:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysMin:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[DaHjaj] LT",nextDay:"[wa’leS] LT",nextWeek:"LLL",lastDay:"[wa’Hu’] LT",lastWeek:"LLL",sameElse:"L"},relativeTime:{future:t,past:s,s:"puS lup",ss:n,m:"wa’ tup",mm:n,h:"wa’ rep",hh:n,d:"wa’ jaj",dd:n,M:"wa’ jar",MM:n,y:"wa’ DIS",yy:n},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},5096(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"};e.defineLocale("tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pzt_Sal_Çar_Per_Cum_Cmt".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),meridiem:function(e,a,t){return e<12?t?"öö":"ÖÖ":t?"ös":"ÖS"},meridiemParse:/öö|ÖÖ|ös|ÖS/,isPM:function(e){return"ös"===e||"ÖS"===e},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[gelecek] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",ss:"%d saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",w:"bir hafta",ww:"%d hafta",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinal:function(e,t){switch(t){case"d":case"D":case"Do":case"DD":return e;default:if(0===e)return e+"'ıncı";var s=e%10,n=e%100-s,r=e>=100?100:null;return e+(a[s]||a[n]||a[r])}},week:{dow:1,doy:7}})}(t(5093))},9846:function(e,a,t){!function(e){"use strict"; +var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"};e.defineLocale("tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pzt_Sal_Çar_Per_Cum_Cmt".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),meridiem:function(e,a,t){return e<12?t?"öö":"ÖÖ":t?"ös":"ÖS"},meridiemParse:/öö|ÖÖ|ös|ÖS/,isPM:function(e){return"ös"===e||"ÖS"===e},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[gelecek] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",ss:"%d saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",w:"bir hafta",ww:"%d hafta",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinal:function(e,t){switch(t){case"d":case"D":case"Do":case"DD":return e;default:if(0===e)return e+"'ıncı";var s=e%10,n=e%100-s,r=e>=100?100:null;return e+(a[s]||a[n]||a[r])}},week:{dow:1,doy:7}})}(t(5093))},9846(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a,t,s){var n={s:["viensas secunds","'iensas secunds"],ss:[e+" secunds",e+" secunds"],m:["'n míut","'iens míut"],mm:[e+" míuts",e+" míuts"],h:["'n þora","'iensa þora"],hh:[e+" þoras",e+" þoras"],d:["'n ziua","'iensa ziua"],dd:[e+" ziuas",e+" ziuas"],M:["'n mes","'iens mes"],MM:[e+" mesen",e+" mesen"],y:["'n ar","'iens ar"],yy:[e+" ars",e+" ars"]};return s||a?n[t][0]:n[t][1]}e.defineLocale("tzl",{months:"Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar".split("_"),monthsShort:"Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec".split("_"),weekdays:"Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi".split("_"),weekdaysShort:"Súl_Lún_Mai_Már_Xhú_Vié_Sát".split("_"),weekdaysMin:"Sú_Lú_Ma_Má_Xh_Vi_Sá".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"D. MMMM [dallas] YYYY",LLL:"D. MMMM [dallas] YYYY HH.mm",LLLL:"dddd, [li] D. MMMM [dallas] YYYY HH.mm"},meridiemParse:/d\'o|d\'a/i,isPM:function(e){return"d'o"===e.toLowerCase()},meridiem:function(e,a,t){return e>11?t?"d'o":"D'O":t?"d'a":"D'A"},calendar:{sameDay:"[oxhi à] LT",nextDay:"[demà à] LT",nextWeek:"dddd [à] LT",lastDay:"[ieiri à] LT",lastWeek:"[sür el] dddd [lasteu à] LT",sameElse:"L"},relativeTime:{future:"osprei %s",past:"ja%s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7711:function(e,a,t){!function(e){"use strict"; +function a(e,a,t,s){var n={s:["viensas secunds","'iensas secunds"],ss:[e+" secunds",e+" secunds"],m:["'n míut","'iens míut"],mm:[e+" míuts",e+" míuts"],h:["'n þora","'iensa þora"],hh:[e+" þoras",e+" þoras"],d:["'n ziua","'iensa ziua"],dd:[e+" ziuas",e+" ziuas"],M:["'n mes","'iens mes"],MM:[e+" mesen",e+" mesen"],y:["'n ar","'iens ar"],yy:[e+" ars",e+" ars"]};return s||a?n[t][0]:n[t][1]}e.defineLocale("tzl",{months:"Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar".split("_"),monthsShort:"Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec".split("_"),weekdays:"Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi".split("_"),weekdaysShort:"Súl_Lún_Mai_Már_Xhú_Vié_Sát".split("_"),weekdaysMin:"Sú_Lú_Ma_Má_Xh_Vi_Sá".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"D. MMMM [dallas] YYYY",LLL:"D. MMMM [dallas] YYYY HH.mm",LLLL:"dddd, [li] D. MMMM [dallas] YYYY HH.mm"},meridiemParse:/d\'o|d\'a/i,isPM:function(e){return"d'o"===e.toLowerCase()},meridiem:function(e,a,t){return e>11?t?"d'o":"D'O":t?"d'a":"D'A"},calendar:{sameDay:"[oxhi à] LT",nextDay:"[demà à] LT",nextWeek:"dddd [à] LT",lastDay:"[ieiri à] LT",lastWeek:"[sür el] dddd [lasteu à] LT",sameElse:"L"},relativeTime:{future:"osprei %s",past:"ja%s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(t(5093))},7711(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("tzm-latn",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",ss:"%d imik",m:"minuḍ",mm:"%d minuḍ",h:"saɛa",hh:"%d tassaɛin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}(t(5093))},1765:function(e,a,t){!function(e){"use strict"; +e.defineLocale("tzm-latn",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",ss:"%d imik",m:"minuḍ",mm:"%d minuḍ",h:"saɛa",hh:"%d tassaɛin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}(t(5093))},1765(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("tzm",{months:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),monthsShort:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),weekdays:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysShort:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysMin:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ⴰⵙⴷⵅ ⴴ] LT",nextDay:"[ⴰⵙⴽⴰ ⴴ] LT",nextWeek:"dddd [ⴴ] LT",lastDay:"[ⴰⵚⴰⵏⵜ ⴴ] LT",lastWeek:"dddd [ⴴ] LT",sameElse:"L"},relativeTime:{future:"ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",past:"ⵢⴰⵏ %s",s:"ⵉⵎⵉⴽ",ss:"%d ⵉⵎⵉⴽ",m:"ⵎⵉⵏⵓⴺ",mm:"%d ⵎⵉⵏⵓⴺ",h:"ⵙⴰⵄⴰ",hh:"%d ⵜⴰⵙⵙⴰⵄⵉⵏ",d:"ⴰⵙⵙ",dd:"%d oⵙⵙⴰⵏ",M:"ⴰⵢoⵓⵔ",MM:"%d ⵉⵢⵢⵉⵔⵏ",y:"ⴰⵙⴳⴰⵙ",yy:"%d ⵉⵙⴳⴰⵙⵏ"},week:{dow:6,doy:12}})}(t(5093))},8414:function(e,a,t){!function(e){"use strict"; +e.defineLocale("tzm",{months:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),monthsShort:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),weekdays:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysShort:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysMin:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ⴰⵙⴷⵅ ⴴ] LT",nextDay:"[ⴰⵙⴽⴰ ⴴ] LT",nextWeek:"dddd [ⴴ] LT",lastDay:"[ⴰⵚⴰⵏⵜ ⴴ] LT",lastWeek:"dddd [ⴴ] LT",sameElse:"L"},relativeTime:{future:"ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",past:"ⵢⴰⵏ %s",s:"ⵉⵎⵉⴽ",ss:"%d ⵉⵎⵉⴽ",m:"ⵎⵉⵏⵓⴺ",mm:"%d ⵎⵉⵏⵓⴺ",h:"ⵙⴰⵄⴰ",hh:"%d ⵜⴰⵙⵙⴰⵄⵉⵏ",d:"ⴰⵙⵙ",dd:"%d oⵙⵙⴰⵏ",M:"ⴰⵢoⵓⵔ",MM:"%d ⵉⵢⵢⵉⵔⵏ",y:"ⴰⵙⴳⴰⵙ",yy:"%d ⵉⵙⴳⴰⵙⵏ"},week:{dow:6,doy:12}})}(t(5093))},8414(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("ug-cn",{months:"يانۋار_فېۋرال_مارت_ئاپرېل_ماي_ئىيۇن_ئىيۇل_ئاۋغۇست_سېنتەبىر_ئۆكتەبىر_نويابىر_دېكابىر".split("_"),monthsShort:"يانۋار_فېۋرال_مارت_ئاپرېل_ماي_ئىيۇن_ئىيۇل_ئاۋغۇست_سېنتەبىر_ئۆكتەبىر_نويابىر_دېكابىر".split("_"),weekdays:"يەكشەنبە_دۈشەنبە_سەيشەنبە_چارشەنبە_پەيشەنبە_جۈمە_شەنبە".split("_"),weekdaysShort:"يە_دۈ_سە_چا_پە_جۈ_شە".split("_"),weekdaysMin:"يە_دۈ_سە_چا_پە_جۈ_شە".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY-يىلىM-ئاينىڭD-كۈنى",LLL:"YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm",LLLL:"dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm"},meridiemParse:/يېرىم كېچە|سەھەر|چۈشتىن بۇرۇن|چۈش|چۈشتىن كېيىن|كەچ/,meridiemHour:function(e,a){return 12===e&&(e=0),"يېرىم كېچە"===a||"سەھەر"===a||"چۈشتىن بۇرۇن"===a?e:"چۈشتىن كېيىن"===a||"كەچ"===a?e+12:e>=11?e:e+12},meridiem:function(e,a,t){var s=100*e+a;return s<600?"يېرىم كېچە":s<900?"سەھەر":s<1130?"چۈشتىن بۇرۇن":s<1230?"چۈش":s<1800?"چۈشتىن كېيىن":"كەچ"},calendar:{sameDay:"[بۈگۈن سائەت] LT",nextDay:"[ئەتە سائەت] LT",nextWeek:"[كېلەركى] dddd [سائەت] LT",lastDay:"[تۆنۈگۈن] LT",lastWeek:"[ئالدىنقى] dddd [سائەت] LT",sameElse:"L"},relativeTime:{future:"%s كېيىن",past:"%s بۇرۇن",s:"نەچچە سېكونت",ss:"%d سېكونت",m:"بىر مىنۇت",mm:"%d مىنۇت",h:"بىر سائەت",hh:"%d سائەت",d:"بىر كۈن",dd:"%d كۈن",M:"بىر ئاي",MM:"%d ئاي",y:"بىر يىل",yy:"%d يىل"},dayOfMonthOrdinalParse:/\d{1,2}(-كۈنى|-ئاي|-ھەپتە)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"-كۈنى";case"w":case"W":return e+"-ھەپتە";default:return e}},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:1,doy:7}})}(t(5093))},6618:function(e,a,t){!function(e){"use strict"; +e.defineLocale("ug-cn",{months:"يانۋار_فېۋرال_مارت_ئاپرېل_ماي_ئىيۇن_ئىيۇل_ئاۋغۇست_سېنتەبىر_ئۆكتەبىر_نويابىر_دېكابىر".split("_"),monthsShort:"يانۋار_فېۋرال_مارت_ئاپرېل_ماي_ئىيۇن_ئىيۇل_ئاۋغۇست_سېنتەبىر_ئۆكتەبىر_نويابىر_دېكابىر".split("_"),weekdays:"يەكشەنبە_دۈشەنبە_سەيشەنبە_چارشەنبە_پەيشەنبە_جۈمە_شەنبە".split("_"),weekdaysShort:"يە_دۈ_سە_چا_پە_جۈ_شە".split("_"),weekdaysMin:"يە_دۈ_سە_چا_پە_جۈ_شە".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY-يىلىM-ئاينىڭD-كۈنى",LLL:"YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm",LLLL:"dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm"},meridiemParse:/يېرىم كېچە|سەھەر|چۈشتىن بۇرۇن|چۈش|چۈشتىن كېيىن|كەچ/,meridiemHour:function(e,a){return 12===e&&(e=0),"يېرىم كېچە"===a||"سەھەر"===a||"چۈشتىن بۇرۇن"===a?e:"چۈشتىن كېيىن"===a||"كەچ"===a?e+12:e>=11?e:e+12},meridiem:function(e,a,t){var s=100*e+a;return s<600?"يېرىم كېچە":s<900?"سەھەر":s<1130?"چۈشتىن بۇرۇن":s<1230?"چۈش":s<1800?"چۈشتىن كېيىن":"كەچ"},calendar:{sameDay:"[بۈگۈن سائەت] LT",nextDay:"[ئەتە سائەت] LT",nextWeek:"[كېلەركى] dddd [سائەت] LT",lastDay:"[تۆنۈگۈن] LT",lastWeek:"[ئالدىنقى] dddd [سائەت] LT",sameElse:"L"},relativeTime:{future:"%s كېيىن",past:"%s بۇرۇن",s:"نەچچە سېكونت",ss:"%d سېكونت",m:"بىر مىنۇت",mm:"%d مىنۇت",h:"بىر سائەت",hh:"%d سائەت",d:"بىر كۈن",dd:"%d كۈن",M:"بىر ئاي",MM:"%d ئاي",y:"بىر يىل",yy:"%d يىل"},dayOfMonthOrdinalParse:/\d{1,2}(-كۈنى|-ئاي|-ھەپتە)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"-كۈنى";case"w":case"W":return e+"-ھەپتە";default:return e}},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:1,doy:7}})}(t(5093))},6618(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,s){return"m"===s?t?"хвилина":"хвилину":"h"===s?t?"година":"годину":e+" "+a({ss:t?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:t?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:t?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"}[s],+e)}function s(e,a){var t={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===e?t.nominative.slice(1,7).concat(t.nominative.slice(0,1)):e?t[/(\[[ВвУу]\]) ?dddd/.test(a)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(a)?"genitive":"nominative"][e.day()]:t.nominative}function n(e){return function(){return e+"о"+(11===this.hours()?"б":"")+"] LT"}}e.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:s,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:n("[Сьогодні "),nextDay:n("[Завтра "),lastDay:n("[Вчора "),nextWeek:n("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return n("[Минулої] dddd [").call(this);case 1:case 2:case 4:return n("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:t,m:t,mm:t,h:"годину",hh:t,d:"день",dd:t,M:"місяць",MM:t,y:"рік",yy:t},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(e){return/^(дня|вечора)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночі":e<12?"ранку":e<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":case"w":case"W":return e+"-й";case"D":return e+"-го";default:return e}},week:{dow:1,doy:7}})}(t(5093))},158:function(e,a,t){!function(e){"use strict"; +function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,s){return"m"===s?t?"хвилина":"хвилину":"h"===s?t?"година":"годину":e+" "+a({ss:t?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:t?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:t?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"}[s],+e)}function s(e,a){var t={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===e?t.nominative.slice(1,7).concat(t.nominative.slice(0,1)):e?t[/(\[[ВвУу]\]) ?dddd/.test(a)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(a)?"genitive":"nominative"][e.day()]:t.nominative}function n(e){return function(){return e+"о"+(11===this.hours()?"б":"")+"] LT"}}e.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:s,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:n("[Сьогодні "),nextDay:n("[Завтра "),lastDay:n("[Вчора "),nextWeek:n("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return n("[Минулої] dddd [").call(this);case 1:case 2:case 4:return n("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:t,m:t,mm:t,h:"годину",hh:t,d:"день",dd:t,M:"місяць",MM:t,y:"рік",yy:t},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(e){return/^(дня|вечора)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночі":e<12?"ранку":e<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":case"w":case"W":return e+"-й";case"D":return e+"-го";default:return e}},week:{dow:1,doy:7}})}(t(5093))},158(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -var a=["جنوری","فروری","مارچ","اپریل","مئی","جون","جولائی","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],t=["اتوار","پیر","منگل","بدھ","جمعرات","جمعہ","ہفتہ"];e.defineLocale("ur",{months:a,monthsShort:a,weekdays:t,weekdaysShort:t,weekdaysMin:t,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd، D MMMM YYYY HH:mm"},meridiemParse:/صبح|شام/,isPM:function(e){return"شام"===e},meridiem:function(e,a,t){return e<12?"صبح":"شام"},calendar:{sameDay:"[آج بوقت] LT",nextDay:"[کل بوقت] LT",nextWeek:"dddd [بوقت] LT",lastDay:"[گذشتہ روز بوقت] LT",lastWeek:"[گذشتہ] dddd [بوقت] LT",sameElse:"L"},relativeTime:{future:"%s بعد",past:"%s قبل",s:"چند سیکنڈ",ss:"%d سیکنڈ",m:"ایک منٹ",mm:"%d منٹ",h:"ایک گھنٹہ",hh:"%d گھنٹے",d:"ایک دن",dd:"%d دن",M:"ایک ماہ",MM:"%d ماہ",y:"ایک سال",yy:"%d سال"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:1,doy:4}})}(t(5093))},2475:function(e,a,t){!function(e){"use strict"; +var a=["جنوری","فروری","مارچ","اپریل","مئی","جون","جولائی","اگست","ستمبر","اکتوبر","نومبر","دسمبر"],t=["اتوار","پیر","منگل","بدھ","جمعرات","جمعہ","ہفتہ"];e.defineLocale("ur",{months:a,monthsShort:a,weekdays:t,weekdaysShort:t,weekdaysMin:t,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd، D MMMM YYYY HH:mm"},meridiemParse:/صبح|شام/,isPM:function(e){return"شام"===e},meridiem:function(e,a,t){return e<12?"صبح":"شام"},calendar:{sameDay:"[آج بوقت] LT",nextDay:"[کل بوقت] LT",nextWeek:"dddd [بوقت] LT",lastDay:"[گذشتہ روز بوقت] LT",lastWeek:"[گذشتہ] dddd [بوقت] LT",sameElse:"L"},relativeTime:{future:"%s بعد",past:"%s قبل",s:"چند سیکنڈ",ss:"%d سیکنڈ",m:"ایک منٹ",mm:"%d منٹ",h:"ایک گھنٹہ",hh:"%d گھنٹے",d:"ایک دن",dd:"%d دن",M:"ایک ماہ",MM:"%d ماہ",y:"ایک سال",yy:"%d سال"},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/,/g,"،")},week:{dow:1,doy:4}})}(t(5093))},2475(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("uz-latn",{months:"Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr".split("_"),monthsShort:"Yan_Fev_Mar_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek".split("_"),weekdays:"Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba".split("_"),weekdaysShort:"Yak_Dush_Sesh_Chor_Pay_Jum_Shan".split("_"),weekdaysMin:"Ya_Du_Se_Cho_Pa_Ju_Sha".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Bugun soat] LT [da]",nextDay:"[Ertaga] LT [da]",nextWeek:"dddd [kuni soat] LT [da]",lastDay:"[Kecha soat] LT [da]",lastWeek:"[O'tgan] dddd [kuni soat] LT [da]",sameElse:"L"},relativeTime:{future:"Yaqin %s ichida",past:"Bir necha %s oldin",s:"soniya",ss:"%d soniya",m:"bir daqiqa",mm:"%d daqiqa",h:"bir soat",hh:"%d soat",d:"bir kun",dd:"%d kun",M:"bir oy",MM:"%d oy",y:"bir yil",yy:"%d yil"},week:{dow:1,doy:7}})}(t(5093))},7609:function(e,a,t){!function(e){"use strict"; +e.defineLocale("uz-latn",{months:"Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr".split("_"),monthsShort:"Yan_Fev_Mar_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek".split("_"),weekdays:"Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba".split("_"),weekdaysShort:"Yak_Dush_Sesh_Chor_Pay_Jum_Shan".split("_"),weekdaysMin:"Ya_Du_Se_Cho_Pa_Ju_Sha".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Bugun soat] LT [da]",nextDay:"[Ertaga] LT [da]",nextWeek:"dddd [kuni soat] LT [da]",lastDay:"[Kecha soat] LT [da]",lastWeek:"[O'tgan] dddd [kuni soat] LT [da]",sameElse:"L"},relativeTime:{future:"Yaqin %s ichida",past:"Bir necha %s oldin",s:"soniya",ss:"%d soniya",m:"bir daqiqa",mm:"%d daqiqa",h:"bir soat",hh:"%d soat",d:"bir kun",dd:"%d kun",M:"bir oy",MM:"%d oy",y:"bir yil",yy:"%d yil"},week:{dow:1,doy:7}})}(t(5093))},7609(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("uz",{months:"январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр".split("_"),monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),weekdaysShort:"Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),weekdaysMin:"Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Бугун соат] LT [да]",nextDay:"[Эртага] LT [да]",nextWeek:"dddd [куни соат] LT [да]",lastDay:"[Кеча соат] LT [да]",lastWeek:"[Утган] dddd [куни соат] LT [да]",sameElse:"L"},relativeTime:{future:"Якин %s ичида",past:"Бир неча %s олдин",s:"фурсат",ss:"%d фурсат",m:"бир дакика",mm:"%d дакика",h:"бир соат",hh:"%d соат",d:"бир кун",dd:"%d кун",M:"бир ой",MM:"%d ой",y:"бир йил",yy:"%d йил"},week:{dow:1,doy:7}})}(t(5093))},1135:function(e,a,t){!function(e){"use strict"; +e.defineLocale("uz",{months:"январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр".split("_"),monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),weekdaysShort:"Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),weekdaysMin:"Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Бугун соат] LT [да]",nextDay:"[Эртага] LT [да]",nextWeek:"dddd [куни соат] LT [да]",lastDay:"[Кеча соат] LT [да]",lastWeek:"[Утган] dddd [куни соат] LT [да]",sameElse:"L"},relativeTime:{future:"Якин %s ичида",past:"Бир неча %s олдин",s:"фурсат",ss:"%d фурсат",m:"бир дакика",mm:"%d дакика",h:"бир соат",hh:"%d соат",d:"бир кун",dd:"%d кун",M:"бир ой",MM:"%d ой",y:"бир йил",yy:"%d йил"},week:{dow:1,doy:7}})}(t(5093))},1135(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Thg 01_Thg 02_Thg 03_Thg 04_Thg 05_Thg 06_Thg 07_Thg 08_Thg 09_Thg 10_Thg 11_Thg 12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(e){return/^ch$/i.test(e)},meridiem:function(e,a,t){return e<12?t?"sa":"SA":t?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần trước lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",ss:"%d giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",w:"một tuần",ww:"%d tuần",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})}(t(5093))},4051:function(e,a,t){!function(e){"use strict"; +e.defineLocale("vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Thg 01_Thg 02_Thg 03_Thg 04_Thg 05_Thg 06_Thg 07_Thg 08_Thg 09_Thg 10_Thg 11_Thg 12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(e){return/^ch$/i.test(e)},meridiem:function(e,a,t){return e<12?t?"sa":"SA":t?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần trước lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",ss:"%d giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",w:"một tuần",ww:"%d tuần",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})}(t(5093))},4051(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",ss:"%d s~écóñ~ds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},2218:function(e,a,t){!function(e){"use strict"; +e.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",ss:"%d s~écóñ~ds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})}(t(5093))},2218(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("yo",{months:"Sẹ́rẹ́_Èrèlè_Ẹrẹ̀nà_Ìgbé_Èbibi_Òkùdu_Agẹmo_Ògún_Owewe_Ọ̀wàrà_Bélú_Ọ̀pẹ̀̀".split("_"),monthsShort:"Sẹ́r_Èrl_Ẹrn_Ìgb_Èbi_Òkù_Agẹ_Ògú_Owe_Ọ̀wà_Bél_Ọ̀pẹ̀̀".split("_"),weekdays:"Àìkú_Ajé_Ìsẹ́gun_Ọjọ́rú_Ọjọ́bọ_Ẹtì_Àbámẹ́ta".split("_"),weekdaysShort:"Àìk_Ajé_Ìsẹ́_Ọjr_Ọjb_Ẹtì_Àbá".split("_"),weekdaysMin:"Àì_Aj_Ìs_Ọr_Ọb_Ẹt_Àb".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Ònì ni] LT",nextDay:"[Ọ̀la ni] LT",nextWeek:"dddd [Ọsẹ̀ tón'bọ] [ni] LT",lastDay:"[Àna ni] LT",lastWeek:"dddd [Ọsẹ̀ tólọ́] [ni] LT",sameElse:"L"},relativeTime:{future:"ní %s",past:"%s kọjá",s:"ìsẹjú aayá die",ss:"aayá %d",m:"ìsẹjú kan",mm:"ìsẹjú %d",h:"wákati kan",hh:"wákati %d",d:"ọjọ́ kan",dd:"ọjọ́ %d",M:"osù kan",MM:"osù %d",y:"ọdún kan",yy:"ọdún %d"},dayOfMonthOrdinalParse:/ọjọ́\s\d{1,2}/,ordinal:"ọjọ́ %d",week:{dow:1,doy:4}})}(t(5093))},2648:function(e,a,t){!function(e){"use strict"; +e.defineLocale("yo",{months:"Sẹ́rẹ́_Èrèlè_Ẹrẹ̀nà_Ìgbé_Èbibi_Òkùdu_Agẹmo_Ògún_Owewe_Ọ̀wàrà_Bélú_Ọ̀pẹ̀̀".split("_"),monthsShort:"Sẹ́r_Èrl_Ẹrn_Ìgb_Èbi_Òkù_Agẹ_Ògú_Owe_Ọ̀wà_Bél_Ọ̀pẹ̀̀".split("_"),weekdays:"Àìkú_Ajé_Ìsẹ́gun_Ọjọ́rú_Ọjọ́bọ_Ẹtì_Àbámẹ́ta".split("_"),weekdaysShort:"Àìk_Ajé_Ìsẹ́_Ọjr_Ọjb_Ẹtì_Àbá".split("_"),weekdaysMin:"Àì_Aj_Ìs_Ọr_Ọb_Ẹt_Àb".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Ònì ni] LT",nextDay:"[Ọ̀la ni] LT",nextWeek:"dddd [Ọsẹ̀ tón'bọ] [ni] LT",lastDay:"[Àna ni] LT",lastWeek:"dddd [Ọsẹ̀ tólọ́] [ni] LT",sameElse:"L"},relativeTime:{future:"ní %s",past:"%s kọjá",s:"ìsẹjú aayá die",ss:"aayá %d",m:"ìsẹjú kan",mm:"ìsẹjú %d",h:"wákati kan",hh:"wákati %d",d:"ọjọ́ kan",dd:"ọjọ́ %d",M:"osù kan",MM:"osù %d",y:"ọdún kan",yy:"ọdún %d"},dayOfMonthOrdinalParse:/ọjọ́\s\d{1,2}/,ordinal:"ọjọ́ %d",week:{dow:1,doy:4}})}(t(5093))},2648(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah点mm分",LLLL:"YYYY年M月D日ddddAh点mm分",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"下午"===a||"晚上"===a?e+12:e>=11?e:e+12},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1130?"上午":s<1230?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:function(e){return e.week()!==this.week()?"[下]dddLT":"[本]dddLT"},lastDay:"[昨天]LT",lastWeek:function(e){return this.week()!==e.week()?"[上]dddLT":"[本]dddLT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|周)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"周";default:return e}},relativeTime:{future:"%s后",past:"%s前",s:"几秒",ss:"%d 秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",w:"1 周",ww:"%d 周",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{dow:1,doy:4}})}(t(5093))},1632:function(e,a,t){!function(e){"use strict"; +e.defineLocale("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah点mm分",LLLL:"YYYY年M月D日ddddAh点mm分",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"下午"===a||"晚上"===a?e+12:e>=11?e:e+12},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1130?"上午":s<1230?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:function(e){return e.week()!==this.week()?"[下]dddLT":"[本]dddLT"},lastDay:"[昨天]LT",lastWeek:function(e){return this.week()!==e.week()?"[上]dddLT":"[本]dddLT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|周)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"周";default:return e}},relativeTime:{future:"%s后",past:"%s前",s:"几秒",ss:"%d 秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",w:"1 周",ww:"%d 周",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{dow:1,doy:4}})}(t(5093))},1632(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("zh-hk",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1200?"上午":1200===s?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(t(5093))},1541:function(e,a,t){!function(e){"use strict"; +e.defineLocale("zh-hk",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1200?"上午":1200===s?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(t(5093))},1541(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("zh-mo",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"D/M/YYYY",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1130?"上午":s<1230?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(t(5093))},304:function(e,a,t){!function(e){"use strict"; +e.defineLocale("zh-mo",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"D/M/YYYY",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1130?"上午":s<1230?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(t(5093))},304(e,a,t){!function(e){"use strict"; //! moment.js locale configuration -e.defineLocale("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1130?"上午":s<1230?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(t(5093))},5358:(e,a,t)=>{var s={"./af":5177,"./af.js":5177,"./ar":1509,"./ar-dz":1488,"./ar-dz.js":1488,"./ar-kw":8676,"./ar-kw.js":8676,"./ar-ly":2353,"./ar-ly.js":2353,"./ar-ma":4496,"./ar-ma.js":4496,"./ar-ps":6947,"./ar-ps.js":6947,"./ar-sa":2682,"./ar-sa.js":2682,"./ar-tn":9756,"./ar-tn.js":9756,"./ar.js":1509,"./az":5533,"./az.js":5533,"./be":8959,"./be.js":8959,"./bg":7777,"./bg.js":7777,"./bm":4903,"./bm.js":4903,"./bn":1290,"./bn-bd":7357,"./bn-bd.js":7357,"./bn.js":1290,"./bo":1545,"./bo.js":1545,"./br":1470,"./br.js":1470,"./bs":4429,"./bs.js":4429,"./ca":7306,"./ca.js":7306,"./cs":6464,"./cs.js":6464,"./cv":3635,"./cv.js":3635,"./cy":4226,"./cy.js":4226,"./da":3601,"./da.js":3601,"./de":7853,"./de-at":6111,"./de-at.js":6111,"./de-ch":4697,"./de-ch.js":4697,"./de.js":7853,"./dv":708,"./dv.js":708,"./el":4691,"./el.js":4691,"./en-au":3872,"./en-au.js":3872,"./en-ca":8298,"./en-ca.js":8298,"./en-gb":6195,"./en-gb.js":6195,"./en-ie":6584,"./en-ie.js":6584,"./en-il":5543,"./en-il.js":5543,"./en-in":9033,"./en-in.js":9033,"./en-nz":9402,"./en-nz.js":9402,"./en-sg":3004,"./en-sg.js":3004,"./eo":2934,"./eo.js":2934,"./es":7650,"./es-do":838,"./es-do.js":838,"./es-mx":7730,"./es-mx.js":7730,"./es-us":6575,"./es-us.js":6575,"./es.js":7650,"./et":3035,"./et.js":3035,"./eu":3508,"./eu.js":3508,"./fa":119,"./fa.js":119,"./fi":527,"./fi.js":527,"./fil":5995,"./fil.js":5995,"./fo":2477,"./fo.js":2477,"./fr":5498,"./fr-ca":6435,"./fr-ca.js":6435,"./fr-ch":7892,"./fr-ch.js":7892,"./fr.js":5498,"./fy":7071,"./fy.js":7071,"./ga":1734,"./ga.js":1734,"./gd":217,"./gd.js":217,"./gl":7329,"./gl.js":7329,"./gom-deva":2124,"./gom-deva.js":2124,"./gom-latn":3383,"./gom-latn.js":3383,"./gu":5050,"./gu.js":5050,"./he":1713,"./he.js":1713,"./hi":3861,"./hi.js":3861,"./hr":6308,"./hr.js":6308,"./hu":609,"./hu.js":609,"./hy-am":7160,"./hy-am.js":7160,"./id":4063,"./id.js":4063,"./is":9374,"./is.js":9374,"./it":8383,"./it-ch":1827,"./it-ch.js":1827,"./it.js":8383,"./ja":3827,"./ja.js":3827,"./jv":9722,"./jv.js":9722,"./ka":1794,"./ka.js":1794,"./kk":7088,"./kk.js":7088,"./km":6870,"./km.js":6870,"./kn":4451,"./kn.js":4451,"./ko":3164,"./ko.js":3164,"./ku":8174,"./ku-kmr":6181,"./ku-kmr.js":6181,"./ku.js":8174,"./ky":8474,"./ky.js":8474,"./lb":9680,"./lb.js":9680,"./lo":5867,"./lo.js":5867,"./lt":5766,"./lt.js":5766,"./lv":9532,"./lv.js":9532,"./me":8076,"./me.js":8076,"./mi":1848,"./mi.js":1848,"./mk":306,"./mk.js":306,"./ml":3739,"./ml.js":3739,"./mn":9053,"./mn.js":9053,"./mr":6169,"./mr.js":6169,"./ms":3386,"./ms-my":2297,"./ms-my.js":2297,"./ms.js":3386,"./mt":7075,"./mt.js":7075,"./my":2264,"./my.js":2264,"./nb":2274,"./nb.js":2274,"./ne":8235,"./ne.js":8235,"./nl":2572,"./nl-be":3784,"./nl-be.js":3784,"./nl.js":2572,"./nn":4566,"./nn.js":4566,"./oc-lnc":9330,"./oc-lnc.js":9330,"./pa-in":9849,"./pa-in.js":9849,"./pl":4418,"./pl.js":4418,"./pt":9834,"./pt-br":8303,"./pt-br.js":8303,"./pt.js":9834,"./ro":4457,"./ro.js":4457,"./ru":2271,"./ru.js":2271,"./sd":1221,"./sd.js":1221,"./se":3478,"./se.js":3478,"./si":7538,"./si.js":7538,"./sk":5784,"./sk.js":5784,"./sl":6637,"./sl.js":6637,"./sq":6794,"./sq.js":6794,"./sr":5719,"./sr-cyrl":3322,"./sr-cyrl.js":3322,"./sr.js":5719,"./ss":6e3,"./ss.js":6e3,"./sv":1011,"./sv.js":1011,"./sw":748,"./sw.js":748,"./ta":1025,"./ta.js":1025,"./te":1885,"./te.js":1885,"./tet":8861,"./tet.js":8861,"./tg":6571,"./tg.js":6571,"./th":5802,"./th.js":5802,"./tk":9527,"./tk.js":9527,"./tl-ph":9231,"./tl-ph.js":9231,"./tlh":1052,"./tlh.js":1052,"./tr":5096,"./tr.js":5096,"./tzl":9846,"./tzl.js":9846,"./tzm":1765,"./tzm-latn":7711,"./tzm-latn.js":7711,"./tzm.js":1765,"./ug-cn":8414,"./ug-cn.js":8414,"./uk":6618,"./uk.js":6618,"./ur":158,"./ur.js":158,"./uz":7609,"./uz-latn":2475,"./uz-latn.js":2475,"./uz.js":7609,"./vi":1135,"./vi.js":1135,"./x-pseudo":4051,"./x-pseudo.js":4051,"./yo":2218,"./yo.js":2218,"./zh-cn":2648,"./zh-cn.js":2648,"./zh-hk":1632,"./zh-hk.js":1632,"./zh-mo":1541,"./zh-mo.js":1541,"./zh-tw":304,"./zh-tw.js":304};function n(e){var a=r(e);return t(a)}function r(e){if(!t.o(s,e)){var a=new Error("Cannot find module '"+e+"'");throw a.code="MODULE_NOT_FOUND",a}return s[e]}n.keys=function(){return Object.keys(s)},n.resolve=r,e.exports=n,n.id=5358},5093:function(e,a,t){(e=t.nmd(e)).exports=function(){"use strict";var a,s;function n(){return a.apply(null,arguments)}function r(e){a=e}function i(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function d(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function _(e,a){return Object.prototype.hasOwnProperty.call(e,a)}function o(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var a;for(a in e)if(_(e,a))return!1;return!0}function u(e){return void 0===e}function m(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function l(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function M(e,a){var t,s=[],n=e.length;for(t=0;t>>0;for(a=0;a0)for(t=0;t=0?t?"+":"":"-")+Math.pow(10,Math.max(0,n)).toString().substr(1)+s}var F=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,z=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,N={},J={};function R(e,a,t,s){var n=s;"string"==typeof s&&(n=function(){return this[s]()}),e&&(J[e]=n),a&&(J[a[0]]=function(){return E(n.apply(this,arguments),a[1],a[2])}),t&&(J[t]=function(){return this.localeData().ordinal(n.apply(this,arguments),e)})}function C(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function I(e){var a,t,s=e.match(F);for(a=0,t=s.length;a=0&&z.test(e);)e=e.replace(z,s),z.lastIndex=0,t-=1;return e}var V={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function q(e){var a=this._longDateFormat[e],t=this._longDateFormat[e.toUpperCase()];return a||!t?a:(this._longDateFormat[e]=t.match(F).map((function(e){return"MMMM"===e||"MM"===e||"DD"===e||"dddd"===e?e.slice(1):e})).join(""),this._longDateFormat[e])}var B="Invalid date";function K(){return this._invalidDate}var Z="%d",$=/\d{1,2}/;function Q(e){return this._ordinal.replace("%d",e)}var X={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function ee(e,a,t,s){var n=this._relativeTime[t];return j(n)?n(e,a,t,s):n.replace(/%d/i,e)}function ae(e,a){var t=this._relativeTime[e>0?"future":"past"];return j(t)?t(a):t.replace(/%s/i,a)}var te={D:"date",dates:"date",date:"date",d:"day",days:"day",day:"day",e:"weekday",weekdays:"weekday",weekday:"weekday",E:"isoWeekday",isoweekdays:"isoWeekday",isoweekday:"isoWeekday",DDD:"dayOfYear",dayofyears:"dayOfYear",dayofyear:"dayOfYear",h:"hour",hours:"hour",hour:"hour",ms:"millisecond",milliseconds:"millisecond",millisecond:"millisecond",m:"minute",minutes:"minute",minute:"minute",M:"month",months:"month",month:"month",Q:"quarter",quarters:"quarter",quarter:"quarter",s:"second",seconds:"second",second:"second",gg:"weekYear",weekyears:"weekYear",weekyear:"weekYear",GG:"isoWeekYear",isoweekyears:"isoWeekYear",isoweekyear:"isoWeekYear",w:"week",weeks:"week",week:"week",W:"isoWeek",isoweeks:"isoWeek",isoweek:"isoWeek",y:"year",years:"year",year:"year"};function se(e){return"string"==typeof e?te[e]||te[e.toLowerCase()]:void 0}function ne(e){var a,t,s={};for(t in e)_(e,t)&&(a=se(t))&&(s[a]=e[t]);return s}var re={date:9,day:11,weekday:11,isoWeekday:11,dayOfYear:4,hour:13,millisecond:16,minute:14,month:8,quarter:7,second:15,weekYear:1,isoWeekYear:1,week:5,isoWeek:5,year:1};function ie(e){var a,t=[];for(a in e)_(e,a)&&t.push({unit:a,priority:re[a]});return t.sort((function(e,a){return e.priority-a.priority})),t}var de,_e=/\d/,oe=/\d\d/,ue=/\d{3}/,me=/\d{4}/,le=/[+-]?\d{6}/,Me=/\d\d?/,he=/\d\d\d\d?/,ce=/\d\d\d\d\d\d?/,Le=/\d{1,3}/,Ye=/\d{1,4}/,ye=/[+-]?\d{1,6}/,fe=/\d+/,ke=/[+-]?\d+/,pe=/Z|[+-]\d\d:?\d\d/gi,De=/Z|[+-]\d\d(?::?\d\d)?/gi,Te=/[+-]?\d+(\.\d{1,3})?/,ge=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,we=/^[1-9]\d?/,ve=/^([1-9]\d|\d)/;function be(e,a,t){de[e]=j(a)?a:function(e,s){return e&&t?t:a}}function He(e,a){return _(de,e)?de[e](a._strict,a._locale):new RegExp(Se(e))}function Se(e){return je(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,(function(e,a,t,s,n){return a||t||s||n})))}function je(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function xe(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function Pe(e){var a=+e,t=0;return 0!==a&&isFinite(a)&&(t=xe(a)),t}de={};var Oe={};function We(e,a){var t,s,n=a;for("string"==typeof e&&(e=[e]),m(a)&&(n=function(e,t){t[a]=Pe(e)}),s=e.length,t=0;t68?1900:2e3)};var Be,Ke=$e("FullYear",!0);function Ze(){return Fe(this.year())}function $e(e,a){return function(t){return null!=t?(Xe(this,e,t),n.updateOffset(this,a),this):Qe(this,e)}}function Qe(e,a){if(!e.isValid())return NaN;var t=e._d,s=e._isUTC;switch(a){case"Milliseconds":return s?t.getUTCMilliseconds():t.getMilliseconds();case"Seconds":return s?t.getUTCSeconds():t.getSeconds();case"Minutes":return s?t.getUTCMinutes():t.getMinutes();case"Hours":return s?t.getUTCHours():t.getHours();case"Date":return s?t.getUTCDate():t.getDate();case"Day":return s?t.getUTCDay():t.getDay();case"Month":return s?t.getUTCMonth():t.getMonth();case"FullYear":return s?t.getUTCFullYear():t.getFullYear();default:return NaN}}function Xe(e,a,t){var s,n,r,i,d;if(e.isValid()&&!isNaN(t)){switch(s=e._d,n=e._isUTC,a){case"Milliseconds":return void(n?s.setUTCMilliseconds(t):s.setMilliseconds(t));case"Seconds":return void(n?s.setUTCSeconds(t):s.setSeconds(t));case"Minutes":return void(n?s.setUTCMinutes(t):s.setMinutes(t));case"Hours":return void(n?s.setUTCHours(t):s.setHours(t));case"Date":return void(n?s.setUTCDate(t):s.setDate(t));case"FullYear":break;default:return}r=t,i=e.month(),d=29!==(d=e.date())||1!==i||Fe(r)?d:28,n?s.setUTCFullYear(r,i,d):s.setFullYear(r,i,d)}}function ea(e){return j(this[e=se(e)])?this[e]():this}function aa(e,a){if("object"==typeof e){var t,s=ie(e=ne(e)),n=s.length;for(t=0;t=0?(d=new Date(e+400,a,t,s,n,r,i),isFinite(d.getFullYear())&&d.setFullYear(e)):d=new Date(e,a,t,s,n,r,i),d}function ka(e){var a,t;return e<100&&e>=0?((t=Array.prototype.slice.call(arguments))[0]=e+400,a=new Date(Date.UTC.apply(null,t)),isFinite(a.getUTCFullYear())&&a.setUTCFullYear(e)):a=new Date(Date.UTC.apply(null,arguments)),a}function pa(e,a,t){var s=7+a-t;return-(7+ka(e,0,s).getUTCDay()-a)%7+s-1}function Da(e,a,t,s,n){var r,i,d=1+7*(a-1)+(7+t-s)%7+pa(e,s,n);return d<=0?i=qe(r=e-1)+d:d>qe(e)?(r=e+1,i=d-qe(e)):(r=e,i=d),{year:r,dayOfYear:i}}function Ta(e,a,t){var s,n,r=pa(e.year(),a,t),i=Math.floor((e.dayOfYear()-r-1)/7)+1;return i<1?s=i+ga(n=e.year()-1,a,t):i>ga(e.year(),a,t)?(s=i-ga(e.year(),a,t),n=e.year()+1):(n=e.year(),s=i),{week:s,year:n}}function ga(e,a,t){var s=pa(e,a,t),n=pa(e+1,a,t);return(qe(e)-s+n)/7}function wa(e){return Ta(e,this._week.dow,this._week.doy).week}R("w",["ww",2],"wo","week"),R("W",["WW",2],"Wo","isoWeek"),be("w",Me,we),be("ww",Me,oe),be("W",Me,we),be("WW",Me,oe),Ae(["w","ww","W","WW"],(function(e,a,t,s){a[s.substr(0,1)]=Pe(e)}));var va={dow:0,doy:6};function ba(){return this._week.dow}function Ha(){return this._week.doy}function Sa(e){var a=this.localeData().week(this);return null==e?a:this.add(7*(e-a),"d")}function ja(e){var a=Ta(this,1,4).week;return null==e?a:this.add(7*(e-a),"d")}function xa(e,a){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=a.weekdaysParse(e))?e:null:parseInt(e,10)}function Pa(e,a){return"string"==typeof e?a.weekdaysParse(e)%7||7:isNaN(e)?null:e}function Oa(e,a){return e.slice(a,7).concat(e.slice(0,a))}R("d",0,"do","day"),R("dd",0,0,(function(e){return this.localeData().weekdaysMin(this,e)})),R("ddd",0,0,(function(e){return this.localeData().weekdaysShort(this,e)})),R("dddd",0,0,(function(e){return this.localeData().weekdays(this,e)})),R("e",0,0,"weekday"),R("E",0,0,"isoWeekday"),be("d",Me),be("e",Me),be("E",Me),be("dd",(function(e,a){return a.weekdaysMinRegex(e)})),be("ddd",(function(e,a){return a.weekdaysShortRegex(e)})),be("dddd",(function(e,a){return a.weekdaysRegex(e)})),Ae(["dd","ddd","dddd"],(function(e,a,t,s){var n=t._locale.weekdaysParse(e,s,t._strict);null!=n?a.d=n:Y(t).invalidWeekday=e})),Ae(["d","e","E"],(function(e,a,t,s){a[s]=Pe(e)}));var Wa="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Aa="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Ea="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Fa=ge,za=ge,Na=ge;function Ja(e,a){var t=i(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(a)?"format":"standalone"];return!0===e?Oa(t,this._week.dow):e?t[e.day()]:t}function Ra(e){return!0===e?Oa(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function Ca(e){return!0===e?Oa(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function Ia(e,a,t){var s,n,r,i=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=c([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return t?"dddd"===a?-1!==(n=Be.call(this._weekdaysParse,i))?n:null:"ddd"===a?-1!==(n=Be.call(this._shortWeekdaysParse,i))?n:null:-1!==(n=Be.call(this._minWeekdaysParse,i))?n:null:"dddd"===a?-1!==(n=Be.call(this._weekdaysParse,i))||-1!==(n=Be.call(this._shortWeekdaysParse,i))||-1!==(n=Be.call(this._minWeekdaysParse,i))?n:null:"ddd"===a?-1!==(n=Be.call(this._shortWeekdaysParse,i))||-1!==(n=Be.call(this._weekdaysParse,i))||-1!==(n=Be.call(this._minWeekdaysParse,i))?n:null:-1!==(n=Be.call(this._minWeekdaysParse,i))||-1!==(n=Be.call(this._weekdaysParse,i))||-1!==(n=Be.call(this._shortWeekdaysParse,i))?n:null}function Ua(e,a,t){var s,n,r;if(this._weekdaysParseExact)return Ia.call(this,e,a,t);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(n=c([2e3,1]).day(s),t&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(n,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(n,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(n,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),t&&"dddd"===a&&this._fullWeekdaysParse[s].test(e))return s;if(t&&"ddd"===a&&this._shortWeekdaysParse[s].test(e))return s;if(t&&"dd"===a&&this._minWeekdaysParse[s].test(e))return s;if(!t&&this._weekdaysParse[s].test(e))return s}}function Ga(e){if(!this.isValid())return null!=e?this:NaN;var a=Qe(this,"Day");return null!=e?(e=xa(e,this.localeData()),this.add(e-a,"d")):a}function Va(e){if(!this.isValid())return null!=e?this:NaN;var a=(this.day()+7-this.localeData()._week.dow)%7;return null==e?a:this.add(e-a,"d")}function qa(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var a=Pa(e,this.localeData());return this.day(this.day()%7?a:a-7)}return this.day()||7}function Ba(e){return this._weekdaysParseExact?(_(this,"_weekdaysRegex")||$a.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(_(this,"_weekdaysRegex")||(this._weekdaysRegex=Fa),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function Ka(e){return this._weekdaysParseExact?(_(this,"_weekdaysRegex")||$a.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(_(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=za),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Za(e){return this._weekdaysParseExact?(_(this,"_weekdaysRegex")||$a.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(_(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Na),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function $a(){function e(e,a){return a.length-e.length}var a,t,s,n,r,i=[],d=[],_=[],o=[];for(a=0;a<7;a++)t=c([2e3,1]).day(a),s=je(this.weekdaysMin(t,"")),n=je(this.weekdaysShort(t,"")),r=je(this.weekdays(t,"")),i.push(s),d.push(n),_.push(r),o.push(s),o.push(n),o.push(r);i.sort(e),d.sort(e),_.sort(e),o.sort(e),this._weekdaysRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+_.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function Qa(){return this.hours()%12||12}function Xa(){return this.hours()||24}function et(e,a){R(e,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)}))}function at(e,a){return a._meridiemParse}function tt(e){return"p"===(e+"").toLowerCase().charAt(0)}R("H",["HH",2],0,"hour"),R("h",["hh",2],0,Qa),R("k",["kk",2],0,Xa),R("hmm",0,0,(function(){return""+Qa.apply(this)+E(this.minutes(),2)})),R("hmmss",0,0,(function(){return""+Qa.apply(this)+E(this.minutes(),2)+E(this.seconds(),2)})),R("Hmm",0,0,(function(){return""+this.hours()+E(this.minutes(),2)})),R("Hmmss",0,0,(function(){return""+this.hours()+E(this.minutes(),2)+E(this.seconds(),2)})),et("a",!0),et("A",!1),be("a",at),be("A",at),be("H",Me,ve),be("h",Me,we),be("k",Me,we),be("HH",Me,oe),be("hh",Me,oe),be("kk",Me,oe),be("hmm",he),be("hmmss",ce),be("Hmm",he),be("Hmmss",ce),We(["H","HH"],Re),We(["k","kk"],(function(e,a,t){var s=Pe(e);a[Re]=24===s?0:s})),We(["a","A"],(function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e})),We(["h","hh"],(function(e,a,t){a[Re]=Pe(e),Y(t).bigHour=!0})),We("hmm",(function(e,a,t){var s=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s)),Y(t).bigHour=!0})),We("hmmss",(function(e,a,t){var s=e.length-4,n=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s,2)),a[Ie]=Pe(e.substr(n)),Y(t).bigHour=!0})),We("Hmm",(function(e,a,t){var s=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s))})),We("Hmmss",(function(e,a,t){var s=e.length-4,n=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s,2)),a[Ie]=Pe(e.substr(n))}));var st=/[ap]\.?m?\.?/i,nt=$e("Hours",!0);function rt(e,a,t){return e>11?t?"pm":"PM":t?"am":"AM"}var it,dt={calendar:W,longDateFormat:V,invalidDate:B,ordinal:Z,dayOfMonthOrdinalParse:$,relativeTime:X,months:na,monthsShort:ra,week:va,weekdays:Wa,weekdaysMin:Ea,weekdaysShort:Aa,meridiemParse:st},_t={},ot={};function ut(e,a){var t,s=Math.min(e.length,a.length);for(t=0;t0;){if(s=ht(n.slice(0,a).join("-")))return s;if(t&&t.length>=a&&ut(n,t)>=a-1)break;a--}r++}return it}function Mt(e){return!(!e||!e.match("^[^/\\\\]*$"))}function ht(a){var s=null;if(void 0===_t[a]&&e&&e.exports&&Mt(a))try{s=it._abbr,t(5358)("./"+a),ct(s)}catch(e){_t[a]=null}return _t[a]}function ct(e,a){var t;return e&&((t=u(a)?yt(e):Lt(e,a))?it=t:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),it._abbr}function Lt(e,a){if(null!==a){var t,s=dt;if(a.abbr=e,null!=_t[e])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=_t[e]._config;else if(null!=a.parentLocale)if(null!=_t[a.parentLocale])s=_t[a.parentLocale]._config;else{if(null==(t=ht(a.parentLocale)))return ot[a.parentLocale]||(ot[a.parentLocale]=[]),ot[a.parentLocale].push({name:e,config:a}),null;s=t._config}return _t[e]=new O(P(s,a)),ot[e]&&ot[e].forEach((function(e){Lt(e.name,e.config)})),ct(e),_t[e]}return delete _t[e],null}function Yt(e,a){if(null!=a){var t,s,n=dt;null!=_t[e]&&null!=_t[e].parentLocale?_t[e].set(P(_t[e]._config,a)):(null!=(s=ht(e))&&(n=s._config),a=P(n,a),null==s&&(a.abbr=e),(t=new O(a)).parentLocale=_t[e],_t[e]=t),ct(e)}else null!=_t[e]&&(null!=_t[e].parentLocale?(_t[e]=_t[e].parentLocale,e===ct()&&ct(e)):null!=_t[e]&&delete _t[e]);return _t[e]}function yt(e){var a;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return it;if(!i(e)){if(a=ht(e))return a;e=[e]}return lt(e)}function ft(){return b(_t)}function kt(e){var a,t=e._a;return t&&-2===Y(e).overflow&&(a=t[Ne]<0||t[Ne]>11?Ne:t[Je]<1||t[Je]>sa(t[ze],t[Ne])?Je:t[Re]<0||t[Re]>24||24===t[Re]&&(0!==t[Ce]||0!==t[Ie]||0!==t[Ue])?Re:t[Ce]<0||t[Ce]>59?Ce:t[Ie]<0||t[Ie]>59?Ie:t[Ue]<0||t[Ue]>999?Ue:-1,Y(e)._overflowDayOfYear&&(aJe)&&(a=Je),Y(e)._overflowWeeks&&-1===a&&(a=Ge),Y(e)._overflowWeekday&&-1===a&&(a=Ve),Y(e).overflow=a),e}var pt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Dt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Tt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],wt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],vt=/^\/?Date\((-?\d+)/i,bt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Ht={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function St(e){var a,t,s,n,r,i,d=e._i,_=pt.exec(d)||Dt.exec(d),o=gt.length,u=wt.length;if(_){for(Y(e).iso=!0,a=0,t=o;aqe(r)||0===e._dayOfYear)&&(Y(e)._overflowDayOfYear=!0),t=ka(r,0,e._dayOfYear),e._a[Ne]=t.getUTCMonth(),e._a[Je]=t.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=i[a]=s[a];for(;a<7;a++)e._a[a]=i[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[Re]&&0===e._a[Ce]&&0===e._a[Ie]&&0===e._a[Ue]&&(e._nextDay=!0,e._a[Re]=0),e._d=(e._useUTC?ka:fa).apply(null,i),n=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Re]=24),e._w&&void 0!==e._w.d&&e._w.d!==n&&(Y(e).weekdayMismatch=!0)}}function Jt(e){var a,t,s,n,r,i,d,_,o;null!=(a=e._w).GG||null!=a.W||null!=a.E?(r=1,i=4,t=Ft(a.GG,e._a[ze],Ta(Kt(),1,4).year),s=Ft(a.W,1),((n=Ft(a.E,1))<1||n>7)&&(_=!0)):(r=e._locale._week.dow,i=e._locale._week.doy,o=Ta(Kt(),r,i),t=Ft(a.gg,e._a[ze],o.year),s=Ft(a.w,o.week),null!=a.d?((n=a.d)<0||n>6)&&(_=!0):null!=a.e?(n=a.e+r,(a.e<0||a.e>6)&&(_=!0)):n=r),s<1||s>ga(t,r,i)?Y(e)._overflowWeeks=!0:null!=_?Y(e)._overflowWeekday=!0:(d=Da(t,s,n,r,i),e._a[ze]=d.year,e._dayOfYear=d.dayOfYear)}function Rt(e){if(e._f!==n.ISO_8601)if(e._f!==n.RFC_2822){e._a=[],Y(e).empty=!0;var a,t,s,r,i,d,_,o=""+e._i,u=o.length,m=0;for(_=(s=G(e._f,e._locale).match(F)||[]).length,a=0;a<_;a++)r=s[a],(t=(o.match(He(r,e))||[])[0])&&((i=o.substr(0,o.indexOf(t))).length>0&&Y(e).unusedInput.push(i),o=o.slice(o.indexOf(t)+t.length),m+=t.length),J[r]?(t?Y(e).empty=!1:Y(e).unusedTokens.push(r),Ee(r,t,e)):e._strict&&!t&&Y(e).unusedTokens.push(r);Y(e).charsLeftOver=u-m,o.length>0&&Y(e).unusedInput.push(o),e._a[Re]<=12&&!0===Y(e).bigHour&&e._a[Re]>0&&(Y(e).bigHour=void 0),Y(e).parsedDateParts=e._a.slice(0),Y(e).meridiem=e._meridiem,e._a[Re]=Ct(e._locale,e._a[Re],e._meridiem),null!==(d=Y(e).era)&&(e._a[ze]=e._locale.erasConvertYear(d,e._a[ze])),Nt(e),kt(e)}else At(e);else St(e)}function Ct(e,a,t){var s;return null==t?a:null!=e.meridiemHour?e.meridiemHour(a,t):null!=e.isPM?((s=e.isPM(t))&&a<12&&(a+=12),s||12!==a||(a=0),a):a}function It(e){var a,t,s,n,r,i,d=!1,_=e._f.length;if(0===_)return Y(e).invalidFormat=!0,void(e._d=new Date(NaN));for(n=0;n<_;n++)r=0,i=!1,a=D({},e),null!=e._useUTC&&(a._useUTC=e._useUTC),a._f=e._f[n],Rt(a),y(a)&&(i=!0),r+=Y(a).charsLeftOver,r+=10*Y(a).unusedTokens.length,Y(a).score=r,d?rthis?this:e:f()}));function Qt(e,a){var t,s;if(1===a.length&&i(a[0])&&(a=a[0]),!a.length)return Kt();for(t=a[0],s=1;sthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ds(){if(!u(this._isDSTShifted))return this._isDSTShifted;var e,a={};return D(a,this),(a=Vt(a))._a?(e=a._isUTC?c(a._a):Kt(a._a),this._isDSTShifted=this.isValid()&&os(a._a,e.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function Ts(){return!!this.isValid()&&!this._isUTC}function gs(){return!!this.isValid()&&this._isUTC}function ws(){return!!this.isValid()&&this._isUTC&&0===this._offset}n.updateOffset=function(){};var vs=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,bs=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Hs(e,a){var t,s,n,r=e,i=null;return ds(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:m(e)||!isNaN(+e)?(r={},a?r[a]=+e:r.milliseconds=+e):(i=vs.exec(e))?(t="-"===i[1]?-1:1,r={y:0,d:Pe(i[Je])*t,h:Pe(i[Re])*t,m:Pe(i[Ce])*t,s:Pe(i[Ie])*t,ms:Pe(_s(1e3*i[Ue]))*t}):(i=bs.exec(e))?(t="-"===i[1]?-1:1,r={y:Ss(i[2],t),M:Ss(i[3],t),w:Ss(i[4],t),d:Ss(i[5],t),h:Ss(i[6],t),m:Ss(i[7],t),s:Ss(i[8],t)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(n=xs(Kt(r.from),Kt(r.to)),(r={}).ms=n.milliseconds,r.M=n.months),s=new is(r),ds(e)&&_(e,"_locale")&&(s._locale=e._locale),ds(e)&&_(e,"_isValid")&&(s._isValid=e._isValid),s}function Ss(e,a){var t=e&&parseFloat(e.replace(",","."));return(isNaN(t)?0:t)*a}function js(e,a){var t={};return t.months=a.month()-e.month()+12*(a.year()-e.year()),e.clone().add(t.months,"M").isAfter(a)&&--t.months,t.milliseconds=+a-+e.clone().add(t.months,"M"),t}function xs(e,a){var t;return e.isValid()&&a.isValid()?(a=Ms(a,e),e.isBefore(a)?t=js(e,a):((t=js(a,e)).milliseconds=-t.milliseconds,t.months=-t.months),t):{milliseconds:0,months:0}}function Ps(e,a){return function(t,s){var n;return null===s||isNaN(+s)||(S(a,"moment()."+a+"(period, number) is deprecated. Please use moment()."+a+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=t,t=s,s=n),Os(this,Hs(t,s),e),this}}function Os(e,a,t,s){var r=a._milliseconds,i=_s(a._days),d=_s(a._months);e.isValid()&&(s=null==s||s,d&&Ma(e,Qe(e,"Month")+d*t),i&&Xe(e,"Date",Qe(e,"Date")+i*t),r&&e._d.setTime(e._d.valueOf()+r*t),s&&n.updateOffset(e,i||d))}Hs.fn=is.prototype,Hs.invalid=rs;var Ws=Ps(1,"add"),As=Ps(-1,"subtract");function Es(e){return"string"==typeof e||e instanceof String}function Fs(e){return g(e)||l(e)||Es(e)||m(e)||Ns(e)||zs(e)||null==e}function zs(e){var a,t,s=d(e)&&!o(e),n=!1,r=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],i=r.length;for(a=0;at.valueOf():t.valueOf()9999?U(t,a?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):j(Date.prototype.toISOString)?a?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",U(t,"Z")):U(t,a?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function en(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e,a,t,s,n="moment",r="";return this.isLocal()||(n=0===this.utcOffset()?"moment.utc":"moment.parseZone",r="Z"),e="["+n+'("]',a=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",t="-MM-DD[T]HH:mm:ss.SSS",s=r+'[")]',this.format(e+a+t+s)}function an(e){e||(e=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var a=U(this,e);return this.localeData().postformat(a)}function tn(e,a){return this.isValid()&&(g(e)&&e.isValid()||Kt(e).isValid())?Hs({to:this,from:e}).locale(this.locale()).humanize(!a):this.localeData().invalidDate()}function sn(e){return this.from(Kt(),e)}function nn(e,a){return this.isValid()&&(g(e)&&e.isValid()||Kt(e).isValid())?Hs({from:this,to:e}).locale(this.locale()).humanize(!a):this.localeData().invalidDate()}function rn(e){return this.to(Kt(),e)}function dn(e){var a;return void 0===e?this._locale._abbr:(null!=(a=yt(e))&&(this._locale=a),this)}n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var _n=v("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(e){return void 0===e?this.localeData():this.locale(e)}));function on(){return this._locale}var un=1e3,mn=60*un,ln=60*mn,Mn=3506328*ln;function hn(e,a){return(e%a+a)%a}function cn(e,a,t){return e<100&&e>=0?new Date(e+400,a,t)-Mn:new Date(e,a,t).valueOf()}function Ln(e,a,t){return e<100&&e>=0?Date.UTC(e+400,a,t)-Mn:Date.UTC(e,a,t)}function Yn(e){var a,t;if(void 0===(e=se(e))||"millisecond"===e||!this.isValid())return this;switch(t=this._isUTC?Ln:cn,e){case"year":a=t(this.year(),0,1);break;case"quarter":a=t(this.year(),this.month()-this.month()%3,1);break;case"month":a=t(this.year(),this.month(),1);break;case"week":a=t(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":a=t(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":a=t(this.year(),this.month(),this.date());break;case"hour":a=this._d.valueOf(),a-=hn(a+(this._isUTC?0:this.utcOffset()*mn),ln);break;case"minute":a=this._d.valueOf(),a-=hn(a,mn);break;case"second":a=this._d.valueOf(),a-=hn(a,un)}return this._d.setTime(a),n.updateOffset(this,!0),this}function yn(e){var a,t;if(void 0===(e=se(e))||"millisecond"===e||!this.isValid())return this;switch(t=this._isUTC?Ln:cn,e){case"year":a=t(this.year()+1,0,1)-1;break;case"quarter":a=t(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":a=t(this.year(),this.month()+1,1)-1;break;case"week":a=t(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":a=t(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":a=t(this.year(),this.month(),this.date()+1)-1;break;case"hour":a=this._d.valueOf(),a+=ln-hn(a+(this._isUTC?0:this.utcOffset()*mn),ln)-1;break;case"minute":a=this._d.valueOf(),a+=mn-hn(a,mn)-1;break;case"second":a=this._d.valueOf(),a+=un-hn(a,un)-1}return this._d.setTime(a),n.updateOffset(this,!0),this}function fn(){return this._d.valueOf()-6e4*(this._offset||0)}function kn(){return Math.floor(this.valueOf()/1e3)}function pn(){return new Date(this.valueOf())}function Dn(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function Tn(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function gn(){return this.isValid()?this.toISOString():null}function wn(){return y(this)}function vn(){return h({},Y(this))}function bn(){return Y(this).overflow}function Hn(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Sn(e,a){var t,s,r,i=this._eras||yt("en")._eras;for(t=0,s=i.length;t=0)return _[s]}function xn(e,a){var t=e.since<=e.until?1:-1;return void 0===a?n(e.since).year():n(e.since).year()+(a-e.offset)*t}function Pn(){var e,a,t,s=this.localeData().eras();for(e=0,a=s.length;e(r=ga(e,s,n))&&(a=r),Qn.call(this,e,a,t,s,n))}function Qn(e,a,t,s,n){var r=Da(e,a,t,s,n),i=ka(r.year,0,r.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}function Xn(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)}R("N",0,0,"eraAbbr"),R("NN",0,0,"eraAbbr"),R("NNN",0,0,"eraAbbr"),R("NNNN",0,0,"eraName"),R("NNNNN",0,0,"eraNarrow"),R("y",["y",1],"yo","eraYear"),R("y",["yy",2],0,"eraYear"),R("y",["yyy",3],0,"eraYear"),R("y",["yyyy",4],0,"eraYear"),be("N",Nn),be("NN",Nn),be("NNN",Nn),be("NNNN",Jn),be("NNNNN",Rn),We(["N","NN","NNN","NNNN","NNNNN"],(function(e,a,t,s){var n=t._locale.erasParse(e,s,t._strict);n?Y(t).era=n:Y(t).invalidEra=e})),be("y",fe),be("yy",fe),be("yyy",fe),be("yyyy",fe),be("yo",Cn),We(["y","yy","yyy","yyyy"],ze),We(["yo"],(function(e,a,t,s){var n;t._locale._eraYearOrdinalRegex&&(n=e.match(t._locale._eraYearOrdinalRegex)),t._locale.eraYearOrdinalParse?a[ze]=t._locale.eraYearOrdinalParse(e,n):a[ze]=parseInt(e,10)})),R(0,["gg",2],0,(function(){return this.weekYear()%100})),R(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),Un("gggg","weekYear"),Un("ggggg","weekYear"),Un("GGGG","isoWeekYear"),Un("GGGGG","isoWeekYear"),be("G",ke),be("g",ke),be("GG",Me,oe),be("gg",Me,oe),be("GGGG",Ye,me),be("gggg",Ye,me),be("GGGGG",ye,le),be("ggggg",ye,le),Ae(["gggg","ggggg","GGGG","GGGGG"],(function(e,a,t,s){a[s.substr(0,2)]=Pe(e)})),Ae(["gg","GG"],(function(e,a,t,s){a[s]=n.parseTwoDigitYear(e)})),R("Q",0,"Qo","quarter"),be("Q",_e),We("Q",(function(e,a){a[Ne]=3*(Pe(e)-1)})),R("D",["DD",2],"Do","date"),be("D",Me,we),be("DD",Me,oe),be("Do",(function(e,a){return e?a._dayOfMonthOrdinalParse||a._ordinalParse:a._dayOfMonthOrdinalParseLenient})),We(["D","DD"],Je),We("Do",(function(e,a){a[Je]=Pe(e.match(Me)[0])}));var er=$e("Date",!0);function ar(e){var a=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?a:this.add(e-a,"d")}R("DDD",["DDDD",3],"DDDo","dayOfYear"),be("DDD",Le),be("DDDD",ue),We(["DDD","DDDD"],(function(e,a,t){t._dayOfYear=Pe(e)})),R("m",["mm",2],0,"minute"),be("m",Me,ve),be("mm",Me,oe),We(["m","mm"],Ce);var tr=$e("Minutes",!1);R("s",["ss",2],0,"second"),be("s",Me,ve),be("ss",Me,oe),We(["s","ss"],Ie);var sr,nr,rr=$e("Seconds",!1);for(R("S",0,0,(function(){return~~(this.millisecond()/100)})),R(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),R(0,["SSS",3],0,"millisecond"),R(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),R(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),R(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),R(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),R(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),R(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),be("S",Le,_e),be("SS",Le,oe),be("SSS",Le,ue),sr="SSSS";sr.length<=9;sr+="S")be(sr,fe);function ir(e,a){a[Ue]=Pe(1e3*("0."+e))}for(sr="S";sr.length<=9;sr+="S")We(sr,ir);function dr(){return this._isUTC?"UTC":""}function _r(){return this._isUTC?"Coordinated Universal Time":""}nr=$e("Milliseconds",!1),R("z",0,0,"zoneAbbr"),R("zz",0,0,"zoneName");var or=T.prototype;function ur(e){return Kt(1e3*e)}function mr(){return Kt.apply(null,arguments).parseZone()}function lr(e){return e}or.add=Ws,or.calendar=Cs,or.clone=Is,or.diff=Zs,or.endOf=yn,or.format=an,or.from=tn,or.fromNow=sn,or.to=nn,or.toNow=rn,or.get=ea,or.invalidAt=bn,or.isAfter=Us,or.isBefore=Gs,or.isBetween=Vs,or.isSame=qs,or.isSameOrAfter=Bs,or.isSameOrBefore=Ks,or.isValid=wn,or.lang=_n,or.locale=dn,or.localeData=on,or.max=$t,or.min=Zt,or.parsingFlags=vn,or.set=aa,or.startOf=Yn,or.subtract=As,or.toArray=Dn,or.toObject=Tn,or.toDate=pn,or.toISOString=Xs,or.inspect=en,"undefined"!=typeof Symbol&&null!=Symbol.for&&(or[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),or.toJSON=gn,or.toString=Qs,or.unix=kn,or.valueOf=fn,or.creationData=Hn,or.eraName=Pn,or.eraNarrow=On,or.eraAbbr=Wn,or.eraYear=An,or.year=Ke,or.isLeapYear=Ze,or.weekYear=Gn,or.isoWeekYear=Vn,or.quarter=or.quarters=Xn,or.month=ha,or.daysInMonth=ca,or.week=or.weeks=Sa,or.isoWeek=or.isoWeeks=ja,or.weeksInYear=Kn,or.weeksInWeekYear=Zn,or.isoWeeksInYear=qn,or.isoWeeksInISOWeekYear=Bn,or.date=er,or.day=or.days=Ga,or.weekday=Va,or.isoWeekday=qa,or.dayOfYear=ar,or.hour=or.hours=nt,or.minute=or.minutes=tr,or.second=or.seconds=rr,or.millisecond=or.milliseconds=nr,or.utcOffset=cs,or.utc=Ys,or.local=ys,or.parseZone=fs,or.hasAlignedHourOffset=ks,or.isDST=ps,or.isLocal=Ts,or.isUtcOffset=gs,or.isUtc=ws,or.isUTC=ws,or.zoneAbbr=dr,or.zoneName=_r,or.dates=v("dates accessor is deprecated. Use date instead.",er),or.months=v("months accessor is deprecated. Use month instead",ha),or.years=v("years accessor is deprecated. Use year instead",Ke),or.zone=v("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Ls),or.isDSTShifted=v("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ds);var Mr=O.prototype;function hr(e,a,t,s){var n=yt(),r=c().set(s,a);return n[t](r,e)}function cr(e,a,t){if(m(e)&&(a=e,e=void 0),e=e||"",null!=a)return hr(e,a,t,"month");var s,n=[];for(s=0;s<12;s++)n[s]=hr(e,s,t,"month");return n}function Lr(e,a,t,s){"boolean"==typeof e?(m(a)&&(t=a,a=void 0),a=a||""):(t=a=e,e=!1,m(a)&&(t=a,a=void 0),a=a||"");var n,r=yt(),i=e?r._week.dow:0,d=[];if(null!=t)return hr(a,(t+i)%7,s,"day");for(n=0;n<7;n++)d[n]=hr(a,(n+i)%7,s,"day");return d}function Yr(e,a){return cr(e,a,"months")}function yr(e,a){return cr(e,a,"monthsShort")}function fr(e,a,t){return Lr(e,a,t,"weekdays")}function kr(e,a,t){return Lr(e,a,t,"weekdaysShort")}function pr(e,a,t){return Lr(e,a,t,"weekdaysMin")}Mr.calendar=A,Mr.longDateFormat=q,Mr.invalidDate=K,Mr.ordinal=Q,Mr.preparse=lr,Mr.postformat=lr,Mr.relativeTime=ee,Mr.pastFuture=ae,Mr.set=x,Mr.eras=Sn,Mr.erasParse=jn,Mr.erasConvertYear=xn,Mr.erasAbbrRegex=Fn,Mr.erasNameRegex=En,Mr.erasNarrowRegex=zn,Mr.months=oa,Mr.monthsShort=ua,Mr.monthsParse=la,Mr.monthsRegex=Ya,Mr.monthsShortRegex=La,Mr.week=wa,Mr.firstDayOfYear=Ha,Mr.firstDayOfWeek=ba,Mr.weekdays=Ja,Mr.weekdaysMin=Ca,Mr.weekdaysShort=Ra,Mr.weekdaysParse=Ua,Mr.weekdaysRegex=Ba,Mr.weekdaysShortRegex=Ka,Mr.weekdaysMinRegex=Za,Mr.isPM=tt,Mr.meridiem=rt,ct("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var a=e%10;return e+(1===Pe(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}}),n.lang=v("moment.lang is deprecated. Use moment.locale instead.",ct),n.langData=v("moment.langData is deprecated. Use moment.localeData instead.",yt);var Dr=Math.abs;function Tr(){var e=this._data;return this._milliseconds=Dr(this._milliseconds),this._days=Dr(this._days),this._months=Dr(this._months),e.milliseconds=Dr(e.milliseconds),e.seconds=Dr(e.seconds),e.minutes=Dr(e.minutes),e.hours=Dr(e.hours),e.months=Dr(e.months),e.years=Dr(e.years),this}function gr(e,a,t,s){var n=Hs(a,t);return e._milliseconds+=s*n._milliseconds,e._days+=s*n._days,e._months+=s*n._months,e._bubble()}function wr(e,a){return gr(this,e,a,1)}function vr(e,a){return gr(this,e,a,-1)}function br(e){return e<0?Math.floor(e):Math.ceil(e)}function Hr(){var e,a,t,s,n,r=this._milliseconds,i=this._days,d=this._months,_=this._data;return r>=0&&i>=0&&d>=0||r<=0&&i<=0&&d<=0||(r+=864e5*br(jr(d)+i),i=0,d=0),_.milliseconds=r%1e3,e=xe(r/1e3),_.seconds=e%60,a=xe(e/60),_.minutes=a%60,t=xe(a/60),_.hours=t%24,i+=xe(t/24),d+=n=xe(Sr(i)),i-=br(jr(n)),s=xe(d/12),d%=12,_.days=i,_.months=d,_.years=s,this}function Sr(e){return 4800*e/146097}function jr(e){return 146097*e/4800}function xr(e){if(!this.isValid())return NaN;var a,t,s=this._milliseconds;if("month"===(e=se(e))||"quarter"===e||"year"===e)switch(a=this._days+s/864e5,t=this._months+Sr(a),e){case"month":return t;case"quarter":return t/3;case"year":return t/12}else switch(a=this._days+Math.round(jr(this._months)),e){case"week":return a/7+s/6048e5;case"day":return a+s/864e5;case"hour":return 24*a+s/36e5;case"minute":return 1440*a+s/6e4;case"second":return 86400*a+s/1e3;case"millisecond":return Math.floor(864e5*a)+s;default:throw new Error("Unknown unit "+e)}}function Pr(e){return function(){return this.as(e)}}var Or=Pr("ms"),Wr=Pr("s"),Ar=Pr("m"),Er=Pr("h"),Fr=Pr("d"),zr=Pr("w"),Nr=Pr("M"),Jr=Pr("Q"),Rr=Pr("y"),Cr=Or;function Ir(){return Hs(this)}function Ur(e){return e=se(e),this.isValid()?this[e+"s"]():NaN}function Gr(e){return function(){return this.isValid()?this._data[e]:NaN}}var Vr=Gr("milliseconds"),qr=Gr("seconds"),Br=Gr("minutes"),Kr=Gr("hours"),Zr=Gr("days"),$r=Gr("months"),Qr=Gr("years");function Xr(){return xe(this.days()/7)}var ei=Math.round,ai={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function ti(e,a,t,s,n){return n.relativeTime(a||1,!!t,e,s)}function si(e,a,t,s){var n=Hs(e).abs(),r=ei(n.as("s")),i=ei(n.as("m")),d=ei(n.as("h")),_=ei(n.as("d")),o=ei(n.as("M")),u=ei(n.as("w")),m=ei(n.as("y")),l=r<=t.ss&&["s",r]||r0,l[4]=s,ti.apply(null,l)}function ni(e){return void 0===e?ei:"function"==typeof e&&(ei=e,!0)}function ri(e,a){return void 0!==ai[e]&&(void 0===a?ai[e]:(ai[e]=a,"s"===e&&(ai.ss=a-1),!0))}function ii(e,a){if(!this.isValid())return this.localeData().invalidDate();var t,s,n=!1,r=ai;return"object"==typeof e&&(a=e,e=!1),"boolean"==typeof e&&(n=e),"object"==typeof a&&(r=Object.assign({},ai,a),null!=a.s&&null==a.ss&&(r.ss=a.s-1)),s=si(this,!n,r,t=this.localeData()),n&&(s=t.pastFuture(+this,s)),t.postformat(s)}var di=Math.abs;function _i(e){return(e>0)-(e<0)||+e}function oi(){if(!this.isValid())return this.localeData().invalidDate();var e,a,t,s,n,r,i,d,_=di(this._milliseconds)/1e3,o=di(this._days),u=di(this._months),m=this.asSeconds();return m?(e=xe(_/60),a=xe(e/60),_%=60,e%=60,t=xe(u/12),u%=12,s=_?_.toFixed(3).replace(/\.?0+$/,""):"",n=m<0?"-":"",r=_i(this._months)!==_i(m)?"-":"",i=_i(this._days)!==_i(m)?"-":"",d=_i(this._milliseconds)!==_i(m)?"-":"",n+"P"+(t?r+t+"Y":"")+(u?r+u+"M":"")+(o?i+o+"D":"")+(a||e||_?"T":"")+(a?d+a+"H":"")+(e?d+e+"M":"")+(_?d+s+"S":"")):"P0D"}var ui=is.prototype;return ui.isValid=ns,ui.abs=Tr,ui.add=wr,ui.subtract=vr,ui.as=xr,ui.asMilliseconds=Or,ui.asSeconds=Wr,ui.asMinutes=Ar,ui.asHours=Er,ui.asDays=Fr,ui.asWeeks=zr,ui.asMonths=Nr,ui.asQuarters=Jr,ui.asYears=Rr,ui.valueOf=Cr,ui._bubble=Hr,ui.clone=Ir,ui.get=Ur,ui.milliseconds=Vr,ui.seconds=qr,ui.minutes=Br,ui.hours=Kr,ui.days=Zr,ui.weeks=Xr,ui.months=$r,ui.years=Qr,ui.humanize=ii,ui.toISOString=oi,ui.toString=oi,ui.toJSON=oi,ui.locale=dn,ui.localeData=on,ui.toIsoString=v("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",oi),ui.lang=_n,R("X",0,0,"unix"),R("x",0,0,"valueOf"),be("x",ke),be("X",Te),We("X",(function(e,a,t){t._d=new Date(1e3*parseFloat(e))})),We("x",(function(e,a,t){t._d=new Date(Pe(e))})), +e.defineLocale("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var s=100*e+a;return s<600?"凌晨":s<900?"早上":s<1130?"上午":s<1230?"中午":s<1800?"下午":"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(t(5093))},5358(e,a,t){var s={"./af":5177,"./af.js":5177,"./ar":1509,"./ar-dz":1488,"./ar-dz.js":1488,"./ar-kw":8676,"./ar-kw.js":8676,"./ar-ly":2353,"./ar-ly.js":2353,"./ar-ma":4496,"./ar-ma.js":4496,"./ar-ps":6947,"./ar-ps.js":6947,"./ar-sa":2682,"./ar-sa.js":2682,"./ar-tn":9756,"./ar-tn.js":9756,"./ar.js":1509,"./az":5533,"./az.js":5533,"./be":8959,"./be.js":8959,"./bg":7777,"./bg.js":7777,"./bm":4903,"./bm.js":4903,"./bn":1290,"./bn-bd":7357,"./bn-bd.js":7357,"./bn.js":1290,"./bo":1545,"./bo.js":1545,"./br":1470,"./br.js":1470,"./bs":4429,"./bs.js":4429,"./ca":7306,"./ca.js":7306,"./cs":6464,"./cs.js":6464,"./cv":3635,"./cv.js":3635,"./cy":4226,"./cy.js":4226,"./da":3601,"./da.js":3601,"./de":7853,"./de-at":6111,"./de-at.js":6111,"./de-ch":4697,"./de-ch.js":4697,"./de.js":7853,"./dv":708,"./dv.js":708,"./el":4691,"./el.js":4691,"./en-au":3872,"./en-au.js":3872,"./en-ca":8298,"./en-ca.js":8298,"./en-gb":6195,"./en-gb.js":6195,"./en-ie":6584,"./en-ie.js":6584,"./en-il":5543,"./en-il.js":5543,"./en-in":9033,"./en-in.js":9033,"./en-nz":9402,"./en-nz.js":9402,"./en-sg":3004,"./en-sg.js":3004,"./eo":2934,"./eo.js":2934,"./es":7650,"./es-do":838,"./es-do.js":838,"./es-mx":7730,"./es-mx.js":7730,"./es-us":6575,"./es-us.js":6575,"./es.js":7650,"./et":3035,"./et.js":3035,"./eu":3508,"./eu.js":3508,"./fa":119,"./fa.js":119,"./fi":527,"./fi.js":527,"./fil":5995,"./fil.js":5995,"./fo":2477,"./fo.js":2477,"./fr":5498,"./fr-ca":6435,"./fr-ca.js":6435,"./fr-ch":7892,"./fr-ch.js":7892,"./fr.js":5498,"./fy":7071,"./fy.js":7071,"./ga":1734,"./ga.js":1734,"./gd":217,"./gd.js":217,"./gl":7329,"./gl.js":7329,"./gom-deva":2124,"./gom-deva.js":2124,"./gom-latn":3383,"./gom-latn.js":3383,"./gu":5050,"./gu.js":5050,"./he":1713,"./he.js":1713,"./hi":3861,"./hi.js":3861,"./hr":6308,"./hr.js":6308,"./hu":609,"./hu.js":609,"./hy-am":7160,"./hy-am.js":7160,"./id":4063,"./id.js":4063,"./is":9374,"./is.js":9374,"./it":8383,"./it-ch":1827,"./it-ch.js":1827,"./it.js":8383,"./ja":3827,"./ja.js":3827,"./jv":9722,"./jv.js":9722,"./ka":1794,"./ka.js":1794,"./kk":7088,"./kk.js":7088,"./km":6870,"./km.js":6870,"./kn":4451,"./kn.js":4451,"./ko":3164,"./ko.js":3164,"./ku":8174,"./ku-kmr":6181,"./ku-kmr.js":6181,"./ku.js":8174,"./ky":8474,"./ky.js":8474,"./lb":9680,"./lb.js":9680,"./lo":5867,"./lo.js":5867,"./lt":5766,"./lt.js":5766,"./lv":9532,"./lv.js":9532,"./me":8076,"./me.js":8076,"./mi":1848,"./mi.js":1848,"./mk":306,"./mk.js":306,"./ml":3739,"./ml.js":3739,"./mn":9053,"./mn.js":9053,"./mr":6169,"./mr.js":6169,"./ms":3386,"./ms-my":2297,"./ms-my.js":2297,"./ms.js":3386,"./mt":7075,"./mt.js":7075,"./my":2264,"./my.js":2264,"./nb":2274,"./nb.js":2274,"./ne":8235,"./ne.js":8235,"./nl":2572,"./nl-be":3784,"./nl-be.js":3784,"./nl.js":2572,"./nn":4566,"./nn.js":4566,"./oc-lnc":9330,"./oc-lnc.js":9330,"./pa-in":9849,"./pa-in.js":9849,"./pl":4418,"./pl.js":4418,"./pt":9834,"./pt-br":8303,"./pt-br.js":8303,"./pt.js":9834,"./ro":4457,"./ro.js":4457,"./ru":2271,"./ru.js":2271,"./sd":1221,"./sd.js":1221,"./se":3478,"./se.js":3478,"./si":7538,"./si.js":7538,"./sk":5784,"./sk.js":5784,"./sl":6637,"./sl.js":6637,"./sq":6794,"./sq.js":6794,"./sr":5719,"./sr-cyrl":3322,"./sr-cyrl.js":3322,"./sr.js":5719,"./ss":6e3,"./ss.js":6e3,"./sv":1011,"./sv.js":1011,"./sw":748,"./sw.js":748,"./ta":1025,"./ta.js":1025,"./te":1885,"./te.js":1885,"./tet":8861,"./tet.js":8861,"./tg":6571,"./tg.js":6571,"./th":5802,"./th.js":5802,"./tk":9527,"./tk.js":9527,"./tl-ph":9231,"./tl-ph.js":9231,"./tlh":1052,"./tlh.js":1052,"./tr":5096,"./tr.js":5096,"./tzl":9846,"./tzl.js":9846,"./tzm":1765,"./tzm-latn":7711,"./tzm-latn.js":7711,"./tzm.js":1765,"./ug-cn":8414,"./ug-cn.js":8414,"./uk":6618,"./uk.js":6618,"./ur":158,"./ur.js":158,"./uz":7609,"./uz-latn":2475,"./uz-latn.js":2475,"./uz.js":7609,"./vi":1135,"./vi.js":1135,"./x-pseudo":4051,"./x-pseudo.js":4051,"./yo":2218,"./yo.js":2218,"./zh-cn":2648,"./zh-cn.js":2648,"./zh-hk":1632,"./zh-hk.js":1632,"./zh-mo":1541,"./zh-mo.js":1541,"./zh-tw":304,"./zh-tw.js":304};function n(e){var a=r(e);return t(a)}function r(e){if(!t.o(s,e)){var a=new Error("Cannot find module '"+e+"'");throw a.code="MODULE_NOT_FOUND",a}return s[e]}n.keys=function(){return Object.keys(s)},n.resolve=r,e.exports=n,n.id=5358},5093(e,a,t){(e=t.nmd(e)).exports=function(){"use strict";var a,s;function n(){return a.apply(null,arguments)}function r(e){a=e}function d(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function i(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function _(e,a){return Object.prototype.hasOwnProperty.call(e,a)}function o(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var a;for(a in e)if(_(e,a))return!1;return!0}function m(e){return void 0===e}function u(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function l(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function M(e,a){var t,s=[],n=e.length;for(t=0;t>>0;for(a=0;a0)for(t=0;t=0?t?"+":"":"-")+Math.pow(10,Math.max(0,n)).toString().substr(1)+s}var F=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,z=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,N={},J={};function R(e,a,t,s){var n=s;"string"==typeof s&&(n=function(){return this[s]()}),e&&(J[e]=n),a&&(J[a[0]]=function(){return E(n.apply(this,arguments),a[1],a[2])}),t&&(J[t]=function(){return this.localeData().ordinal(n.apply(this,arguments),e)})}function C(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function I(e){var a,t,s=e.match(F);for(a=0,t=s.length;a=0&&z.test(e);)e=e.replace(z,s),z.lastIndex=0,t-=1;return e}var V={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function q(e){var a=this._longDateFormat[e],t=this._longDateFormat[e.toUpperCase()];return a||!t?a:(this._longDateFormat[e]=t.match(F).map((function(e){return"MMMM"===e||"MM"===e||"DD"===e||"dddd"===e?e.slice(1):e})).join(""),this._longDateFormat[e])}var B="Invalid date";function K(){return this._invalidDate}var Z="%d",$=/\d{1,2}/;function Q(e){return this._ordinal.replace("%d",e)}var X={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function ee(e,a,t,s){var n=this._relativeTime[t];return j(n)?n(e,a,t,s):n.replace(/%d/i,e)}function ae(e,a){var t=this._relativeTime[e>0?"future":"past"];return j(t)?t(a):t.replace(/%s/i,a)}var te={D:"date",dates:"date",date:"date",d:"day",days:"day",day:"day",e:"weekday",weekdays:"weekday",weekday:"weekday",E:"isoWeekday",isoweekdays:"isoWeekday",isoweekday:"isoWeekday",DDD:"dayOfYear",dayofyears:"dayOfYear",dayofyear:"dayOfYear",h:"hour",hours:"hour",hour:"hour",ms:"millisecond",milliseconds:"millisecond",millisecond:"millisecond",m:"minute",minutes:"minute",minute:"minute",M:"month",months:"month",month:"month",Q:"quarter",quarters:"quarter",quarter:"quarter",s:"second",seconds:"second",second:"second",gg:"weekYear",weekyears:"weekYear",weekyear:"weekYear",GG:"isoWeekYear",isoweekyears:"isoWeekYear",isoweekyear:"isoWeekYear",w:"week",weeks:"week",week:"week",W:"isoWeek",isoweeks:"isoWeek",isoweek:"isoWeek",y:"year",years:"year",year:"year"};function se(e){return"string"==typeof e?te[e]||te[e.toLowerCase()]:void 0}function ne(e){var a,t,s={};for(t in e)_(e,t)&&(a=se(t))&&(s[a]=e[t]);return s}var re={date:9,day:11,weekday:11,isoWeekday:11,dayOfYear:4,hour:13,millisecond:16,minute:14,month:8,quarter:7,second:15,weekYear:1,isoWeekYear:1,week:5,isoWeek:5,year:1};function de(e){var a,t=[];for(a in e)_(e,a)&&t.push({unit:a,priority:re[a]});return t.sort((function(e,a){return e.priority-a.priority})),t}var ie,_e=/\d/,oe=/\d\d/,me=/\d{3}/,ue=/\d{4}/,le=/[+-]?\d{6}/,Me=/\d\d?/,he=/\d\d\d\d?/,ce=/\d\d\d\d\d\d?/,Le=/\d{1,3}/,Ye=/\d{1,4}/,ye=/[+-]?\d{1,6}/,fe=/\d+/,ke=/[+-]?\d+/,pe=/Z|[+-]\d\d:?\d\d/gi,De=/Z|[+-]\d\d(?::?\d\d)?/gi,Te=/[+-]?\d+(\.\d{1,3})?/,ge=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,we=/^[1-9]\d?/,ve=/^([1-9]\d|\d)/;function be(e,a,t){ie[e]=j(a)?a:function(e,s){return e&&t?t:a}}function He(e,a){return _(ie,e)?ie[e](a._strict,a._locale):new RegExp(Se(e))}function Se(e){return je(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,(function(e,a,t,s,n){return a||t||s||n})))}function je(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function xe(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function Pe(e){var a=+e,t=0;return 0!==a&&isFinite(a)&&(t=xe(a)),t}ie={};var Oe={};function We(e,a){var t,s,n=a;for("string"==typeof e&&(e=[e]),u(a)&&(n=function(e,t){t[a]=Pe(e)}),s=e.length,t=0;t68?1900:2e3)};var Be,Ke=$e("FullYear",!0);function Ze(){return Fe(this.year())}function $e(e,a){return function(t){return null!=t?(Xe(this,e,t),n.updateOffset(this,a),this):Qe(this,e)}}function Qe(e,a){if(!e.isValid())return NaN;var t=e._d,s=e._isUTC;switch(a){case"Milliseconds":return s?t.getUTCMilliseconds():t.getMilliseconds();case"Seconds":return s?t.getUTCSeconds():t.getSeconds();case"Minutes":return s?t.getUTCMinutes():t.getMinutes();case"Hours":return s?t.getUTCHours():t.getHours();case"Date":return s?t.getUTCDate():t.getDate();case"Day":return s?t.getUTCDay():t.getDay();case"Month":return s?t.getUTCMonth():t.getMonth();case"FullYear":return s?t.getUTCFullYear():t.getFullYear();default:return NaN}}function Xe(e,a,t){var s,n,r,d,i;if(e.isValid()&&!isNaN(t)){switch(s=e._d,n=e._isUTC,a){case"Milliseconds":return void(n?s.setUTCMilliseconds(t):s.setMilliseconds(t));case"Seconds":return void(n?s.setUTCSeconds(t):s.setSeconds(t));case"Minutes":return void(n?s.setUTCMinutes(t):s.setMinutes(t));case"Hours":return void(n?s.setUTCHours(t):s.setHours(t));case"Date":return void(n?s.setUTCDate(t):s.setDate(t));case"FullYear":break;default:return}r=t,d=e.month(),i=29!==(i=e.date())||1!==d||Fe(r)?i:28,n?s.setUTCFullYear(r,d,i):s.setFullYear(r,d,i)}}function ea(e){return j(this[e=se(e)])?this[e]():this}function aa(e,a){if("object"==typeof e){var t,s=de(e=ne(e)),n=s.length;for(t=0;t=0?(i=new Date(e+400,a,t,s,n,r,d),isFinite(i.getFullYear())&&i.setFullYear(e)):i=new Date(e,a,t,s,n,r,d),i}function ka(e){var a,t;return e<100&&e>=0?((t=Array.prototype.slice.call(arguments))[0]=e+400,a=new Date(Date.UTC.apply(null,t)),isFinite(a.getUTCFullYear())&&a.setUTCFullYear(e)):a=new Date(Date.UTC.apply(null,arguments)),a}function pa(e,a,t){var s=7+a-t;return-(7+ka(e,0,s).getUTCDay()-a)%7+s-1}function Da(e,a,t,s,n){var r,d,i=1+7*(a-1)+(7+t-s)%7+pa(e,s,n);return i<=0?d=qe(r=e-1)+i:i>qe(e)?(r=e+1,d=i-qe(e)):(r=e,d=i),{year:r,dayOfYear:d}}function Ta(e,a,t){var s,n,r=pa(e.year(),a,t),d=Math.floor((e.dayOfYear()-r-1)/7)+1;return d<1?s=d+ga(n=e.year()-1,a,t):d>ga(e.year(),a,t)?(s=d-ga(e.year(),a,t),n=e.year()+1):(n=e.year(),s=d),{week:s,year:n}}function ga(e,a,t){var s=pa(e,a,t),n=pa(e+1,a,t);return(qe(e)-s+n)/7}function wa(e){return Ta(e,this._week.dow,this._week.doy).week}R("w",["ww",2],"wo","week"),R("W",["WW",2],"Wo","isoWeek"),be("w",Me,we),be("ww",Me,oe),be("W",Me,we),be("WW",Me,oe),Ae(["w","ww","W","WW"],(function(e,a,t,s){a[s.substr(0,1)]=Pe(e)}));var va={dow:0,doy:6};function ba(){return this._week.dow}function Ha(){return this._week.doy}function Sa(e){var a=this.localeData().week(this);return null==e?a:this.add(7*(e-a),"d")}function ja(e){var a=Ta(this,1,4).week;return null==e?a:this.add(7*(e-a),"d")}function xa(e,a){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=a.weekdaysParse(e))?e:null:parseInt(e,10)}function Pa(e,a){return"string"==typeof e?a.weekdaysParse(e)%7||7:isNaN(e)?null:e}function Oa(e,a){return e.slice(a,7).concat(e.slice(0,a))}R("d",0,"do","day"),R("dd",0,0,(function(e){return this.localeData().weekdaysMin(this,e)})),R("ddd",0,0,(function(e){return this.localeData().weekdaysShort(this,e)})),R("dddd",0,0,(function(e){return this.localeData().weekdays(this,e)})),R("e",0,0,"weekday"),R("E",0,0,"isoWeekday"),be("d",Me),be("e",Me),be("E",Me),be("dd",(function(e,a){return a.weekdaysMinRegex(e)})),be("ddd",(function(e,a){return a.weekdaysShortRegex(e)})),be("dddd",(function(e,a){return a.weekdaysRegex(e)})),Ae(["dd","ddd","dddd"],(function(e,a,t,s){var n=t._locale.weekdaysParse(e,s,t._strict);null!=n?a.d=n:Y(t).invalidWeekday=e})),Ae(["d","e","E"],(function(e,a,t,s){a[s]=Pe(e)}));var Wa="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Aa="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Ea="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Fa=ge,za=ge,Na=ge;function Ja(e,a){var t=d(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(a)?"format":"standalone"];return!0===e?Oa(t,this._week.dow):e?t[e.day()]:t}function Ra(e){return!0===e?Oa(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function Ca(e){return!0===e?Oa(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function Ia(e,a,t){var s,n,r,d=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=c([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return t?"dddd"===a?-1!==(n=Be.call(this._weekdaysParse,d))?n:null:"ddd"===a?-1!==(n=Be.call(this._shortWeekdaysParse,d))?n:null:-1!==(n=Be.call(this._minWeekdaysParse,d))?n:null:"dddd"===a?-1!==(n=Be.call(this._weekdaysParse,d))||-1!==(n=Be.call(this._shortWeekdaysParse,d))||-1!==(n=Be.call(this._minWeekdaysParse,d))?n:null:"ddd"===a?-1!==(n=Be.call(this._shortWeekdaysParse,d))||-1!==(n=Be.call(this._weekdaysParse,d))||-1!==(n=Be.call(this._minWeekdaysParse,d))?n:null:-1!==(n=Be.call(this._minWeekdaysParse,d))||-1!==(n=Be.call(this._weekdaysParse,d))||-1!==(n=Be.call(this._shortWeekdaysParse,d))?n:null}function Ua(e,a,t){var s,n,r;if(this._weekdaysParseExact)return Ia.call(this,e,a,t);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(n=c([2e3,1]).day(s),t&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(n,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(n,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(n,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),t&&"dddd"===a&&this._fullWeekdaysParse[s].test(e))return s;if(t&&"ddd"===a&&this._shortWeekdaysParse[s].test(e))return s;if(t&&"dd"===a&&this._minWeekdaysParse[s].test(e))return s;if(!t&&this._weekdaysParse[s].test(e))return s}}function Ga(e){if(!this.isValid())return null!=e?this:NaN;var a=Qe(this,"Day");return null!=e?(e=xa(e,this.localeData()),this.add(e-a,"d")):a}function Va(e){if(!this.isValid())return null!=e?this:NaN;var a=(this.day()+7-this.localeData()._week.dow)%7;return null==e?a:this.add(e-a,"d")}function qa(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var a=Pa(e,this.localeData());return this.day(this.day()%7?a:a-7)}return this.day()||7}function Ba(e){return this._weekdaysParseExact?(_(this,"_weekdaysRegex")||$a.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(_(this,"_weekdaysRegex")||(this._weekdaysRegex=Fa),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function Ka(e){return this._weekdaysParseExact?(_(this,"_weekdaysRegex")||$a.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(_(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=za),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Za(e){return this._weekdaysParseExact?(_(this,"_weekdaysRegex")||$a.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(_(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Na),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function $a(){function e(e,a){return a.length-e.length}var a,t,s,n,r,d=[],i=[],_=[],o=[];for(a=0;a<7;a++)t=c([2e3,1]).day(a),s=je(this.weekdaysMin(t,"")),n=je(this.weekdaysShort(t,"")),r=je(this.weekdays(t,"")),d.push(s),i.push(n),_.push(r),o.push(s),o.push(n),o.push(r);d.sort(e),i.sort(e),_.sort(e),o.sort(e),this._weekdaysRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+_.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+d.join("|")+")","i")}function Qa(){return this.hours()%12||12}function Xa(){return this.hours()||24}function et(e,a){R(e,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)}))}function at(e,a){return a._meridiemParse}function tt(e){return"p"===(e+"").toLowerCase().charAt(0)}R("H",["HH",2],0,"hour"),R("h",["hh",2],0,Qa),R("k",["kk",2],0,Xa),R("hmm",0,0,(function(){return""+Qa.apply(this)+E(this.minutes(),2)})),R("hmmss",0,0,(function(){return""+Qa.apply(this)+E(this.minutes(),2)+E(this.seconds(),2)})),R("Hmm",0,0,(function(){return""+this.hours()+E(this.minutes(),2)})),R("Hmmss",0,0,(function(){return""+this.hours()+E(this.minutes(),2)+E(this.seconds(),2)})),et("a",!0),et("A",!1),be("a",at),be("A",at),be("H",Me,ve),be("h",Me,we),be("k",Me,we),be("HH",Me,oe),be("hh",Me,oe),be("kk",Me,oe),be("hmm",he),be("hmmss",ce),be("Hmm",he),be("Hmmss",ce),We(["H","HH"],Re),We(["k","kk"],(function(e,a,t){var s=Pe(e);a[Re]=24===s?0:s})),We(["a","A"],(function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e})),We(["h","hh"],(function(e,a,t){a[Re]=Pe(e),Y(t).bigHour=!0})),We("hmm",(function(e,a,t){var s=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s)),Y(t).bigHour=!0})),We("hmmss",(function(e,a,t){var s=e.length-4,n=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s,2)),a[Ie]=Pe(e.substr(n)),Y(t).bigHour=!0})),We("Hmm",(function(e,a,t){var s=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s))})),We("Hmmss",(function(e,a,t){var s=e.length-4,n=e.length-2;a[Re]=Pe(e.substr(0,s)),a[Ce]=Pe(e.substr(s,2)),a[Ie]=Pe(e.substr(n))}));var st=/[ap]\.?m?\.?/i,nt=$e("Hours",!0);function rt(e,a,t){return e>11?t?"pm":"PM":t?"am":"AM"}var dt,it={calendar:W,longDateFormat:V,invalidDate:B,ordinal:Z,dayOfMonthOrdinalParse:$,relativeTime:X,months:na,monthsShort:ra,week:va,weekdays:Wa,weekdaysMin:Ea,weekdaysShort:Aa,meridiemParse:st},_t={},ot={};function mt(e,a){var t,s=Math.min(e.length,a.length);for(t=0;t0;){if(s=ht(n.slice(0,a).join("-")))return s;if(t&&t.length>=a&&mt(n,t)>=a-1)break;a--}r++}return dt}function Mt(e){return!(!e||!e.match("^[^/\\\\]*$"))}function ht(a){var s=null;if(void 0===_t[a]&&e&&e.exports&&Mt(a))try{s=dt._abbr,t(5358)("./"+a),ct(s)}catch(e){_t[a]=null}return _t[a]}function ct(e,a){var t;return e&&((t=m(a)?yt(e):Lt(e,a))?dt=t:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),dt._abbr}function Lt(e,a){if(null!==a){var t,s=it;if(a.abbr=e,null!=_t[e])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=_t[e]._config;else if(null!=a.parentLocale)if(null!=_t[a.parentLocale])s=_t[a.parentLocale]._config;else{if(null==(t=ht(a.parentLocale)))return ot[a.parentLocale]||(ot[a.parentLocale]=[]),ot[a.parentLocale].push({name:e,config:a}),null;s=t._config}return _t[e]=new O(P(s,a)),ot[e]&&ot[e].forEach((function(e){Lt(e.name,e.config)})),ct(e),_t[e]}return delete _t[e],null}function Yt(e,a){if(null!=a){var t,s,n=it;null!=_t[e]&&null!=_t[e].parentLocale?_t[e].set(P(_t[e]._config,a)):(null!=(s=ht(e))&&(n=s._config),a=P(n,a),null==s&&(a.abbr=e),(t=new O(a)).parentLocale=_t[e],_t[e]=t),ct(e)}else null!=_t[e]&&(null!=_t[e].parentLocale?(_t[e]=_t[e].parentLocale,e===ct()&&ct(e)):null!=_t[e]&&delete _t[e]);return _t[e]}function yt(e){var a;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return dt;if(!d(e)){if(a=ht(e))return a;e=[e]}return lt(e)}function ft(){return b(_t)}function kt(e){var a,t=e._a;return t&&-2===Y(e).overflow&&(a=t[Ne]<0||t[Ne]>11?Ne:t[Je]<1||t[Je]>sa(t[ze],t[Ne])?Je:t[Re]<0||t[Re]>24||24===t[Re]&&(0!==t[Ce]||0!==t[Ie]||0!==t[Ue])?Re:t[Ce]<0||t[Ce]>59?Ce:t[Ie]<0||t[Ie]>59?Ie:t[Ue]<0||t[Ue]>999?Ue:-1,Y(e)._overflowDayOfYear&&(aJe)&&(a=Je),Y(e)._overflowWeeks&&-1===a&&(a=Ge),Y(e)._overflowWeekday&&-1===a&&(a=Ve),Y(e).overflow=a),e}var pt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Dt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Tt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],wt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],vt=/^\/?Date\((-?\d+)/i,bt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Ht={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function St(e){var a,t,s,n,r,d,i=e._i,_=pt.exec(i)||Dt.exec(i),o=gt.length,m=wt.length;if(_){for(Y(e).iso=!0,a=0,t=o;aqe(r)||0===e._dayOfYear)&&(Y(e)._overflowDayOfYear=!0),t=ka(r,0,e._dayOfYear),e._a[Ne]=t.getUTCMonth(),e._a[Je]=t.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=d[a]=s[a];for(;a<7;a++)e._a[a]=d[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[Re]&&0===e._a[Ce]&&0===e._a[Ie]&&0===e._a[Ue]&&(e._nextDay=!0,e._a[Re]=0),e._d=(e._useUTC?ka:fa).apply(null,d),n=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Re]=24),e._w&&void 0!==e._w.d&&e._w.d!==n&&(Y(e).weekdayMismatch=!0)}}function Jt(e){var a,t,s,n,r,d,i,_,o;null!=(a=e._w).GG||null!=a.W||null!=a.E?(r=1,d=4,t=Ft(a.GG,e._a[ze],Ta(Kt(),1,4).year),s=Ft(a.W,1),((n=Ft(a.E,1))<1||n>7)&&(_=!0)):(r=e._locale._week.dow,d=e._locale._week.doy,o=Ta(Kt(),r,d),t=Ft(a.gg,e._a[ze],o.year),s=Ft(a.w,o.week),null!=a.d?((n=a.d)<0||n>6)&&(_=!0):null!=a.e?(n=a.e+r,(a.e<0||a.e>6)&&(_=!0)):n=r),s<1||s>ga(t,r,d)?Y(e)._overflowWeeks=!0:null!=_?Y(e)._overflowWeekday=!0:(i=Da(t,s,n,r,d),e._a[ze]=i.year,e._dayOfYear=i.dayOfYear)}function Rt(e){if(e._f!==n.ISO_8601)if(e._f!==n.RFC_2822){e._a=[],Y(e).empty=!0;var a,t,s,r,d,i,_,o=""+e._i,m=o.length,u=0;for(_=(s=G(e._f,e._locale).match(F)||[]).length,a=0;a<_;a++)r=s[a],(t=(o.match(He(r,e))||[])[0])&&((d=o.substr(0,o.indexOf(t))).length>0&&Y(e).unusedInput.push(d),o=o.slice(o.indexOf(t)+t.length),u+=t.length),J[r]?(t?Y(e).empty=!1:Y(e).unusedTokens.push(r),Ee(r,t,e)):e._strict&&!t&&Y(e).unusedTokens.push(r);Y(e).charsLeftOver=m-u,o.length>0&&Y(e).unusedInput.push(o),e._a[Re]<=12&&!0===Y(e).bigHour&&e._a[Re]>0&&(Y(e).bigHour=void 0),Y(e).parsedDateParts=e._a.slice(0),Y(e).meridiem=e._meridiem,e._a[Re]=Ct(e._locale,e._a[Re],e._meridiem),null!==(i=Y(e).era)&&(e._a[ze]=e._locale.erasConvertYear(i,e._a[ze])),Nt(e),kt(e)}else At(e);else St(e)}function Ct(e,a,t){var s;return null==t?a:null!=e.meridiemHour?e.meridiemHour(a,t):null!=e.isPM?((s=e.isPM(t))&&a<12&&(a+=12),s||12!==a||(a=0),a):a}function It(e){var a,t,s,n,r,d,i=!1,_=e._f.length;if(0===_)return Y(e).invalidFormat=!0,void(e._d=new Date(NaN));for(n=0;n<_;n++)r=0,d=!1,a=D({},e),null!=e._useUTC&&(a._useUTC=e._useUTC),a._f=e._f[n],Rt(a),y(a)&&(d=!0),r+=Y(a).charsLeftOver,r+=10*Y(a).unusedTokens.length,Y(a).score=r,i?rthis?this:e:f()}));function Qt(e,a){var t,s;if(1===a.length&&d(a[0])&&(a=a[0]),!a.length)return Kt();for(t=a[0],s=1;sthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ds(){if(!m(this._isDSTShifted))return this._isDSTShifted;var e,a={};return D(a,this),(a=Vt(a))._a?(e=a._isUTC?c(a._a):Kt(a._a),this._isDSTShifted=this.isValid()&&os(a._a,e.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function Ts(){return!!this.isValid()&&!this._isUTC}function gs(){return!!this.isValid()&&this._isUTC}function ws(){return!!this.isValid()&&this._isUTC&&0===this._offset}n.updateOffset=function(){};var vs=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,bs=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Hs(e,a){var t,s,n,r=e,d=null;return is(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:u(e)||!isNaN(+e)?(r={},a?r[a]=+e:r.milliseconds=+e):(d=vs.exec(e))?(t="-"===d[1]?-1:1,r={y:0,d:Pe(d[Je])*t,h:Pe(d[Re])*t,m:Pe(d[Ce])*t,s:Pe(d[Ie])*t,ms:Pe(_s(1e3*d[Ue]))*t}):(d=bs.exec(e))?(t="-"===d[1]?-1:1,r={y:Ss(d[2],t),M:Ss(d[3],t),w:Ss(d[4],t),d:Ss(d[5],t),h:Ss(d[6],t),m:Ss(d[7],t),s:Ss(d[8],t)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(n=xs(Kt(r.from),Kt(r.to)),(r={}).ms=n.milliseconds,r.M=n.months),s=new ds(r),is(e)&&_(e,"_locale")&&(s._locale=e._locale),is(e)&&_(e,"_isValid")&&(s._isValid=e._isValid),s}function Ss(e,a){var t=e&&parseFloat(e.replace(",","."));return(isNaN(t)?0:t)*a}function js(e,a){var t={};return t.months=a.month()-e.month()+12*(a.year()-e.year()),e.clone().add(t.months,"M").isAfter(a)&&--t.months,t.milliseconds=+a-+e.clone().add(t.months,"M"),t}function xs(e,a){var t;return e.isValid()&&a.isValid()?(a=Ms(a,e),e.isBefore(a)?t=js(e,a):((t=js(a,e)).milliseconds=-t.milliseconds,t.months=-t.months),t):{milliseconds:0,months:0}}function Ps(e,a){return function(t,s){var n;return null===s||isNaN(+s)||(S(a,"moment()."+a+"(period, number) is deprecated. Please use moment()."+a+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=t,t=s,s=n),Os(this,Hs(t,s),e),this}}function Os(e,a,t,s){var r=a._milliseconds,d=_s(a._days),i=_s(a._months);e.isValid()&&(s=s??!0,i&&Ma(e,Qe(e,"Month")+i*t),d&&Xe(e,"Date",Qe(e,"Date")+d*t),r&&e._d.setTime(e._d.valueOf()+r*t),s&&n.updateOffset(e,d||i))}Hs.fn=ds.prototype,Hs.invalid=rs;var Ws=Ps(1,"add"),As=Ps(-1,"subtract");function Es(e){return"string"==typeof e||e instanceof String}function Fs(e){return g(e)||l(e)||Es(e)||u(e)||Ns(e)||zs(e)||null==e}function zs(e){var a,t,s=i(e)&&!o(e),n=!1,r=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],d=r.length;for(a=0;at.valueOf():t.valueOf()9999?U(t,a?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):j(Date.prototype.toISOString)?a?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",U(t,"Z")):U(t,a?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function en(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e,a,t,s,n="moment",r="";return this.isLocal()||(n=0===this.utcOffset()?"moment.utc":"moment.parseZone",r="Z"),e="["+n+'("]',a=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",t="-MM-DD[T]HH:mm:ss.SSS",s=r+'[")]',this.format(e+a+t+s)}function an(e){e||(e=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var a=U(this,e);return this.localeData().postformat(a)}function tn(e,a){return this.isValid()&&(g(e)&&e.isValid()||Kt(e).isValid())?Hs({to:this,from:e}).locale(this.locale()).humanize(!a):this.localeData().invalidDate()}function sn(e){return this.from(Kt(),e)}function nn(e,a){return this.isValid()&&(g(e)&&e.isValid()||Kt(e).isValid())?Hs({from:this,to:e}).locale(this.locale()).humanize(!a):this.localeData().invalidDate()}function rn(e){return this.to(Kt(),e)}function dn(e){var a;return void 0===e?this._locale._abbr:(null!=(a=yt(e))&&(this._locale=a),this)}n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var _n=v("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(e){return void 0===e?this.localeData():this.locale(e)}));function on(){return this._locale}var mn=1e3,un=60*mn,ln=60*un,Mn=3506328*ln;function hn(e,a){return(e%a+a)%a}function cn(e,a,t){return e<100&&e>=0?new Date(e+400,a,t)-Mn:new Date(e,a,t).valueOf()}function Ln(e,a,t){return e<100&&e>=0?Date.UTC(e+400,a,t)-Mn:Date.UTC(e,a,t)}function Yn(e){var a,t;if(void 0===(e=se(e))||"millisecond"===e||!this.isValid())return this;switch(t=this._isUTC?Ln:cn,e){case"year":a=t(this.year(),0,1);break;case"quarter":a=t(this.year(),this.month()-this.month()%3,1);break;case"month":a=t(this.year(),this.month(),1);break;case"week":a=t(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":a=t(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":a=t(this.year(),this.month(),this.date());break;case"hour":a=this._d.valueOf(),a-=hn(a+(this._isUTC?0:this.utcOffset()*un),ln);break;case"minute":a=this._d.valueOf(),a-=hn(a,un);break;case"second":a=this._d.valueOf(),a-=hn(a,mn)}return this._d.setTime(a),n.updateOffset(this,!0),this}function yn(e){var a,t;if(void 0===(e=se(e))||"millisecond"===e||!this.isValid())return this;switch(t=this._isUTC?Ln:cn,e){case"year":a=t(this.year()+1,0,1)-1;break;case"quarter":a=t(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":a=t(this.year(),this.month()+1,1)-1;break;case"week":a=t(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":a=t(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":a=t(this.year(),this.month(),this.date()+1)-1;break;case"hour":a=this._d.valueOf(),a+=ln-hn(a+(this._isUTC?0:this.utcOffset()*un),ln)-1;break;case"minute":a=this._d.valueOf(),a+=un-hn(a,un)-1;break;case"second":a=this._d.valueOf(),a+=mn-hn(a,mn)-1}return this._d.setTime(a),n.updateOffset(this,!0),this}function fn(){return this._d.valueOf()-6e4*(this._offset||0)}function kn(){return Math.floor(this.valueOf()/1e3)}function pn(){return new Date(this.valueOf())}function Dn(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function Tn(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function gn(){return this.isValid()?this.toISOString():null}function wn(){return y(this)}function vn(){return h({},Y(this))}function bn(){return Y(this).overflow}function Hn(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Sn(e,a){var t,s,r,d=this._eras||yt("en")._eras;for(t=0,s=d.length;t=0)return _[s]}function xn(e,a){var t=e.since<=e.until?1:-1;return void 0===a?n(e.since).year():n(e.since).year()+(a-e.offset)*t}function Pn(){var e,a,t,s=this.localeData().eras();for(e=0,a=s.length;e(r=ga(e,s,n))&&(a=r),Qn.call(this,e,a,t,s,n))}function Qn(e,a,t,s,n){var r=Da(e,a,t,s,n),d=ka(r.year,0,r.dayOfYear);return this.year(d.getUTCFullYear()),this.month(d.getUTCMonth()),this.date(d.getUTCDate()),this}function Xn(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)}R("N",0,0,"eraAbbr"),R("NN",0,0,"eraAbbr"),R("NNN",0,0,"eraAbbr"),R("NNNN",0,0,"eraName"),R("NNNNN",0,0,"eraNarrow"),R("y",["y",1],"yo","eraYear"),R("y",["yy",2],0,"eraYear"),R("y",["yyy",3],0,"eraYear"),R("y",["yyyy",4],0,"eraYear"),be("N",Nn),be("NN",Nn),be("NNN",Nn),be("NNNN",Jn),be("NNNNN",Rn),We(["N","NN","NNN","NNNN","NNNNN"],(function(e,a,t,s){var n=t._locale.erasParse(e,s,t._strict);n?Y(t).era=n:Y(t).invalidEra=e})),be("y",fe),be("yy",fe),be("yyy",fe),be("yyyy",fe),be("yo",Cn),We(["y","yy","yyy","yyyy"],ze),We(["yo"],(function(e,a,t,s){var n;t._locale._eraYearOrdinalRegex&&(n=e.match(t._locale._eraYearOrdinalRegex)),t._locale.eraYearOrdinalParse?a[ze]=t._locale.eraYearOrdinalParse(e,n):a[ze]=parseInt(e,10)})),R(0,["gg",2],0,(function(){return this.weekYear()%100})),R(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),Un("gggg","weekYear"),Un("ggggg","weekYear"),Un("GGGG","isoWeekYear"),Un("GGGGG","isoWeekYear"),be("G",ke),be("g",ke),be("GG",Me,oe),be("gg",Me,oe),be("GGGG",Ye,ue),be("gggg",Ye,ue),be("GGGGG",ye,le),be("ggggg",ye,le),Ae(["gggg","ggggg","GGGG","GGGGG"],(function(e,a,t,s){a[s.substr(0,2)]=Pe(e)})),Ae(["gg","GG"],(function(e,a,t,s){a[s]=n.parseTwoDigitYear(e)})),R("Q",0,"Qo","quarter"),be("Q",_e),We("Q",(function(e,a){a[Ne]=3*(Pe(e)-1)})),R("D",["DD",2],"Do","date"),be("D",Me,we),be("DD",Me,oe),be("Do",(function(e,a){return e?a._dayOfMonthOrdinalParse||a._ordinalParse:a._dayOfMonthOrdinalParseLenient})),We(["D","DD"],Je),We("Do",(function(e,a){a[Je]=Pe(e.match(Me)[0])}));var er=$e("Date",!0);function ar(e){var a=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?a:this.add(e-a,"d")}R("DDD",["DDDD",3],"DDDo","dayOfYear"),be("DDD",Le),be("DDDD",me),We(["DDD","DDDD"],(function(e,a,t){t._dayOfYear=Pe(e)})),R("m",["mm",2],0,"minute"),be("m",Me,ve),be("mm",Me,oe),We(["m","mm"],Ce);var tr=$e("Minutes",!1);R("s",["ss",2],0,"second"),be("s",Me,ve),be("ss",Me,oe),We(["s","ss"],Ie);var sr,nr,rr=$e("Seconds",!1);for(R("S",0,0,(function(){return~~(this.millisecond()/100)})),R(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),R(0,["SSS",3],0,"millisecond"),R(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),R(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),R(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),R(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),R(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),R(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),be("S",Le,_e),be("SS",Le,oe),be("SSS",Le,me),sr="SSSS";sr.length<=9;sr+="S")be(sr,fe);function dr(e,a){a[Ue]=Pe(1e3*("0."+e))}for(sr="S";sr.length<=9;sr+="S")We(sr,dr);function ir(){return this._isUTC?"UTC":""}function _r(){return this._isUTC?"Coordinated Universal Time":""}nr=$e("Milliseconds",!1),R("z",0,0,"zoneAbbr"),R("zz",0,0,"zoneName");var or=T.prototype;function mr(e){return Kt(1e3*e)}function ur(){return Kt.apply(null,arguments).parseZone()}function lr(e){return e}or.add=Ws,or.calendar=Cs,or.clone=Is,or.diff=Zs,or.endOf=yn,or.format=an,or.from=tn,or.fromNow=sn,or.to=nn,or.toNow=rn,or.get=ea,or.invalidAt=bn,or.isAfter=Us,or.isBefore=Gs,or.isBetween=Vs,or.isSame=qs,or.isSameOrAfter=Bs,or.isSameOrBefore=Ks,or.isValid=wn,or.lang=_n,or.locale=dn,or.localeData=on,or.max=$t,or.min=Zt,or.parsingFlags=vn,or.set=aa,or.startOf=Yn,or.subtract=As,or.toArray=Dn,or.toObject=Tn,or.toDate=pn,or.toISOString=Xs,or.inspect=en,"undefined"!=typeof Symbol&&null!=Symbol.for&&(or[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),or.toJSON=gn,or.toString=Qs,or.unix=kn,or.valueOf=fn,or.creationData=Hn,or.eraName=Pn,or.eraNarrow=On,or.eraAbbr=Wn,or.eraYear=An,or.year=Ke,or.isLeapYear=Ze,or.weekYear=Gn,or.isoWeekYear=Vn,or.quarter=or.quarters=Xn,or.month=ha,or.daysInMonth=ca,or.week=or.weeks=Sa,or.isoWeek=or.isoWeeks=ja,or.weeksInYear=Kn,or.weeksInWeekYear=Zn,or.isoWeeksInYear=qn,or.isoWeeksInISOWeekYear=Bn,or.date=er,or.day=or.days=Ga,or.weekday=Va,or.isoWeekday=qa,or.dayOfYear=ar,or.hour=or.hours=nt,or.minute=or.minutes=tr,or.second=or.seconds=rr,or.millisecond=or.milliseconds=nr,or.utcOffset=cs,or.utc=Ys,or.local=ys,or.parseZone=fs,or.hasAlignedHourOffset=ks,or.isDST=ps,or.isLocal=Ts,or.isUtcOffset=gs,or.isUtc=ws,or.isUTC=ws,or.zoneAbbr=ir,or.zoneName=_r,or.dates=v("dates accessor is deprecated. Use date instead.",er),or.months=v("months accessor is deprecated. Use month instead",ha),or.years=v("years accessor is deprecated. Use year instead",Ke),or.zone=v("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Ls),or.isDSTShifted=v("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ds);var Mr=O.prototype;function hr(e,a,t,s){var n=yt(),r=c().set(s,a);return n[t](r,e)}function cr(e,a,t){if(u(e)&&(a=e,e=void 0),e=e||"",null!=a)return hr(e,a,t,"month");var s,n=[];for(s=0;s<12;s++)n[s]=hr(e,s,t,"month");return n}function Lr(e,a,t,s){"boolean"==typeof e?(u(a)&&(t=a,a=void 0),a=a||""):(t=a=e,e=!1,u(a)&&(t=a,a=void 0),a=a||"");var n,r=yt(),d=e?r._week.dow:0,i=[];if(null!=t)return hr(a,(t+d)%7,s,"day");for(n=0;n<7;n++)i[n]=hr(a,(n+d)%7,s,"day");return i}function Yr(e,a){return cr(e,a,"months")}function yr(e,a){return cr(e,a,"monthsShort")}function fr(e,a,t){return Lr(e,a,t,"weekdays")}function kr(e,a,t){return Lr(e,a,t,"weekdaysShort")}function pr(e,a,t){return Lr(e,a,t,"weekdaysMin")}Mr.calendar=A,Mr.longDateFormat=q,Mr.invalidDate=K,Mr.ordinal=Q,Mr.preparse=lr,Mr.postformat=lr,Mr.relativeTime=ee,Mr.pastFuture=ae,Mr.set=x,Mr.eras=Sn,Mr.erasParse=jn,Mr.erasConvertYear=xn,Mr.erasAbbrRegex=Fn,Mr.erasNameRegex=En,Mr.erasNarrowRegex=zn,Mr.months=oa,Mr.monthsShort=ma,Mr.monthsParse=la,Mr.monthsRegex=Ya,Mr.monthsShortRegex=La,Mr.week=wa,Mr.firstDayOfYear=Ha,Mr.firstDayOfWeek=ba,Mr.weekdays=Ja,Mr.weekdaysMin=Ca,Mr.weekdaysShort=Ra,Mr.weekdaysParse=Ua,Mr.weekdaysRegex=Ba,Mr.weekdaysShortRegex=Ka,Mr.weekdaysMinRegex=Za,Mr.isPM=tt,Mr.meridiem=rt,ct("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var a=e%10;return e+(1===Pe(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}}),n.lang=v("moment.lang is deprecated. Use moment.locale instead.",ct),n.langData=v("moment.langData is deprecated. Use moment.localeData instead.",yt);var Dr=Math.abs;function Tr(){var e=this._data;return this._milliseconds=Dr(this._milliseconds),this._days=Dr(this._days),this._months=Dr(this._months),e.milliseconds=Dr(e.milliseconds),e.seconds=Dr(e.seconds),e.minutes=Dr(e.minutes),e.hours=Dr(e.hours),e.months=Dr(e.months),e.years=Dr(e.years),this}function gr(e,a,t,s){var n=Hs(a,t);return e._milliseconds+=s*n._milliseconds,e._days+=s*n._days,e._months+=s*n._months,e._bubble()}function wr(e,a){return gr(this,e,a,1)}function vr(e,a){return gr(this,e,a,-1)}function br(e){return e<0?Math.floor(e):Math.ceil(e)}function Hr(){var e,a,t,s,n,r=this._milliseconds,d=this._days,i=this._months,_=this._data;return r>=0&&d>=0&&i>=0||r<=0&&d<=0&&i<=0||(r+=864e5*br(jr(i)+d),d=0,i=0),_.milliseconds=r%1e3,e=xe(r/1e3),_.seconds=e%60,a=xe(e/60),_.minutes=a%60,t=xe(a/60),_.hours=t%24,d+=xe(t/24),i+=n=xe(Sr(d)),d-=br(jr(n)),s=xe(i/12),i%=12,_.days=d,_.months=i,_.years=s,this}function Sr(e){return 4800*e/146097}function jr(e){return 146097*e/4800}function xr(e){if(!this.isValid())return NaN;var a,t,s=this._milliseconds;if("month"===(e=se(e))||"quarter"===e||"year"===e)switch(a=this._days+s/864e5,t=this._months+Sr(a),e){case"month":return t;case"quarter":return t/3;case"year":return t/12}else switch(a=this._days+Math.round(jr(this._months)),e){case"week":return a/7+s/6048e5;case"day":return a+s/864e5;case"hour":return 24*a+s/36e5;case"minute":return 1440*a+s/6e4;case"second":return 86400*a+s/1e3;case"millisecond":return Math.floor(864e5*a)+s;default:throw new Error("Unknown unit "+e)}}function Pr(e){return function(){return this.as(e)}}var Or=Pr("ms"),Wr=Pr("s"),Ar=Pr("m"),Er=Pr("h"),Fr=Pr("d"),zr=Pr("w"),Nr=Pr("M"),Jr=Pr("Q"),Rr=Pr("y"),Cr=Or;function Ir(){return Hs(this)}function Ur(e){return e=se(e),this.isValid()?this[e+"s"]():NaN}function Gr(e){return function(){return this.isValid()?this._data[e]:NaN}}var Vr=Gr("milliseconds"),qr=Gr("seconds"),Br=Gr("minutes"),Kr=Gr("hours"),Zr=Gr("days"),$r=Gr("months"),Qr=Gr("years");function Xr(){return xe(this.days()/7)}var ed=Math.round,ad={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function td(e,a,t,s,n){return n.relativeTime(a||1,!!t,e,s)}function sd(e,a,t,s){var n=Hs(e).abs(),r=ed(n.as("s")),d=ed(n.as("m")),i=ed(n.as("h")),_=ed(n.as("d")),o=ed(n.as("M")),m=ed(n.as("w")),u=ed(n.as("y")),l=r<=t.ss&&["s",r]||r0,l[4]=s,td.apply(null,l)}function nd(e){return void 0===e?ed:"function"==typeof e&&(ed=e,!0)}function rd(e,a){return void 0!==ad[e]&&(void 0===a?ad[e]:(ad[e]=a,"s"===e&&(ad.ss=a-1),!0))}function dd(e,a){if(!this.isValid())return this.localeData().invalidDate();var t,s,n=!1,r=ad;return"object"==typeof e&&(a=e,e=!1),"boolean"==typeof e&&(n=e),"object"==typeof a&&(r=Object.assign({},ad,a),null!=a.s&&null==a.ss&&(r.ss=a.s-1)),s=sd(this,!n,r,t=this.localeData()),n&&(s=t.pastFuture(+this,s)),t.postformat(s)}var id=Math.abs;function _d(e){return(e>0)-(e<0)||+e}function od(){if(!this.isValid())return this.localeData().invalidDate();var e,a,t,s,n,r,d,i,_=id(this._milliseconds)/1e3,o=id(this._days),m=id(this._months),u=this.asSeconds();return u?(e=xe(_/60),a=xe(e/60),_%=60,e%=60,t=xe(m/12),m%=12,s=_?_.toFixed(3).replace(/\.?0+$/,""):"",n=u<0?"-":"",r=_d(this._months)!==_d(u)?"-":"",d=_d(this._days)!==_d(u)?"-":"",i=_d(this._milliseconds)!==_d(u)?"-":"",n+"P"+(t?r+t+"Y":"")+(m?r+m+"M":"")+(o?d+o+"D":"")+(a||e||_?"T":"")+(a?i+a+"H":"")+(e?i+e+"M":"")+(_?i+s+"S":"")):"P0D"}var md=ds.prototype;return md.isValid=ns,md.abs=Tr,md.add=wr,md.subtract=vr,md.as=xr,md.asMilliseconds=Or,md.asSeconds=Wr,md.asMinutes=Ar,md.asHours=Er,md.asDays=Fr,md.asWeeks=zr,md.asMonths=Nr,md.asQuarters=Jr,md.asYears=Rr,md.valueOf=Cr,md._bubble=Hr,md.clone=Ir,md.get=Ur,md.milliseconds=Vr,md.seconds=qr,md.minutes=Br,md.hours=Kr,md.days=Zr,md.weeks=Xr,md.months=$r,md.years=Qr,md.humanize=dd,md.toISOString=od,md.toString=od,md.toJSON=od,md.locale=dn,md.localeData=on,md.toIsoString=v("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",od),md.lang=_n,R("X",0,0,"unix"),R("x",0,0,"valueOf"),be("x",ke),be("X",Te),We("X",(function(e,a,t){t._d=new Date(1e3*parseFloat(e))})),We("x",(function(e,a,t){t._d=new Date(Pe(e))})), //! moment.js -n.version="2.30.1",r(Kt),n.fn=or,n.min=Xt,n.max=es,n.now=as,n.utc=c,n.unix=ur,n.months=Yr,n.isDate=l,n.locale=ct,n.invalid=f,n.duration=Hs,n.isMoment=g,n.weekdays=fr,n.parseZone=mr,n.localeData=yt,n.isDuration=ds,n.monthsShort=yr,n.weekdaysMin=pr,n.defineLocale=Lt,n.updateLocale=Yt,n.locales=ft,n.weekdaysShort=kr,n.normalizeUnits=se,n.relativeTimeRounding=ni,n.relativeTimeThreshold=ri,n.calendarFormat=Rs,n.prototype=or,n.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},n}()},5946:(e,a,t)=>{e.exports=t(5093)}},a={};function t(s){var n=a[s];if(void 0!==n)return n.exports;var r=a[s]={id:s,loaded:!1,exports:{}};return e[s].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}return t.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),t.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),t(5946)})())); \ No newline at end of file +n.version="2.30.1",r(Kt),n.fn=or,n.min=Xt,n.max=es,n.now=as,n.utc=c,n.unix=mr,n.months=Yr,n.isDate=l,n.locale=ct,n.invalid=f,n.duration=Hs,n.isMoment=g,n.weekdays=fr,n.parseZone=ur,n.localeData=yt,n.isDuration=is,n.monthsShort=yr,n.weekdaysMin=pr,n.defineLocale=Lt,n.updateLocale=Yt,n.locales=ft,n.weekdaysShort=kr,n.normalizeUnits=se,n.relativeTimeRounding=nd,n.relativeTimeThreshold=rd,n.calendarFormat=Rs,n.prototype=or,n.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},n}()},5946(e,a,t){e.exports=t(5093)}},a={};function t(s){var n=a[s];if(void 0!==n)return n.exports;var r=a[s]={id:s,loaded:!1,exports:{}};return e[s].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}return t.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),t.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),t(5946)})())); \ No newline at end of file diff --git a/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/package-lock.json b/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/package-lock.json index 71fe669cc..b67190b2a 100644 --- a/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/package-lock.json +++ b/src/modules/Elsa.Expressions.JavaScript.Libraries/ClientLib/package-lock.json @@ -84,16 +84,18 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "22.7.4", @@ -105,148 +107,163 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -298,19 +315,22 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "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 + "dev": true, + "license": "Apache-2.0" }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -318,44 +338,84 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, "peerDependencies": { - "acorn": "^8" + "acorn": "^8.14.0" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "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" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, - "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==", + "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, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, "peerDependencies": { - "ajv": "^6.9.1" + "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, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", + "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "dev": true, "funding": [ { @@ -371,11 +431,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -391,9 +453,9 @@ "dev": true }, "node_modules/caniuse-lite": { - "version": "1.0.30001667", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", - "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", "dev": true, "funding": [ { @@ -408,7 +470,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chrome-trace-event": { "version": "1.0.4", @@ -446,10 +509,11 @@ "dev": true }, "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==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -460,19 +524,21 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.32", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", - "integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==", - "dev": true + "version": "1.5.364", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz", + "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==", + "dev": true, + "license": "ISC" }, "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -491,16 +557,18 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -561,13 +629,25 @@ "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 + "dev": true, + "license": "MIT" }, - "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-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -613,13 +693,15 @@ "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 + "dev": true, + "license": "BSD-2-Clause" }, "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 + "dev": true, + "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", @@ -726,17 +808,12 @@ "node": ">= 10.13.0" } }, - "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": "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 + "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, + "license": "MIT" }, "node_modules/kind-of": { "version": "6.0.3", @@ -748,12 +825,17 @@ } }, "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==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/locate-path": { @@ -769,10 +851,11 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", @@ -781,22 +864,11 @@ "dev": true }, "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==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "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" - }, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -817,10 +889,14 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/p-limit": { "version": "2.3.0", @@ -883,10 +959,11 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/pkg-dir": { "version": "4.2.0", @@ -900,24 +977,6 @@ "node": ">=8" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -930,6 +989,16 @@ "node": ">= 10.13.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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -968,35 +1037,17 @@ "node": ">=8" } }, - "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/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 10.13.0" @@ -1006,15 +1057,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -1095,12 +1137,17 @@ } }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/terser": { @@ -1122,16 +1169,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -1144,12 +1191,39 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } @@ -1162,9 +1236,9 @@ "dev": true }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -1180,9 +1254,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -1191,20 +1266,12 @@ "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/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -1214,34 +1281,35 @@ } }, "node_modules/webpack": { - "version": "5.95.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", - "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -1328,10 +1396,11 @@ } }, "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==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } @@ -1415,9 +1484,9 @@ } }, "@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true }, "@types/json-schema": { @@ -1436,148 +1505,148 @@ } }, "@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true }, "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -1615,47 +1684,65 @@ "dev": true }, "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true }, - "acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, "requires": {} }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "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" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "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, + "requires": { + "ajv": "^8.0.0" } }, "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, - "requires": {} - }, - "browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "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, "requires": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "fast-deep-equal": "^3.1.3" + } + }, + "baseline-browser-mapping": { + "version": "2.10.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", + "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "dev": true + }, + "browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "requires": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" } }, "buffer-from": { @@ -1665,9 +1752,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001667", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", - "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", "dev": true }, "chrome-trace-event": { @@ -1700,9 +1787,9 @@ "dev": true }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -1711,19 +1798,19 @@ } }, "electron-to-chromium": { - "version": "1.5.32", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", - "integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==", + "version": "1.5.364", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz", + "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==", "dev": true }, "enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "dev": true, "requires": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" } }, "envinfo": { @@ -1733,9 +1820,9 @@ "dev": true }, "es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true }, "escalade": { @@ -1789,10 +1876,10 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "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==", + "fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true }, "fastest-levenshtein": { @@ -1907,16 +1994,10 @@ "supports-color": "^8.0.0" } }, - "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 - }, "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==", + "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 }, "kind-of": { @@ -1926,9 +2007,9 @@ "dev": true }, "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==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true }, "locate-path": { @@ -1941,9 +2022,9 @@ } }, "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true }, "merge-stream": { @@ -1953,20 +2034,11 @@ "dev": true }, "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true }, - "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, - "requires": { - "mime-db": "1.52.0" - } - }, "moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -1980,9 +2052,9 @@ "dev": true }, "node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", "dev": true }, "p-limit": { @@ -2028,9 +2100,9 @@ "dev": true }, "picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "pkg-dir": { @@ -2042,21 +2114,6 @@ "find-up": "^4.0.0" } }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, "rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -2066,6 +2123,12 @@ "resolve": "^1.20.0" } }, + "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 + }, "resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -2092,30 +2155,16 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "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 - }, "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" } }, "shallow-clone": { @@ -2174,9 +2223,9 @@ "dev": true }, "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true }, "terser": { @@ -2192,16 +2241,15 @@ } }, "terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "terser": "^5.31.1" } }, "undici-types": { @@ -2211,28 +2259,19 @@ "dev": true }, "update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "requires": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" + "picocolors": "^1.1.1" } }, "watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -2240,34 +2279,34 @@ } }, "webpack": { - "version": "5.95.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", - "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "dev": true, "requires": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" } }, "webpack-cli": { @@ -2311,9 +2350,9 @@ } }, "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==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "dev": true }, "which": { From b280a711b2097c28f1f832e324c629c5fe06563c Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 31 May 2026 09:40:02 +0200 Subject: [PATCH 5/6] [codex] Fix diagnostics live feed regressions (#7548) * Avoid null endpoint DTO metadata in tests * Enforce console logs hub read permission * Remove unused console logs hub import * Support mapped endpoint metadata in auth tests * Reduce console log capture throughput impact * Address Copilot console logs review * Refactor task scheduling to support tenant-level background work and enhance logging functionality. * Introduce ConsoleStreamHook for stdout/stderr tee and enhance logging validation. Adjust test cases and startup warnings for distributed lock provider usage. * Refactor console logging pipeline with capture optimization and new ConsoleLogsHost; update tests accordingly. * Add Ansi SGR parser for console logs and associated unit tests * Remove ANSI color renderings and parsers; integrate ConsoleLogScopeAccessor for improved logging context with workflow instance ID support. * Address console logs code quality feedback * Address PR review feedback * Preserve console logs extension points * Stabilize console logs host lifecycle * Address final automated review comments * Tighten console log capture shutdown * Address console log review feedback * Address follow-up review feedback * Cover final review feedback * Avoid recursive console provider initialization * Guard console host lease shutdown * Preserve console log scope and provider lifetime * Correlate console log scope fallback * Tighten console scope correlation * Expose host services during provider construction * Redact ANSI-normalized console lines * Add OpenTelemetry diagnostics backend foundation * Add OTLP HTTP ingestion parsing * Document OpenTelemetry diagnostics setup * Enforce OpenTelemetry hub permissions * Remove `ConsoleCaptureTee` and related services and tests * Add OpenTelemetry HTTP ingestion integration test * Use pipeline contributors for console log context * Update CShells package versions to 0.0.24-preview.132 * Add OpenTelemetry ingestion security tests * Add OpenTelemetry API authorization tests * Filter live console logs by workflow instance * Add OpenTelemetry hub tests * Add OpenTelemetry gRPC metadata hook * Assert OpenTelemetry workflow tags survive ingestion * Mark OpenTelemetry core build verified * Enhance console logging with activity execution metadata and extend test coverage. * Address console logs stream consumption comment * Wire OpenTelemetry diagnostics into core sample * Address Core diagnostics review feedback * Address Core Copilot follow-up feedback * Add OpenTelemetry metric instrument names * Address Core Copilot provider feedback * Address Core Copilot diagnostics follow-up * Address Core Copilot live feed feedback * Address Core Copilot store feedback * Integrate OpenTelemetry for logging, tracing, and metrics in ModularServer and update launch settings and docker-compose configuration. * Refactor to replace `ConsoleLogStream.Core` with `ConsoleLogStreaming.Core` across codebase and update `ConsoleStreamHook` installation. * Add diagnostics OpenTelemetry backend * Fix OpenTelemetry live hub subscription * Fix modular OpenTelemetry exporter endpoints * Add CShells logging configuration in appsettings.json * Remove obsolete unit tests and helper classes * Restore default activity exception handling * Simplify type serialization and alias management This commit refactors the internal type serialization and alias management system to reduce boilerplate, improve robustness, and simplify the developer experience: - Removed numerous explicit `ExpressionOptions` type alias registrations across various modules. - Updated `TypeJsonConverter` and polymorphic serialization to reliably handle types using assembly-qualified names when a short alias is not explicitly registered. - Streamlined `ExcludeFromHashConverter` to strictly adhere to `ExcludeFromHashAttribute` for hash calculations, removing complex `JsonIgnoreCondition` logic. - Eliminated several helper classes (`WorkflowJsonTypeResolver`, `WorkflowTypeValidator`, `IWorkflowTypeRegistry`, `WorkflowFactoryDictionary`, `JavaScriptExceptionTypeAliasRegistrar`, `WorkflowRuntimeTypeAliasRegistrar`) and their associated unit tests, simplifying the codebase. Additionally, this commit introduces a comprehensive markdown document (`product-website-feature-source.md`) outlining Elsa's core features, Studio capabilities, extension ecosystem, and architectural selling points, intended as source material for the product website. * Refine type serialization for improved robustness and alias handling This commit further enhances the type serialization and deserialization mechanisms: * Centralizes type resolution and alias management through `IWellKnownTypeRegistry` and `WorkflowJsonTypeResolver`. * Prioritizes registered type aliases when serializing type metadata in `PolymorphicObjectConverter`, resulting in more concise JSON output. * Enhances deserialization in `PolymorphicObjectConverter` and `VariableMapper` to gracefully handle unknown or non-instantiable types, providing fallbacks and logging warnings. * Simplifies `TypeJsonConverter` by delegating complex type resolution logic to the `WorkflowJsonTypeResolver`. * Adds `JsonArray` to the well-known type aliases for direct recognition. * Fix console logs packaging and workflow type resolution * Fix console log metadata and type resolution * Address Copilot review feedback * Enhance type resolution, improve console log handling, and update tests - Streamlined `WorkflowDictionaryExtensions` for better workflow registration validation. - Refined `ConsoleLogsAuthorizationTests` with the new `SetJsonRequest` helper to improve test requests handling. - Updated `OrderDefinition` to ignore JSON serialization for `KeySelector`. - Enhanced `WorkflowRuntimeFeature` for improved workflow registration and type alias configuration. - Added tests to ensure `ConsoleLogProvider` metadata filtration in various scenarios. - Improved type serialization logic in `WorkflowJsonTypeResolver`. - Updated README to fix references related to diagnostics. - Optimized `ExcludeFromHashConverter` for property serialization conditions. - Modified `TriggerIndexer` for streamlined trigger management. - Tested payload checks in `PublishEventTests`. - Adjusted `Endpoint` in `ConsoleLogs` for automatic JSON request handling. - Ensured registration of workflow type aliases in `WorkflowsFeature`. * Restore CLR workflow registration compatibility * Align JSON island serialization fixtures * Add Console Logs Services and Enhance Endpoint Handling - Introduced `ActivityExecutionsEndpointTests` to validate route exposure. - Added `ConsoleLogCaptureHostedService` for console log streaming. - Implemented `ConsoleStreamJsonConverter` for JSON conversion of console streams. - Developed `ElsaConsoleLogRecentBuffer` to handle recent log buffering. - Updated `ConsoleLogsAuthorizationTests` with new test cases for stream filter mapping. - Consolidated console log provider dependencies and registration, including recent buffering. - Enhanced `ElsaConsoleLogProvider` to use recent buffer for filtering. - Adjusted `Program.cs` for streamlined logging service setup. * Enhance type resolution and test coverage; streamline console log integration - Added `ConsoleStreamHook` for streamlined log streaming. - Updated `WorkflowJsonTypeResolverTests` to improve type resolution and test new scenarios. - Simplified type resolution by removing trusted assembly checks. * Fix CI smoke and package restore failures * Fix Docker smoke image project paths * Fix Docker Python runtime packages * Fix Docker CA smoke teardown * Refresh Elsa roadmap * Implement background processors and mediation coordination - Added `BackgroundCommandProcessor`, `BackgroundJobProcessor`, and `BackgroundNotificationProcessor` classes for handling commands, jobs, and notifications, respectively. - Introduced `MediatorBackgroundProcessingCoordinator` to coordinate the execution of all background processors. - Implemented `MediatorBackgroundTask` for wrapping `MediatorBackgroundProcessingCoordinator` in `BackgroundTask`. - Added unit tests for `MediatorBackgroundTask` to ensure proper start and stop behavior. - Refactored `BackgroundCommandSenderHostedService` to utilize `BackgroundCommandProcessor`. - Introduced 'elsa-roadmap-refresh' skill configuration for roadmap updates. * Address workflow type resolution review feedback * Address follow-up review feedback * Restore recent console logs execute path * Address Copilot follow-up review * Decouple workflow JSON aliases from expressions * Fix workflow management unit test setup * Fix console logs recent endpoint handler shape * Respect workflow JSON strict type aliases * Remove unused console log contracts reference * Address Copilot review feedback * Address Copilot follow-up comments * Synchronize ring buffer dropped count * Address background processor strategy replay * Fix diagnostics live feed regressions --- .../CommandStrategies/BackgroundStrategy.cs | 2 +- .../ElsaConsoleLogSubscriptionManager.cs | 38 +++++ .../InMemory/InMemoryOpenTelemetryLiveFeed.cs | 139 +++++++++++++++++- .../ConsoleLogsAuthorizationTests.cs | 2 +- .../ConsoleLogsHubSourceStatusTests.cs | 43 +++++- .../TestConsoleLogSourceRegistry.cs | 28 ++++ .../OpenTelemetryHubTests.cs | 70 ++++++++- .../ElsaConsoleLogSubscriptionManagerTests.cs | 21 ++- .../BackgroundCommandProcessorTests.cs | 5 +- 9 files changed, 335 insertions(+), 13 deletions(-) create mode 100644 test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/TestConsoleLogSourceRegistry.cs diff --git a/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs b/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs index 242f6d772..860a72478 100644 --- a/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs +++ b/src/common/Elsa.Mediator/CommandStrategies/BackgroundStrategy.cs @@ -21,7 +21,7 @@ public class BackgroundStrategy : ICommandStrategy commandContext.ResultType, commandContext.Headers, commandContext.ServiceProvider, - commandContext.CancellationToken); + CancellationToken.None); await commandsChannel.Writer.WriteAsync(queuedContext, context.CancellationToken); return default!; } diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs index 0b25cc2a6..723b31f48 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/RealTime/ElsaConsoleLogSubscriptionManager.cs @@ -12,6 +12,7 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable { private readonly ConcurrentDictionary _subscriptions = new(StringComparer.Ordinal); private readonly IConsoleLogProvider _provider; + private readonly IConsoleLogSourceRegistry _sourceRegistry; private readonly IHubContext _hubContext; private readonly ILogger _logger; @@ -20,12 +21,15 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable ///

    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 P%{5I`J!plBUC93eu!D~A delta 370252 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

public ElsaConsoleLogSubscriptionManager( IConsoleLogProvider provider, + IConsoleLogSourceRegistry sourceRegistry, IHubContext hubContext, ILogger logger) { _provider = provider; + _sourceRegistry = sourceRegistry; _hubContext = hubContext; _logger = logger; + _sourceRegistry.SourceChanged += OnSourceChanged; } /// @@ -62,6 +66,8 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable /// public void Dispose() { + _sourceRegistry.SourceChanged -= OnSourceChanged; + foreach (var subscription in _subscriptions.Values) { subscription.CancellationTokenSource.Cancel(); @@ -125,6 +131,38 @@ public sealed class ElsaConsoleLogSubscriptionManager : IDisposable subscription.CancellationTokenSource.Dispose(); } + private void OnSourceChanged(ConsoleLogSource source) + { + _ = BroadcastSourceChangedAsync(source, _subscriptions.ToArray()); + } + + private async Task BroadcastSourceChangedAsync(ConsoleLogSource source, IReadOnlyCollection> subscriptions) + { + try + { + foreach (var (connectionId, subscription) in subscriptions) + { + if (!MatchesSource(source, subscription.Filter)) + continue; + + await _hubContext.Clients.Client(connectionId).ReceiveSourceChangedAsync(source, subscription.CancellationTokenSource.Token).ConfigureAwait(false); + } + } + catch (OperationCanceledException e) + { + _logger.LogDebug(e, "Console log source change broadcast for source {SourceId} was canceled", source.Id); + } + catch (Exception e) when (e is not OperationCanceledException) + { + _logger.LogDebug(e, "Failed to broadcast console log source change for source {SourceId}", source.Id); + } + } + + private static bool MatchesSource(ConsoleLogSource source, ElsaConsoleLogFilter filter) + { + return string.IsNullOrWhiteSpace(filter.SourceId) || string.Equals(source.Id, filter.SourceId, StringComparison.OrdinalIgnoreCase); + } + private static string GetSourceSignature(ConsoleLogSource source) { var metadata = source.Metadata diff --git a/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs index b84776c44..ab48b6d3a 100644 --- a/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs +++ b/src/modules/Elsa.Diagnostics.OpenTelemetry/Providers/InMemory/InMemoryOpenTelemetryLiveFeed.cs @@ -63,16 +63,18 @@ public class InMemoryOpenTelemetryLiveFeed(IOptions MatchesTrace(trace, serviceResourceIds))) TryWrite(new OpenTelemetryStreamItem { Trace = trace }); - foreach (var log in batch.Logs.Where(x => string.IsNullOrWhiteSpace(filter.TraceId) || string.Equals(x.TraceId, filter.TraceId, StringComparison.OrdinalIgnoreCase))) + foreach (var log in batch.Logs.Where(log => MatchesLog(log, serviceResourceIds))) TryWrite(new OpenTelemetryStreamItem { Log = log }); - foreach (var point in batch.MetricPoints) + foreach (var point in batch.MetricPoints.Where(point => MatchesMetricPoint(point, serviceResourceIds))) TryWrite(new OpenTelemetryStreamItem { MetricPoint = point }); } @@ -152,15 +154,140 @@ public class InMemoryOpenTelemetryLiveFeed(IOptions filter.To) + return false; + + if (!string.IsNullOrWhiteSpace(filter.Search) && !Matches(resource.Id, filter.Search) && !Matches(resource.ServiceName, filter.Search)) + return false; + + return true; + } + + private bool MatchesTrace(TelemetryTrace trace, HashSet? serviceResourceIds) + { + if (!string.IsNullOrWhiteSpace(filter.TraceId) && !EqualsIgnoreCase(trace.TraceId, filter.TraceId)) return false; if (filter.Status != null && trace.Status != filter.Status) return false; + if (filter.From != null && trace.StartTime < filter.From) + return false; + + if (filter.To != null && trace.StartTime > filter.To) + return false; + + if (!string.IsNullOrWhiteSpace(filter.WorkflowInstanceId) && !trace.WorkflowInstanceIds.Any(id => Matches(id, filter.WorkflowInstanceId))) + return false; + + if (!string.IsNullOrWhiteSpace(filter.ResourceId) && !trace.ResourceIds.Contains(filter.ResourceId, StringComparer.OrdinalIgnoreCase)) + return false; + + if (serviceResourceIds != null && !trace.ResourceIds.Any(serviceResourceIds.Contains)) + return false; + + if (!string.IsNullOrWhiteSpace(filter.Search) && !Matches(trace.TraceId, filter.Search) && !Matches(trace.Name, filter.Search)) + return false; + return true; } + + private bool MatchesLog(OtlpLogRecord log, HashSet? serviceResourceIds) + { + if (filter.Status != null) + return false; + + if (!string.IsNullOrWhiteSpace(filter.ResourceId) && !EqualsIgnoreCase(log.ResourceId, filter.ResourceId)) + return false; + + if (serviceResourceIds != null && !serviceResourceIds.Contains(log.ResourceId)) + return false; + + if (!string.IsNullOrWhiteSpace(filter.TraceId) && !EqualsIgnoreCase(log.TraceId, filter.TraceId)) + return false; + + if (!string.IsNullOrWhiteSpace(filter.WorkflowInstanceId) && !AttributeMatches(log.Attributes, "workflow.instance.id", filter.WorkflowInstanceId)) + return false; + + if (filter.From != null && log.Timestamp < filter.From) + return false; + + if (filter.To != null && log.Timestamp > filter.To) + return false; + + if (!string.IsNullOrWhiteSpace(filter.Search) && !Matches(log.Body, filter.Search)) + return false; + + return true; + } + + private bool MatchesMetricPoint(MetricPoint point, HashSet? serviceResourceIds) + { + if (filter.Status != null) + return false; + + if (!string.IsNullOrWhiteSpace(filter.ResourceId) && !EqualsIgnoreCase(point.ResourceId, filter.ResourceId)) + return false; + + if (serviceResourceIds != null && !serviceResourceIds.Contains(point.ResourceId)) + return false; + + if (!string.IsNullOrWhiteSpace(filter.TraceId) && !EqualsIgnoreCase(point.TraceId, filter.TraceId)) + return false; + + if (!string.IsNullOrWhiteSpace(filter.WorkflowInstanceId) && !AttributeMatches(point.Attributes, "workflow.instance.id", filter.WorkflowInstanceId)) + return false; + + if (filter.From != null && point.Timestamp < filter.From) + return false; + + if (filter.To != null && point.Timestamp > filter.To) + return false; + + if (!string.IsNullOrWhiteSpace(filter.Search) && !Matches(point.InstrumentName, filter.Search) && !Matches(point.InstrumentId, filter.Search)) + return false; + + return true; + } + + private HashSet? ResolveServiceResourceIds(IEnumerable resources) + { + if (string.IsNullOrWhiteSpace(filter.ServiceName)) + return null; + + return resources + .Where(x => EqualsIgnoreCase(x.ServiceName, filter.ServiceName)) + .Select(x => x.Id) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + } + + private static bool AttributeMatches(IDictionary attributes, string key, string? search) + { + return attributes.TryGetValue(key, out var value) && Matches(value, search); + } + + private static bool EqualsIgnoreCase(string? candidate, string? search) => string.Equals(candidate, search, StringComparison.OrdinalIgnoreCase); + + private static bool Matches(string? candidate, string? search) => !string.IsNullOrEmpty(candidate) && !string.IsNullOrEmpty(search) && candidate.Contains(search, StringComparison.OrdinalIgnoreCase); } } diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs index 90d00d2c3..d6bf4c1a4 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsAuthorizationTests.cs @@ -292,7 +292,7 @@ public class ConsoleLogsAuthorizationTests private static ElsaConsoleLogsHub CreateHub(TestConsoleLogProvider provider, params string[] permissions) { var hubContext = new TestHubContext(); - var subscriptionManager = new ElsaConsoleLogSubscriptionManager(provider, hubContext, NullLogger.Instance); + var subscriptionManager = new ElsaConsoleLogSubscriptionManager(provider, new TestConsoleLogSourceRegistry(), hubContext, NullLogger.Instance); var authorizer = new ElsaConsoleLogStreamHubAuthorizer(); return new ElsaConsoleLogsHub(provider, authorizer, subscriptionManager) diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs index 321d1a6f1..7c09d8a9f 100644 --- a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/ConsoleLogsHubSourceStatusTests.cs @@ -20,15 +20,32 @@ public class ConsoleLogsHubSourceStatusTests { var source = new ConsoleLogSource { Id = "source-1", DisplayName = "Source 1" }; var provider = new SingleLineProvider(new ConsoleLogLine { Text = "message", Source = source }); + var sourceRegistry = new TestConsoleLogSourceRegistry(); var client = new TestConsoleLogsClient(); var hubContext = new TestHubContext(client); - var manager = new ElsaConsoleLogSubscriptionManager(provider, hubContext, NullLogger.Instance); + using var manager = new ElsaConsoleLogSubscriptionManager(provider, sourceRegistry, hubContext, NullLogger.Instance); await manager.SubscribeAsync("connection-1", new ElsaConsoleLogFilter(), CancellationToken.None); Assert.Same(source, await client.SourceChanged.Task.WaitAsync(TimeSpan.FromSeconds(5))); } + [Fact] + public async Task PushedSubscription_ForwardsSourceChangeFromRegistry() + { + var source = new ConsoleLogSource { Id = "source-1", DisplayName = "Source 1" }; + var provider = new IdleProvider(); + var sourceRegistry = new TestConsoleLogSourceRegistry(); + var client = new TestConsoleLogsClient(); + var hubContext = new TestHubContext(client); + using var manager = new ElsaConsoleLogSubscriptionManager(provider, sourceRegistry, hubContext, NullLogger.Instance); + + await manager.SubscribeAsync("connection-1", new ElsaConsoleLogFilter { SourceId = source.Id }, CancellationToken.None); + sourceRegistry.Raise(source); + + Assert.Same(source, await client.SourceChanged.Task.WaitAsync(TimeSpan.FromSeconds(5))); + } + private sealed class SingleLineProvider(ConsoleLogLine line) : IConsoleLogProvider { public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) @@ -53,6 +70,30 @@ public class ConsoleLogsHubSourceStatusTests } } + private sealed class IdleProvider : IConsoleLogProvider + { + public ValueTask PublishAsync(ConsoleLogLine line, CancellationToken cancellationToken = default) + { + return ValueTask.CompletedTask; + } + + public ValueTask GetRecentAsync(ConsoleLogFilter filter, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(new RecentConsoleLogsResult()); + } + + public async IAsyncEnumerable SubscribeAsync(ConsoleLogFilter filter, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) + { + await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken); + yield break; + } + + public ValueTask> ListSourcesAsync(CancellationToken cancellationToken = default) + { + return ValueTask.FromResult>([]); + } + } + private sealed class TestConsoleLogsClient : IElsaConsoleLogsClient { public TaskCompletionSource SourceChanged { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/TestConsoleLogSourceRegistry.cs b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/TestConsoleLogSourceRegistry.cs new file mode 100644 index 000000000..120a176f6 --- /dev/null +++ b/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/TestConsoleLogSourceRegistry.cs @@ -0,0 +1,28 @@ +using ConsoleLogStreaming.Core; +using ConsoleLogStreaming.Core.Models; + +namespace Elsa.Diagnostics.ConsoleLogs.IntegrationTests; + +internal sealed class TestConsoleLogSourceRegistry : IConsoleLogSourceRegistry +{ + public event Action? SourceChanged; + + public ConsoleLogSource Current { get; private set; } = new() { Id = "test-source" }; + + public ConsoleLogSource MarkSeen(ConsoleLogSource source, DateTimeOffset timestamp) + { + Current = source; + SourceChanged?.Invoke(source); + return source; + } + + public IReadOnlyCollection List() + { + return [Current]; + } + + public void Raise(ConsoleLogSource source) + { + SourceChanged?.Invoke(source); + } +} diff --git a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs index d65e12d8e..fae7cc61b 100644 --- a/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs +++ b/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/OpenTelemetryHubTests.cs @@ -72,6 +72,57 @@ public class OpenTelemetryHubTests Assert.Equal("trace-keep", enumerator.Current.Trace?.TraceId); } + [Fact] + public async Task LiveFeed_WhenServiceNameFilterIsSet_OnlyPublishesMatchingResourcesAndTraces() + { + var liveFeed = new InMemoryOpenTelemetryLiveFeed(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions())); + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + await using var enumerator = liveFeed.SubscribeAsync(new OpenTelemetryTraceFilter { ServiceName = "api" }, timeout.Token).GetAsyncEnumerator(timeout.Token); + var next = enumerator.MoveNextAsync().AsTask(); + + await liveFeed.PublishAsync(new OpenTelemetryBatch( + [Resource("resource-skip", "worker")], + [Trace("trace-skip", ["resource-skip"])], + [], [], [], []), timeout.Token); + + var completed = await Task.WhenAny(next, Task.Delay(TimeSpan.FromMilliseconds(150), timeout.Token)); + Assert.NotSame(next, completed); + + await liveFeed.PublishAsync(new OpenTelemetryBatch( + [Resource("resource-keep", "api")], + [Trace("trace-keep", ["resource-keep"])], + [], [], [], []), timeout.Token); + + Assert.True(await next); + Assert.Equal("resource-keep", enumerator.Current.Resource?.Id); + + Assert.True(await enumerator.MoveNextAsync()); + Assert.Equal("trace-keep", enumerator.Current.Trace?.TraceId); + } + + [Fact] + public async Task LiveFeed_WhenResourceFilterIsSet_FiltersLogsAndMetricPoints() + { + var liveFeed = new InMemoryOpenTelemetryLiveFeed(OptionsFactory.Create(new OpenTelemetryDiagnosticsOptions())); + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + await using var enumerator = liveFeed.SubscribeAsync(new OpenTelemetryTraceFilter { ResourceId = "resource-keep" }, timeout.Token).GetAsyncEnumerator(timeout.Token); + var first = enumerator.MoveNextAsync().AsTask(); + + await liveFeed.PublishAsync(new OpenTelemetryBatch( + [], + [], + [], + [], + [MetricPoint("point-skip", "resource-skip"), MetricPoint("point-keep", "resource-keep")], + [Log("log-skip", "resource-skip"), Log("log-keep", "resource-keep")]), timeout.Token); + + Assert.True(await first); + Assert.Equal("log-keep", enumerator.Current.Log?.Id); + + Assert.True(await enumerator.MoveNextAsync()); + Assert.Equal("point-keep", enumerator.Current.MetricPoint?.Id); + } + [Fact] public async Task LiveFeed_WhenSubscriberQueueOverflows_PublishesDroppedItemSummary() { @@ -121,9 +172,24 @@ public class OpenTelemetryHubTests return new ClaimsPrincipal(identity); } - private TelemetryTrace Trace(string traceId) + private TelemetryResource Resource(string id, string serviceName) { - return new(traceId, $"{traceId}-root", traceId, _now, _now.AddMilliseconds(10), TimeSpan.FromMilliseconds(10), SpanStatus.Ok, [], [], 1); + return new(id, serviceName, null, null, new Dictionary(), _now, TelemetryResourceStatus.Active); + } + + private TelemetryTrace Trace(string traceId, IReadOnlyCollection? resourceIds = null, IReadOnlyCollection? workflowInstanceIds = null) + { + return new(traceId, $"{traceId}-root", traceId, _now, _now.AddMilliseconds(10), TimeSpan.FromMilliseconds(10), SpanStatus.Ok, resourceIds ?? [], workflowInstanceIds ?? [], 1); + } + + private MetricPoint MetricPoint(string id, string resourceId) + { + return new(id, $"{id}-instrument", $"{id}-instrument", resourceId, _now, 1, null, null, new Dictionary(), null, null); + } + + private OtlpLogRecord Log(string id, string resourceId) + { + return new(id, resourceId, _now, "Information", 9, id, null, null, new Dictionary()); } private class TestLiveFeed(params OpenTelemetryStreamItem[] items) : IOpenTelemetryLiveFeed diff --git a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs index 2558ca593..2ede75203 100644 --- a/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs +++ b/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/ElsaConsoleLogSubscriptionManagerTests.cs @@ -24,7 +24,7 @@ public class ElsaConsoleLogSubscriptionManagerTests ConsoleLogStreamingItem.FromLine(CreateLine(source, "second"))); var client = new RecordingConsoleLogsClient(); var hubContext = new TestHubContext(client); - using var manager = new ElsaConsoleLogSubscriptionManager(provider, hubContext, NullLogger.Instance); + using var manager = new ElsaConsoleLogSubscriptionManager(provider, new TestConsoleLogSourceRegistry(), hubContext, NullLogger.Instance); await manager.SubscribeAsync("connection-1", new(), CancellationToken.None); @@ -91,6 +91,25 @@ public class ElsaConsoleLogSubscriptionManagerTests } } + private sealed class TestConsoleLogSourceRegistry : IConsoleLogSourceRegistry + { + public event Action? SourceChanged; + + public ConsoleLogSource Current { get; private set; } = new() { Id = "test-source" }; + + public ConsoleLogSource MarkSeen(ConsoleLogSource source, DateTimeOffset timestamp) + { + Current = source; + SourceChanged?.Invoke(source); + return source; + } + + public IReadOnlyCollection List() + { + return [Current]; + } + } + private sealed class RecordingConsoleLogsClient : IElsaConsoleLogsClient { public List Lines { get; } = []; diff --git a/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs b/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs index b831000e5..21680a41b 100644 --- a/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs +++ b/test/unit/Elsa.Mediator.UnitTests/BackgroundCommandProcessorTests.cs @@ -51,9 +51,11 @@ public class BackgroundCommandProcessorTests services.AddSingleton(); await using var serviceProvider = services.BuildServiceProvider(); var channel = serviceProvider.GetRequiredService(); - var commandContext = new CommandContext(new TestCommand(), CommandStrategy.Background, typeof(Unit), new Dictionary(), serviceProvider, CancellationToken.None); + using var commandCancellationTokenSource = new CancellationTokenSource(); + var commandContext = new CommandContext(new TestCommand(), CommandStrategy.Background, typeof(Unit), new Dictionary(), serviceProvider, commandCancellationTokenSource.Token); var strategyContext = new CommandStrategyContext(commandContext, new TestCommandHandler(), serviceProvider); + await commandCancellationTokenSource.CancelAsync(); await CommandStrategy.Background.ExecuteAsync(strategyContext); var queuedContext = await channel.Reader.ReadAsync(); @@ -61,6 +63,7 @@ public class BackgroundCommandProcessorTests Assert.Same(CommandStrategy.Default, queuedContext.CommandStrategy); Assert.Same(commandContext.Command, queuedContext.Command); Assert.Same(commandContext.Headers, queuedContext.Headers); + Assert.False(queuedContext.CancellationToken.IsCancellationRequested); } private sealed class RecordingCommandSender(CommandSenderRecorder recorder) : ICommandSender From c2fb027c4151baf44ce11d1da962ff4bce8108d6 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 31 May 2026 11:09:39 +0200 Subject: [PATCH 6/6] Refactor: Overhauls workflow JSON type serialization (#7549) * Avoid null endpoint DTO metadata in tests * Enforce console logs hub read permission * Remove unused console logs hub import * Support mapped endpoint metadata in auth tests * Reduce console log capture throughput impact * Address Copilot console logs review * Refactor task scheduling to support tenant-level background work and enhance logging functionality. * Introduce ConsoleStreamHook for stdout/stderr tee and enhance logging validation. Adjust test cases and startup warnings for distributed lock provider usage. * Refactor console logging pipeline with capture optimization and new ConsoleLogsHost; update tests accordingly. * Add Ansi SGR parser for console logs and associated unit tests * Remove ANSI color renderings and parsers; integrate ConsoleLogScopeAccessor for improved logging context with workflow instance ID support. * Address console logs code quality feedback * Address PR review feedback * Preserve console logs extension points * Stabilize console logs host lifecycle * Address final automated review comments * Tighten console log capture shutdown * Address console log review feedback * Address follow-up review feedback * Cover final review feedback * Avoid recursive console provider initialization * Guard console host lease shutdown * Preserve console log scope and provider lifetime * Correlate console log scope fallback * Tighten console scope correlation * Expose host services during provider construction * Redact ANSI-normalized console lines * Remove `ConsoleCaptureTee` and related services and tests * Use pipeline contributors for console log context * Update CShells package versions to 0.0.24-preview.132 * Filter live console logs by workflow instance * Enhance console logging with activity execution metadata and extend test coverage. * Address console logs stream consumption comment * Add diagnostics OpenTelemetry backend * Introduce dedicated workflow JSON type registry and hardening This change addresses GitHub issue #7541 by establishing a separate type registry (`IWorkflowJsonTypeRegistry`) for workflow JSON serialization. This decouples workflow type resolution from expression type aliases, enforcing a strict trust boundary. Key aspects: - New workflow JSON emits preferred aliases for registered types. - Existing persisted workflows can be loaded via registered legacy names. - Unknown, abstract, interface, open generic, or inappropriate collection types are rejected during deserialization, enhancing security. - Public APIs (e.g., incident strategies) now expose consistent workflow JSON type identifiers. This ensures secure, predictable, and backward-compatible handling of types within workflow definitions and payloads. * Remove unused project references and streamline console log endpoint * Move serialization type aliases to Elsa.Common * Update serialization integration fixtures for aliases * Stabilize missing rate limiter policy test --- .specify/feature.json | 2 +- AGENTS.md | 2 +- Elsa.sln | 86 ++-- doc/wiki/workflow-core.md | 8 + .../checklists/requirements.md | 34 ++ .../workflow-json-type-identifiers.md | 15 + .../010-workflow-json-hardening/data-model.md | 20 + specs/010-workflow-json-hardening/plan.md | 88 ++++ .../010-workflow-json-hardening/quickstart.md | 11 + specs/010-workflow-json-hardening/research.md | 25 ++ specs/010-workflow-json-hardening/spec.md | 103 +++++ specs/010-workflow-json-hardening/tasks.md | 125 ++++++ src/apps/Elsa.ModularServer.Web/Program.cs | 1 - .../Models/IncidentStrategyDescriptor.cs | 4 +- .../Features/AlterationsFeature.cs | 7 +- .../ShellFeatures/AlterationsFeature.cs | 7 +- .../SerializationTypeOptionsExtensions.cs | 53 +++ .../Elsa.Common/Extensions/TypeExtensions.cs | 33 +- .../ISerializationTypeRegistry.cs | 27 ++ .../Serialization/SerializationTypeOptions.cs | 85 ++++ .../SerializationTypeRegistry.cs | 60 +++ .../SerializationTypeResolver.cs} | 195 +++++---- .../Contracts/ElsaConsoleLogFilter.cs | 30 +- .../Endpoints/ConsoleLogs/Sources/Endpoint.cs | 4 +- .../Features/JavaScriptFeature.cs | 9 +- .../JavaScriptExceptionTypeAliasRegistrar.cs | 34 ++ .../ShellFeatures/JavaScriptFeature.cs | 7 +- .../Extensions/TypeExtensions.cs | 35 +- src/modules/Elsa.Http/Features/HttpFeature.cs | 33 +- .../Elsa.Http/ShellFeatures/HttpFeature.cs | 33 +- .../WorkflowDefinitionPersistenceFeature.cs | 4 +- .../Features/ResilienceFeature.cs | 7 + .../ShellFeatures/ResilienceFeature.cs | 7 + .../Features/SchedulingFeature.cs | 17 +- .../ShellFeatures/SchedulingFeature.cs | 5 +- .../Elsa.Workflows.Api/AssemblyInfo.cs | 3 +- .../IncidentStrategies/List/Endpoint.cs | 16 +- .../Serialization/FlowchartJsonConverter.cs | 9 +- .../WorkflowJsonOptionsExtensions.cs | 66 --- .../Features/FlowchartFeature.cs | 5 +- .../Features/WorkflowsFeature.cs | 33 +- .../Converters/OutputJsonConverter.cs | 15 +- .../PolymorphicDictionaryConverter.cs | 6 +- .../Converters/PolymorphicObjectConverter.cs | 28 +- .../PolymorphicObjectConverterFactory.cs | 23 +- .../Converters/TypeJsonConverter.cs | 40 +- .../Converters/VariableConverter.cs | 14 +- .../Converters/VariableConverterFactory.cs | 22 +- .../Options/WorkflowJsonOptions.cs | 91 ---- .../Serializers/BookmarkPayloadSerializer.cs | 15 +- .../JsonWorkflowStateSerializer.cs | 26 +- .../Serializers/SafeSerializer.cs | 3 +- .../Elsa.Workflows.Core/Services/Hasher.cs | 12 +- .../Services/VariableMapper.cs | 51 +-- .../ShellFeatures/FlowchartFeature.cs | 5 +- .../ShellFeatures/WorkflowsFeature.cs | 35 +- .../ManagementServiceCollectionExtensions.cs | 8 +- .../Extensions/ModuleExtensions.cs | 11 +- .../WorkflowManagementFeatureExtensions.cs | 6 +- .../Features/WorkflowManagementFeature.cs | 7 +- .../Mappers/VariableDefinitionMapper.cs | 25 +- .../WorkflowManagementFeature.cs | 5 +- .../WorkflowTriggerEqualityComparer.cs | 21 +- .../DependencyInjectionExtensions.cs | 5 +- .../Features/WorkflowRuntimeFeature.cs | 42 +- .../Services/TriggerIndexer.cs | 7 +- .../ShellFeatures/WorkflowRuntimeFeature.cs | 38 +- .../WorkflowRuntimeTypeAliasRegistrar.cs | 36 ++ .../Serialization/JsonSerialization/Tests.cs | 8 +- .../Serialization/Polymorphism/Tests.cs | 12 +- .../Serialization/Polymorphism/data.json | 2 +- .../RateLimiting/IngressRateLimitingTests.cs | 12 +- .../Endpoints/IncidentStrategies/ListTests.cs | 28 ++ .../Converters/ActivityJsonConverterTests.cs | 4 +- .../SerializationTypeResolverTests.cs | 396 ++++++++++++++++++ .../WorkflowJsonTypeResolverTests.cs | 268 ------------ .../Services/VariableMapperTests.cs | 53 +-- .../Mappers/VariableDefinitionMapperTests.cs | 49 +-- ...rkflowDefinitionExporterRegressionTests.cs | 6 +- .../WorkflowTriggerEqualityComparerTests.cs | 94 +++-- .../Features/WorkflowRuntimeFeatureTests.cs | 214 ++++++++++ 81 files changed, 2073 insertions(+), 1018 deletions(-) create mode 100644 specs/010-workflow-json-hardening/checklists/requirements.md create mode 100644 specs/010-workflow-json-hardening/contracts/workflow-json-type-identifiers.md create mode 100644 specs/010-workflow-json-hardening/data-model.md create mode 100644 specs/010-workflow-json-hardening/plan.md create mode 100644 specs/010-workflow-json-hardening/quickstart.md create mode 100644 specs/010-workflow-json-hardening/research.md create mode 100644 specs/010-workflow-json-hardening/spec.md create mode 100644 specs/010-workflow-json-hardening/tasks.md create mode 100644 src/modules/Elsa.Common/Extensions/SerializationTypeOptionsExtensions.cs create mode 100644 src/modules/Elsa.Common/Serialization/ISerializationTypeRegistry.cs create mode 100644 src/modules/Elsa.Common/Serialization/SerializationTypeOptions.cs create mode 100644 src/modules/Elsa.Common/Serialization/SerializationTypeRegistry.cs rename src/modules/{Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs => Elsa.Common/Serialization/SerializationTypeResolver.cs} (60%) create mode 100644 src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs delete mode 100644 src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs delete mode 100644 src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs create mode 100644 src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs create mode 100644 test/unit/Elsa.Workflows.Api.UnitTests/Endpoints/IncidentStrategies/ListTests.cs create mode 100644 test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/SerializationTypeResolverTests.cs delete mode 100644 test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs create mode 100644 test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs diff --git a/.specify/feature.json b/.specify/feature.json index d418d5e78..1c74f069f 100644 --- a/.specify/feature.json +++ b/.specify/feature.json @@ -1,3 +1,3 @@ { - "feature_directory": "specs/008-diagnostics-otel" + "feature_directory": "specs/010-workflow-json-hardening" } diff --git a/AGENTS.md b/AGENTS.md index 62610a8e8..3390d955c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -83,7 +83,7 @@ Before handing off changes, verify the following when applicable: For additional context about technologies to be used, project structure, -shell commands, and other important information, read `specs/008-diagnostics-otel/plan.md`. +shell commands, and other important information, read `specs/010-workflow-json-hardening/plan.md`. ## Active Technologies diff --git a/Elsa.sln b/Elsa.sln index 46a604192..2fc20c983 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.7.34003.232 @@ -347,11 +347,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Secrets.UnitTests", "t EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Workflows.Api.UnitTests", "test\unit\Elsa.Workflows.Api.UnitTests\Elsa.Workflows.Api.UnitTests.csproj", "{81CFD2E0-2E5E-4810-ADB8-A08301199166}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry", "src\modules\Elsa.Diagnostics.OpenTelemetry\Elsa.Diagnostics.OpenTelemetry.csproj", "{007E3396-34EE-40A8-B697-23D694DC9EBE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry", "src\modules\Elsa.Diagnostics.OpenTelemetry\Elsa.Diagnostics.OpenTelemetry.csproj", "{8F4AD54E-8586-4D8C-82E6-69218DD4280F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry.UnitTests", "test\unit\Elsa.Diagnostics.OpenTelemetry.UnitTests\Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj", "{D9D6C168-36CB-46EB-838A-B26C22FE9FDB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry.UnitTests", "test\unit\Elsa.Diagnostics.OpenTelemetry.UnitTests\Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj", "{60F844CC-6DA6-45EB-BA5E-B480B4E77624}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry.IntegrationTests", "test\integration\Elsa.Diagnostics.OpenTelemetry.IntegrationTests\Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj", "{B5075CE7-7332-4F78-AB3D-492D670789FB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Diagnostics.OpenTelemetry.IntegrationTests", "test\integration\Elsa.Diagnostics.OpenTelemetry.IntegrationTests\Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj", "{B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1393,42 +1393,42 @@ Global {81CFD2E0-2E5E-4810-ADB8-A08301199166}.Release|x64.Build.0 = Release|Any CPU {81CFD2E0-2E5E-4810-ADB8-A08301199166}.Release|x86.ActiveCfg = Release|Any CPU {81CFD2E0-2E5E-4810-ADB8-A08301199166}.Release|x86.Build.0 = Release|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x64.ActiveCfg = Debug|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x64.Build.0 = Debug|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x86.ActiveCfg = Debug|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Debug|x86.Build.0 = Debug|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|Any CPU.Build.0 = Release|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x64.ActiveCfg = Release|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x64.Build.0 = Release|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x86.ActiveCfg = Release|Any CPU - {007E3396-34EE-40A8-B697-23D694DC9EBE}.Release|x86.Build.0 = Release|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x64.ActiveCfg = Debug|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x64.Build.0 = Debug|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x86.ActiveCfg = Debug|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Debug|x86.Build.0 = Debug|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|Any CPU.Build.0 = Release|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x64.ActiveCfg = Release|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x64.Build.0 = Release|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x86.ActiveCfg = Release|Any CPU - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB}.Release|x86.Build.0 = Release|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x64.ActiveCfg = Debug|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x64.Build.0 = Debug|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x86.ActiveCfg = Debug|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Debug|x86.Build.0 = Debug|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|Any CPU.Build.0 = Release|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x64.ActiveCfg = Release|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x64.Build.0 = Release|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x86.ActiveCfg = Release|Any CPU - {B5075CE7-7332-4F78-AB3D-492D670789FB}.Release|x86.Build.0 = Release|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Debug|x64.ActiveCfg = Debug|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Debug|x64.Build.0 = Debug|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Debug|x86.ActiveCfg = Debug|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Debug|x86.Build.0 = Debug|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Release|Any CPU.Build.0 = Release|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Release|x64.ActiveCfg = Release|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Release|x64.Build.0 = Release|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Release|x86.ActiveCfg = Release|Any CPU + {8F4AD54E-8586-4D8C-82E6-69218DD4280F}.Release|x86.Build.0 = Release|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Debug|x64.ActiveCfg = Debug|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Debug|x64.Build.0 = Debug|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Debug|x86.ActiveCfg = Debug|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Debug|x86.Build.0 = Debug|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Release|Any CPU.Build.0 = Release|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Release|x64.ActiveCfg = Release|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Release|x64.Build.0 = Release|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Release|x86.ActiveCfg = Release|Any CPU + {60F844CC-6DA6-45EB-BA5E-B480B4E77624}.Release|x86.Build.0 = Release|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Debug|x64.ActiveCfg = Debug|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Debug|x64.Build.0 = Debug|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Debug|x86.ActiveCfg = Debug|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Debug|x86.Build.0 = Debug|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Release|Any CPU.Build.0 = Release|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Release|x64.ActiveCfg = Release|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Release|x64.Build.0 = Release|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Release|x86.ActiveCfg = Release|Any CPU + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1552,9 +1552,9 @@ Global {09B4B78B-FE02-44E2-8667-E182AF921C54} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {7D905CEC-B30B-4C99-B5F7-3052D33EC8E9} = {18453B51-25EB-4317-A4B3-B10518252E92} {81CFD2E0-2E5E-4810-ADB8-A08301199166} = {18453B51-25EB-4317-A4B3-B10518252E92} - {D9D6C168-36CB-46EB-838A-B26C22FE9FDB} = {18453B51-25EB-4317-A4B3-B10518252E92} - {B5075CE7-7332-4F78-AB3D-492D670789FB} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} - {007E3396-34EE-40A8-B697-23D694DC9EBE} = {78FD90A4-90A5-445F-97F2-74BA835AFA5D} + {8F4AD54E-8586-4D8C-82E6-69218DD4280F} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} + {60F844CC-6DA6-45EB-BA5E-B480B4E77624} = {18453B51-25EB-4317-A4B3-B10518252E92} + {B6A62D42-D9AA-47BE-BCBC-FCB866D346F0} = {1B8D5897-902E-4632-8698-E89CAF3DDF54} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E} diff --git a/doc/wiki/workflow-core.md b/doc/wiki/workflow-core.md index 83707c568..c82a48106 100644 --- a/doc/wiki/workflow-core.md +++ b/doc/wiki/workflow-core.md @@ -148,6 +148,14 @@ Core serializers live under [Serialization](../../src/modules/Elsa.Workflows.Cor Custom constructor and additional converter configurators are registered by `WorkflowsFeature`. +### Workflow JSON Type Identifiers + +Workflow JSON type resolution uses the shared `ISerializationTypeRegistry` from `Elsa.Common.Serialization`, not expression type aliases. Register workflow-serializable payload types through `SerializationTypeOptions`; keep `ExpressionOptions` for expression/type metadata only. + +New workflow JSON writes preferred aliases when a type is registered. Compatibility reads also accept explicitly registered legacy names, including selected CLR names from older persisted workflow JSON. Unknown CLR names are rejected rather than loaded dynamically. Polymorphic object reads also reject abstract, interface, open generic, and unsupported collection targets unless the resolver can map a known collection interface to a concrete collection type. + +Public API payloads that expose workflow JSON type identifiers should emit values from `ISerializationTypeRegistry`. For example, incident strategy descriptors return the alias that workflow JSON accepts, while registered legacy CLR names remain readable during the compatibility window. + ## When To Change This Layer Change workflow core only when you are changing engine semantics, activity contracts, execution state, serialization, core activity behavior, or flowchart behavior. If the change is about persisted definitions, API DTOs, background dispatch, or a module-specific transport, start in management, API, runtime, or the extension module instead. diff --git a/specs/010-workflow-json-hardening/checklists/requirements.md b/specs/010-workflow-json-hardening/checklists/requirements.md new file mode 100644 index 000000000..9a990910a --- /dev/null +++ b/specs/010-workflow-json-hardening/checklists/requirements.md @@ -0,0 +1,34 @@ +# Specification Quality Checklist: Workflow JSON Type Hardening + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-05-29 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Validation passed. The issue explicitly requires a dedicated workflow serialization type registry or resolver; the specification names this capability as a required product behavior while deferring implementation details to planning. diff --git a/specs/010-workflow-json-hardening/contracts/workflow-json-type-identifiers.md b/specs/010-workflow-json-hardening/contracts/workflow-json-type-identifiers.md new file mode 100644 index 000000000..2e39ff815 --- /dev/null +++ b/specs/010-workflow-json-hardening/contracts/workflow-json-type-identifiers.md @@ -0,0 +1,15 @@ +# Contract: Workflow JSON Type Identifiers + +## Identifier Rules + +- New workflow JSON writes aliases when a type is registered with a workflow JSON alias. +- Compatibility reads accept registered aliases and registered legacy names. +- Unknown CLR names are rejected. +- Abstract, interface, open generic, and inappropriate collection targets are rejected for polymorphic object materialization. +- Supported collection aliases are limited to known collection wrappers closed over registered element types. + +## Incident Strategy Descriptor + +`GET /descriptors/incident-strategies` returns `typeName` values from the shared serialization type registry. + +Clients should persist or submit returned `typeName` values unchanged. During the compatibility window, existing CLR names registered as legacy identifiers remain accepted when workflow JSON is read. diff --git a/specs/010-workflow-json-hardening/data-model.md b/specs/010-workflow-json-hardening/data-model.md new file mode 100644 index 000000000..1782d97ec --- /dev/null +++ b/specs/010-workflow-json-hardening/data-model.md @@ -0,0 +1,20 @@ +# Data Model: Workflow JSON Type Hardening + +## SerializationTypeOptions + +- Stores workflow JSON aliases mapped to concrete types. +- Stores optional legacy names mapped to the same concrete types. +- Provides default primitive and JSON island aliases needed by workflow payloads. +- Lives in `Elsa.Common` so non-workflow serialization layers can share the same trust boundary. + +## SerializationTypeRegistry + +- Runtime registry built from `SerializationTypeOptions`. +- Resolves aliases and registered legacy names to types. +- Lists registered types for compatibility resolution. +- Returns preferred aliases for writing new workflow JSON and public descriptor values. + +## Workflow Type Identifier + +- Alias: preferred stable identifier for new workflow JSON. +- Legacy name: supported compatibility identifier for previously persisted workflow JSON or older clients. diff --git a/specs/010-workflow-json-hardening/plan.md b/specs/010-workflow-json-hardening/plan.md new file mode 100644 index 000000000..d68f63df0 --- /dev/null +++ b/specs/010-workflow-json-hardening/plan.md @@ -0,0 +1,88 @@ +# Implementation Plan: Workflow JSON Type Hardening + +**Branch**: `codex/7541-workflow-json-hardening` | **Date**: 2026-05-29 | **Spec**: [spec.md](spec.md) +**Input**: Feature specification from `/specs/010-workflow-json-hardening/spec.md` + +**Note**: This template is filled in by the `/speckit-plan` command. See `.specify/templates/plan-template.md` for the execution workflow. + +## Summary + +Reintroduce workflow JSON hardening through a workflow-specific type registry and resolver. Existing registered legacy CLR names remain readable, new workflow JSON emits aliases when available, and public descriptor APIs use the same identifier contract they accept. + +## Technical Context + + + +**Language/Version**: C# latest with nullable reference types, multi-targeting through existing project settings +**Primary Dependencies**: System.Text.Json, Elsa feature/module infrastructure, existing expression registry for expression-only behavior +**Storage**: Existing workflow JSON payloads only; no schema changes +**Testing**: Targeted `dotnet test` for workflow core/runtime/api test projects +**Target Platform**: Elsa server/library consumers on supported .NET target frameworks +**Project Type**: Modular .NET library and API modules +**Performance Goals**: Type lookup remains dictionary-based and does not add reflection scans to normal serialization +**Constraints**: No arbitrary CLR type loading; compatibility only for explicitly registered workflow JSON legacy names +**Scale/Scope**: Workflow definitions, workflow state, trigger/bookmark payloads, incident strategy descriptor contract, and module/extension registrations + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +PASS. The change stays inside existing workflow modules, adds one explicit extensibility point for serialization trust, preserves public compatibility, and includes focused tests. No new persistence provider or unrelated module is introduced. + +## Project Structure + +### Documentation (this feature) + +```text +specs/[###-feature]/ +├── plan.md # This file (/speckit-plan command output) +├── research.md # Phase 0 output (/speckit-plan command) +├── data-model.md # Phase 1 output (/speckit-plan command) +├── quickstart.md # Phase 1 output (/speckit-plan command) +├── contracts/ # Phase 1 output (/speckit-plan command) +└── tasks.md # Phase 2 output (/speckit-tasks command - NOT created by /speckit-plan) +``` + +### Source Code (repository root) + + +```text +src/modules/Elsa.Workflows.Core/ +├── Contracts/ +├── Extensions/ +├── Options/ +├── Serialization/ +└── Features/ + +src/modules/Elsa.Workflows.Runtime/ +├── Features/ +├── ShellFeatures/ +└── Services/ + +src/modules/Elsa.Workflows.Api/ +└── Endpoints/IncidentStrategies/ + +test/unit/Elsa.Workflows.Core.UnitTests/ +test/unit/Elsa.Workflows.Runtime.UnitTests/ +test/integration/Elsa.Workflows.IntegrationTests/ +``` + +**Structure Decision**: Extend the existing workflow core serialization surface and update runtime/API registrations in place. Tests stay in the nearest existing workflow test projects. + +## Complexity Tracking + +> **Fill ONLY if Constitution Check has violations that must be justified** + +| Violation | Why Needed | Simpler Alternative Rejected Because | +|-----------|------------|-------------------------------------| +| [e.g., 4th project] | [current need] | [why 3 projects insufficient] | +| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] | diff --git a/specs/010-workflow-json-hardening/quickstart.md b/specs/010-workflow-json-hardening/quickstart.md new file mode 100644 index 000000000..9ea443ee7 --- /dev/null +++ b/specs/010-workflow-json-hardening/quickstart.md @@ -0,0 +1,11 @@ +# Quickstart: Workflow JSON Type Hardening + +1. Register built-in workflow JSON aliases through workflow features. +2. Register module payload aliases through each module that serializes workflow payloads. +3. Verify `TypeJsonConverter` and `PolymorphicObjectConverter` use the shared serialization registry, not expression options. +4. Run targeted tests: + +```sh +dotnet test test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj --filter SerializationTypeResolverTests +dotnet test test/unit/Elsa.Workflows.Runtime.UnitTests/Elsa.Workflows.Runtime.UnitTests.csproj --filter WorkflowRuntimeFeatureTests +``` diff --git a/specs/010-workflow-json-hardening/research.md b/specs/010-workflow-json-hardening/research.md new file mode 100644 index 000000000..03c83d02f --- /dev/null +++ b/specs/010-workflow-json-hardening/research.md @@ -0,0 +1,25 @@ +# Research: Workflow JSON Type Hardening + +## Decision: Dedicated Workflow JSON Registry + +Use a workflow-specific registry and options object for `TypeJsonConverter`, `PolymorphicObjectConverter`, workflow state serialization, bookmark payload serialization, trigger comparison, hashing, and descriptor contracts. + +**Rationale**: The issue explicitly rejects using `ExpressionOptions` as the workflow JSON trust boundary. A dedicated registry makes the allowed workflow JSON surface explicit while leaving expression aliases available for expression evaluation and designer variable metadata. + +**Alternatives considered**: Reusing `IWellKnownTypeRegistry` was rejected because it is fed by `ExpressionOptions`. Direct `Type.GetType` fallback was rejected because it can load arbitrary CLR names. + +## Decision: Explicit Legacy Compatibility Names + +Compatibility reads accept aliases and registered legacy names, including simple assembly-qualified names, full assembly-qualified names for registered types, and supported collection wrappers over registered element types. + +**Rationale**: Existing persisted workflows may contain CLR names, but the trust boundary must be the registration list, not assembly probing. + +**Alternatives considered**: A broad assembly allow-list was rejected for this slice because it is harder to reason about and can accidentally expose unrelated types from trusted assemblies. + +## Decision: Alias-First Public Descriptor Contract + +Incident strategy descriptors should emit the workflow JSON alias for registered strategies while keeping legacy CLR names readable on input during the compatibility window. + +**Rationale**: The reported dropdown failure came from descriptors returning CLR names while hardened reads expected aliases. Emitting aliases aligns new clients with hardened serialization without breaking old payloads. + +**Alternatives considered**: Keeping CLR names in descriptors was rejected because it perpetuates the inconsistent contract. diff --git a/specs/010-workflow-json-hardening/spec.md b/specs/010-workflow-json-hardening/spec.md new file mode 100644 index 000000000..01ecff726 --- /dev/null +++ b/specs/010-workflow-json-hardening/spec.md @@ -0,0 +1,103 @@ +# Feature Specification: Workflow JSON Type Hardening + +**Feature Branch**: `codex/7541-workflow-json-hardening` +**Created**: 2026-05-29 +**Status**: Draft +**Input**: User description: "GitHub issue #7541: Redo workflow JSON type hardening with dedicated alias design" + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Load Existing Workflows Safely (Priority: P1) + +Operators can upgrade Elsa without losing access to persisted workflows whose JSON contains existing type identifiers, including CLR type names emitted by earlier versions. + +**Why this priority**: Backward compatibility is required before hardening can be reintroduced without breaking production workflows. + +**Independent Test**: Load representative persisted workflow JSON that contains legacy type names and verify the workflow can be read while unknown or unsafe type identifiers are rejected. + +**Acceptance Scenarios**: + +1. **Given** a persisted workflow that references a known legacy type name, **When** the workflow is deserialized after upgrade, **Then** the workflow loads successfully. +2. **Given** a persisted workflow that references an unknown or untrusted type name, **When** the workflow is deserialized, **Then** the workflow is rejected with a clear failure instead of resolving arbitrary types. +3. **Given** a persisted workflow that contains abstract, interface, open generic, or collection type identifiers where a concrete workflow type is required, **When** the workflow is deserialized, **Then** the identifier is rejected. + +--- + +### User Story 2 - Use Consistent Type Identifiers in APIs (Priority: P2) + +API consumers receive consistent type identifiers for workflow-facing options such as incident handling strategies and can submit those identifiers back without relying on implementation-specific names. + +**Why this priority**: The reported incident strategy dropdown failure came from inconsistent contracts between API descriptors and hardened workflow JSON reads. + +**Independent Test**: Request descriptor data for incident strategies, select a returned option, and verify a workflow or workflow definition using that option can be accepted and read. + +**Acceptance Scenarios**: + +1. **Given** API descriptor data for incident handling strategies, **When** the options are returned, **Then** every option uses the documented workflow type identifier contract. +2. **Given** a client submits a supported incident strategy identifier from the descriptor payload, **When** the workflow payload is processed, **Then** the identifier resolves to the intended strategy. +3. **Given** older clients submit legacy CLR identifiers during the compatibility window, **When** the workflow payload is processed, **Then** supported legacy identifiers continue to resolve. + +--- + +### User Story 3 - Register Workflow-Serializable Types Explicitly (Priority: P3) + +Module and extension authors can explicitly register the types and legacy names that are valid in workflow serialization payloads without using expression configuration as the trust boundary. + +**Why this priority**: Hardening must be extensible for built-in modules, custom workflow types, runtime payloads, and third-party extensions. + +**Independent Test**: Register a custom workflow-facing type and legacy identifier, then verify alias-based payloads and supported legacy payloads resolve while unrelated types do not. + +**Acceptance Scenarios**: + +1. **Given** a module registers a workflow-serializable type with an alias, **When** workflow JSON references the alias, **Then** the type resolves successfully. +2. **Given** a module registers a supported legacy name for a workflow-serializable type, **When** compatibility JSON references the legacy name, **Then** the type resolves successfully. +3. **Given** a type is registered only for expression use, **When** workflow JSON references it, **Then** workflow JSON resolution does not accept it unless it is also registered for workflow serialization. + +### Edge Cases + +- Legacy JSON references a CLR type moved between assemblies or renamed after earlier persistence. +- Payloads reference unknown, untrusted, abstract, interface, open generic, array, dictionary, or collection types. +- JSON islands contain values that resemble type metadata but should remain normal JSON data. +- Runtime trigger and bookmark payloads include polymorphic values that need the same trust model as workflow definitions. +- Custom workflow types are registered by host applications or extensions after core services are configured. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: The system MUST keep workflow JSON type resolution separate from expression type alias configuration. +- **FR-002**: The system MUST provide a dedicated registry or resolver for workflow-serializable type identifiers. +- **FR-003**: The system MUST allow built-in modules, extensions, and host applications to register workflow-serializable aliases. +- **FR-004**: The system MUST allow supported legacy type names to be registered for backward-compatible reads. +- **FR-005**: The system MUST document which legacy identifiers remain readable during the compatibility window and how unsupported identifiers fail. +- **FR-006**: The system MUST reject unknown, untrusted, abstract, open generic, interface, and inappropriate collection type identifiers when resolving workflow JSON types. +- **FR-007**: The system MUST continue loading existing workflows that reference supported CLR type names during the compatibility window. +- **FR-008**: The system MUST serialize new workflow-facing payloads with the documented type identifier contract where the payload belongs to that contract. +- **FR-009**: The system MUST keep public API payloads that expose workflow type identifiers internally consistent for request and response flows. +- **FR-010**: The system MUST cover the incident handling strategy option flow with a regression test. +- **FR-011**: The system MUST cover persisted workflow JSON, alias JSON, runtime trigger or bookmark payloads, JSON islands, and custom workflow types with tests. +- **FR-012**: The system MUST document the security model, trust boundaries, and migration behavior before hardened resolution is reintroduced. + +### Key Entities *(include if feature involves data)* + +- **Workflow Type Identifier**: A stable value used in workflow-facing JSON or API payloads to identify an allowed type. +- **Workflow-Serializable Type Registration**: A trusted registration that maps a workflow type identifier and optional legacy names to a concrete allowed type. +- **Compatibility Window**: The supported period or mode in which selected legacy CLR type names remain readable. +- **Public Type Identifier Contract**: The documented request and response behavior for API payloads that expose workflow type identifiers. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: All representative legacy workflow JSON fixtures covered by tests load successfully when they use supported legacy identifiers. +- **SC-002**: Tests demonstrate rejection for unknown, untrusted, abstract, interface, open generic, and inappropriate collection type identifiers. +- **SC-003**: Incident strategy descriptor and submit flows pass a regression test that uses the same identifier contract in both directions. +- **SC-004**: New workflow JSON hardening tests run without depending on expression type alias configuration. +- **SC-005**: Documentation explains the trust model and compatibility behavior clearly enough for module authors to register workflow-serializable types without reading implementation code. + +## Assumptions + +- The compatibility window accepts known Elsa workflow-related CLR type names and explicitly registered host or extension legacy names, not arbitrary CLR resolution. +- Public API type identifier changes can be transitional: aliases are preferred for new payloads while supported legacy values remain readable. +- Existing workflow JSON fixtures are sufficient to represent persisted workflow compatibility risks, with new fixtures added where gaps are found. +- Cloud vault, external migration tooling, and data store schema changes are outside this feature unless existing tests prove they are required. diff --git a/specs/010-workflow-json-hardening/tasks.md b/specs/010-workflow-json-hardening/tasks.md new file mode 100644 index 000000000..00ec64244 --- /dev/null +++ b/specs/010-workflow-json-hardening/tasks.md @@ -0,0 +1,125 @@ +# Tasks: Workflow JSON Type Hardening + +**Input**: Design documents from `/specs/010-workflow-json-hardening/` +**Prerequisites**: plan.md, spec.md, research.md, data-model.md, contracts/ + +**Tests**: Required by the feature specification for compatibility, rejection behavior, incident strategies, runtime payloads, JSON islands, and custom workflow types. + +## Phase 1: Setup (Shared Infrastructure) + +**Purpose**: Confirm the clean worktree and documentation context. + +- [x] T001 Verify the dedicated worktree status in `/Users/sipke/Projects/Elsa/elsa-core-7541` +- [x] T002 Update Spec Kit agent context in `/Users/sipke/Projects/Elsa/elsa-core-7541/AGENTS.md` + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: Add the dedicated workflow JSON trust boundary before changing user-facing behavior. + +- [x] T003 Add serialization type registry contracts in `src/modules/Elsa.Common/Serialization/ISerializationTypeRegistry.cs` +- [x] T004 Add serialization type options in `src/modules/Elsa.Common/Serialization/SerializationTypeOptions.cs` +- [x] T005 Add serialization type registry implementation in `src/modules/Elsa.Common/Serialization/SerializationTypeRegistry.cs` +- [x] T006 Add workflow JSON registration extensions in `src/modules/Elsa.Common/Extensions/SerializationTypeOptionsExtensions.cs` +- [x] T007 Update workflow JSON resolver to use the dedicated registry in `src/modules/Elsa.Common/Serialization/SerializationTypeResolver.cs` +- [x] T008 Update workflow type converters to use the dedicated registry in `src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs`, `src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverter.cs`, `src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs`, and `src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs` + +**Checkpoint**: Workflow JSON converters no longer depend on `ExpressionOptions`. + +--- + +## Phase 3: User Story 1 - Load Existing Workflows Safely (Priority: P1) MVP + +**Goal**: Existing registered CLR type names remain readable while unsafe names fail. + +**Independent Test**: Deserialize legacy workflow JSON/type payloads with registered names and verify unsafe identifiers are rejected. + +### Tests for User Story 1 + +- [x] T009 [US1] Update resolver tests for dedicated registry compatibility in `test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/SerializationTypeResolverTests.cs` +- [x] T010 [US1] Add regression coverage for expression-only aliases not being accepted by workflow JSON in `test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/SerializationTypeResolverTests.cs` + +### Implementation for User Story 1 + +- [x] T011 [US1] Register core workflow JSON aliases and legacy names in `src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs` and `src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs` +- [x] T012 [US1] Update workflow serializers and hashing to consume `ISerializationTypeRegistry` in `src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs`, `src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs`, `src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs`, and `src/modules/Elsa.Workflows.Core/Services/Hasher.cs` + +**Checkpoint**: User Story 1 can be validated independently. + +--- + +## Phase 4: User Story 2 - Use Consistent Type Identifiers in APIs (Priority: P2) + +**Goal**: Incident strategy descriptors emit the same workflow type identifiers that workflow JSON accepts. + +**Independent Test**: Descriptor output for incident strategies returns aliases and supported legacy identifiers remain readable. + +### Tests for User Story 2 + +- [x] T013 [US2] Add incident strategy descriptor regression tests in `test/unit/Elsa.Workflows.Api.UnitTests/Endpoints/IncidentStrategies/ListTests.cs` + +### Implementation for User Story 2 + +- [x] T014 [US2] Register incident strategy aliases and legacy names in `src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs` and `src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs` +- [x] T015 [US2] Emit workflow JSON aliases from incident strategy descriptors in `src/modules/Elsa.Workflows.Api/Endpoints/IncidentStrategies/List/Endpoint.cs` +- [x] T016 [US2] Update client model documentation for identifier semantics in `src/clients/Elsa.Api.Client/Resources/IncidentStrategies/Models/IncidentStrategyDescriptor.cs` + +**Checkpoint**: User Story 2 can be validated independently. + +--- + +## Phase 5: User Story 3 - Register Workflow-Serializable Types Explicitly (Priority: P3) + +**Goal**: Modules and host applications register workflow JSON types without using expression options. + +**Independent Test**: Runtime and extension payloads resolve from workflow JSON registrations while expression-only aliases do not. + +### Tests for User Story 3 + +- [x] T017 [US3] Update runtime feature tests for workflow JSON registrations in `test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs` +- [x] T018 [US3] Update runtime trigger comparer tests for the dedicated registry in `test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs` + +### Implementation for User Story 3 + +- [x] T019 [US3] Move runtime workflow payload registration to workflow JSON options in `src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs`, `src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs`, and `src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs` +- [x] T020 [US3] Move module payload registrations to workflow JSON options in `src/modules/Elsa.Http/Features/HttpFeature.cs`, `src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs`, `src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs`, `src/modules/Elsa.Resilience/Features/ResilienceFeature.cs`, `src/modules/Elsa.Resilience/ShellFeatures/ResilienceFeature.cs`, `src/modules/Elsa.Alterations/Features/AlterationsFeature.cs`, `src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs`, and `src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs` +- [x] T021 [US3] Update runtime trigger comparison to use `ISerializationTypeRegistry` in `src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs` and `src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs` + +**Checkpoint**: User Story 3 can be validated independently. + +--- + +## Phase 6: Polish & Cross-Cutting Concerns + +**Purpose**: Documentation and validation. + +- [x] T022 Add workflow JSON hardening documentation in `doc/wiki/workflow-core.md` +- [x] T023 Run targeted workflow core unit tests with `dotnet test test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj --filter SerializationTypeResolverTests` +- [x] T024 Run targeted workflow runtime unit tests with `dotnet test test/unit/Elsa.Workflows.Runtime.UnitTests/Elsa.Workflows.Runtime.UnitTests.csproj --filter WorkflowRuntimeFeatureTests` +- [x] T025 Review changed files and ensure `.specify/feature.json` and Spec Kit artifacts are correct + +--- + +## Dependencies & Execution Order + +- **Setup**: T001-T002 first. +- **Foundational**: T003-T008 block all user stories. +- **US1**: T009-T012 produces the MVP compatibility slice. +- **US2**: T013-T016 depends on the registry from Foundational and may run after US1. +- **US3**: T017-T021 depends on the registry from Foundational and may run after US1. +- **Polish**: T022-T025 after implementation. + +## Parallel Opportunities + +- Test updates in T009, T013, T017, and T018 can be developed in parallel after T003-T008. +- Module registration moves in T020 can be parallelized by module after the extension API exists. +- Documentation T022 can run after the contract behavior is finalized. + +## Implementation Strategy + +1. Establish the dedicated registry and switch converters. +2. Preserve legacy compatibility for existing workflow JSON. +3. Align incident strategy API descriptors with the registry. +4. Move runtime/module payload registrations off expression options. +5. Validate with targeted tests and documentation. diff --git a/src/apps/Elsa.ModularServer.Web/Program.cs b/src/apps/Elsa.ModularServer.Web/Program.cs index 3a5624e39..f27fae972 100644 --- a/src/apps/Elsa.ModularServer.Web/Program.cs +++ b/src/apps/Elsa.ModularServer.Web/Program.cs @@ -48,7 +48,6 @@ services.AddOpenTelemetry() .AddHttpClientInstrumentation() .AddMeter(WorkflowInstrumentation.MeterName) .AddOtlpExporter(options => ConfigureDiagnosticsOtlpExporter(options, configuration, "metrics"))); - var nuplaneConfiguration = configuration.GetSection("Nuplane"); services.AddNuplane(nuplaneConfiguration, nuplane => diff --git a/src/clients/Elsa.Api.Client/Resources/IncidentStrategies/Models/IncidentStrategyDescriptor.cs b/src/clients/Elsa.Api.Client/Resources/IncidentStrategies/Models/IncidentStrategyDescriptor.cs index fc401f354..657396a88 100644 --- a/src/clients/Elsa.Api.Client/Resources/IncidentStrategies/Models/IncidentStrategyDescriptor.cs +++ b/src/clients/Elsa.Api.Client/Resources/IncidentStrategies/Models/IncidentStrategyDescriptor.cs @@ -3,7 +3,7 @@ namespace Elsa.Api.Client.Resources.IncidentStrategies.Models; /// /// Represents an incident strategy. /// -/// The .NET type name of the strategy. +/// The workflow JSON type identifier of the strategy. /// The display name of the strategy. /// The description of the strategy. -public record IncidentStrategyDescriptor(string TypeName, string DisplayName, string? Description); \ No newline at end of file +public record IncidentStrategyDescriptor(string TypeName, string DisplayName, string? Description); diff --git a/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs b/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs index 2b608d392..6f9173636 100644 --- a/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs +++ b/src/modules/Elsa.Alterations/Features/AlterationsFeature.cs @@ -6,11 +6,12 @@ using Elsa.Alterations.Core.Stores; using Elsa.Alterations.Extensions; using Elsa.Alterations.Services; using Elsa.Alterations.Workflows; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Services; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Alterations.Features; @@ -60,10 +61,10 @@ public class AlterationsFeature : FeatureBase /// public override void Apply() { - Services.Configure(options => + Services.Configure(options => { - options.RegisterTypeAlias(typeof(AlterationPlanParams), typeof(AlterationPlanParams).GetSimpleAssemblyQualifiedName()); options.RegisterTypeAlias(typeof(AlterationPlanParams), nameof(AlterationPlanParams)); + options.RegisterLegacySimpleAssemblyQualifiedName(typeof(AlterationPlanParams)); }); Services.AddScoped(); diff --git a/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs b/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs index aa6962a91..8721c3a9c 100644 --- a/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs +++ b/src/modules/Elsa.Alterations/ShellFeatures/AlterationsFeature.cs @@ -8,10 +8,11 @@ using Elsa.Alterations.Core.Stores; using Elsa.Alterations.Extensions; using Elsa.Alterations.Services; using Elsa.Alterations.Workflows; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; +using Elsa.Workflows.Options; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Alterations.ShellFeatures; @@ -42,10 +43,10 @@ public class AlterationsFeature : IFastEndpointsShellFeature public void ConfigureServices(IServiceCollection services) { - services.Configure(options => + services.Configure(options => { - options.RegisterTypeAlias(typeof(AlterationPlanParams), typeof(AlterationPlanParams).GetSimpleAssemblyQualifiedName()); options.RegisterTypeAlias(typeof(AlterationPlanParams), nameof(AlterationPlanParams)); + options.RegisterLegacySimpleAssemblyQualifiedName(typeof(AlterationPlanParams)); }); services.AddScoped(); diff --git a/src/modules/Elsa.Common/Extensions/SerializationTypeOptionsExtensions.cs b/src/modules/Elsa.Common/Extensions/SerializationTypeOptionsExtensions.cs new file mode 100644 index 000000000..fe257dbe3 --- /dev/null +++ b/src/modules/Elsa.Common/Extensions/SerializationTypeOptionsExtensions.cs @@ -0,0 +1,53 @@ +using Elsa.Common.Serialization; + +// ReSharper disable once CheckNamespace +namespace Elsa.Extensions; + +/// +/// Extends . +/// +public static class SerializationTypeOptionsExtensions +{ + /// + /// Registers a preferred serialization alias. + /// + public static SerializationTypeOptions AddTypeAlias(this SerializationTypeOptions options, string alias) => options.RegisterTypeAlias(typeof(T), alias); + + /// + /// Registers the type name as the preferred serialization alias. + /// + public static SerializationTypeOptions AddTypeAlias(this SerializationTypeOptions options) => options.RegisterTypeAlias(typeof(T), typeof(T).Name); + + /// + /// Registers a preferred serialization alias and the current simple assembly-qualified name as a legacy identifier. + /// + public static SerializationTypeOptions AddTypeAliasWithLegacyName(this SerializationTypeOptions options, Type type, string alias) + { + options.RegisterTypeAlias(type, alias); + options.RegisterLegacySimpleAssemblyQualifiedName(type); + return options; + } + + /// + /// Registers a preferred serialization alias and the current simple assembly-qualified name as a legacy identifier. + /// + public static SerializationTypeOptions AddTypeAliasWithLegacyName(this SerializationTypeOptions options, string alias) => options.AddTypeAliasWithLegacyName(typeof(T), alias); + + /// + /// Registers the current simple assembly-qualified name as a compatibility identifier. + /// + public static SerializationTypeOptions AddLegacySimpleAssemblyQualifiedName(this SerializationTypeOptions options) => options.RegisterLegacySimpleAssemblyQualifiedName(typeof(T)); + + /// + /// Registers the current simple assembly-qualified name as a compatibility identifier. + /// + public static SerializationTypeOptions AddLegacySimpleAssemblyQualifiedName(this SerializationTypeOptions options, Type type) => options.RegisterLegacySimpleAssemblyQualifiedName(type); + + /// + /// Registers the current simple assembly-qualified name as the preferred alias for compatibility-only types. + /// + public static SerializationTypeOptions AddSimpleAssemblyQualifiedTypeAlias(this SerializationTypeOptions options, Type type) + { + return options.RegisterTypeAlias(type, type.GetSimpleAssemblyQualifiedName()); + } +} diff --git a/src/modules/Elsa.Common/Extensions/TypeExtensions.cs b/src/modules/Elsa.Common/Extensions/TypeExtensions.cs index 863a2057b..588eda811 100644 --- a/src/modules/Elsa.Common/Extensions/TypeExtensions.cs +++ b/src/modules/Elsa.Common/Extensions/TypeExtensions.cs @@ -1,3 +1,5 @@ +using System.Collections.Concurrent; + // ReSharper disable once CheckNamespace namespace Elsa.Extensions; @@ -6,6 +8,17 @@ namespace Elsa.Extensions; /// public static class TypeExtensions { + private static readonly ConcurrentDictionary SimpleAssemblyQualifiedTypeNameCache = new(); + + /// + /// Gets the assembly-qualified name of the type, without version, culture, and public key token information. + /// + public static string GetSimpleAssemblyQualifiedName(this Type type) + { + if (type is null) throw new ArgumentNullException(nameof(type)); + return SimpleAssemblyQualifiedTypeNameCache.GetOrAdd(type, BuildSimplifiedName); + } + /// /// Returns true of the type is generic, false otherwise. /// @@ -54,4 +67,22 @@ public static class TypeExtensions { return type.IsPrimitive || type == typeof(decimal) || type == typeof(float) || type == typeof(double) || type == typeof(int) || type == typeof(long) || type == typeof(short) || type == typeof(byte) || type == typeof(uint) || type == typeof(ulong) || type == typeof(ushort) || type == typeof(sbyte); } -} \ No newline at end of file + + private static string BuildSimplifiedName(Type type) + { + var assemblyName = type.Assembly.GetName().Name; + + if (type.IsGenericType) + { + var genericTypeName = type.GetGenericTypeDefinition().FullName!; + var backtickIndex = genericTypeName.IndexOf('`'); + var typeNameWithoutArity = genericTypeName[..backtickIndex]; + var arity = genericTypeName[backtickIndex..]; + var simplifiedGenericArguments = type.GetGenericArguments().Select(BuildSimplifiedName); + + return $"{typeNameWithoutArity}{arity}[[{string.Join("],[", simplifiedGenericArguments)}]], {assemblyName}"; + } + + return $"{type.FullName}, {assemblyName}"; + } +} diff --git a/src/modules/Elsa.Common/Serialization/ISerializationTypeRegistry.cs b/src/modules/Elsa.Common/Serialization/ISerializationTypeRegistry.cs new file mode 100644 index 000000000..123963a1f --- /dev/null +++ b/src/modules/Elsa.Common/Serialization/ISerializationTypeRegistry.cs @@ -0,0 +1,27 @@ +namespace Elsa.Common.Serialization; + +/// +/// A registry of types that may be resolved from serialization type identifiers. +/// +public interface ISerializationTypeRegistry +{ + /// + /// Registers a type with an alias. + /// + void RegisterType(Type type, string alias); + + /// + /// Attempts to get the preferred alias for the specified type. + /// + bool TryGetAlias(Type type, out string alias); + + /// + /// Attempts to get the type associated with the specified alias or legacy name. + /// + bool TryGetType(string alias, out Type type); + + /// + /// Returns all registered types. + /// + IEnumerable ListTypes(); +} diff --git a/src/modules/Elsa.Common/Serialization/SerializationTypeOptions.cs b/src/modules/Elsa.Common/Serialization/SerializationTypeOptions.cs new file mode 100644 index 000000000..d252fd068 --- /dev/null +++ b/src/modules/Elsa.Common/Serialization/SerializationTypeOptions.cs @@ -0,0 +1,85 @@ +using System.Collections.ObjectModel; +using System.Dynamic; +using System.Text.Json; +using System.Text.Json.Nodes; +using Elsa.Extensions; + +namespace Elsa.Common.Serialization; + +/// +/// Options for serialization type identifiers. +/// +public class SerializationTypeOptions +{ + private readonly IDictionary _aliasTypeDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly IDictionary _typeAliasDictionary = new Dictionary(); + + /// + /// Initializes a new instance of the class. + /// + public SerializationTypeOptions() + { + AliasTypeDictionary = new ReadOnlyDictionary(_aliasTypeDictionary); + TypeAliasDictionary = new ReadOnlyDictionary(_typeAliasDictionary); + + RegisterTypeAlias(typeof(short), "Int16"); + RegisterTypeAlias(typeof(int), "Int32"); + RegisterTypeAlias(typeof(long), "Int64"); + RegisterLegacyTypeName(typeof(long), "Long"); + RegisterTypeAlias(typeof(float), "Single"); + RegisterTypeAlias(typeof(object), "Object"); + RegisterTypeAlias(typeof(string), "String"); + RegisterTypeAlias(typeof(bool), "Boolean"); + RegisterTypeAlias(typeof(decimal), "Decimal"); + RegisterTypeAlias(typeof(double), "Double"); + RegisterTypeAlias(typeof(byte[]), "ByteArray"); + RegisterTypeAlias(typeof(Guid), nameof(Guid)); + RegisterTypeAlias(typeof(DateTime), nameof(DateTime)); + RegisterTypeAlias(typeof(DateTimeOffset), nameof(DateTimeOffset)); + RegisterTypeAlias(typeof(TimeSpan), nameof(TimeSpan)); + RegisterTypeAlias(typeof(Stream), nameof(Stream)); + RegisterTypeAlias(typeof(ExpandoObject), "JSON"); + RegisterTypeAlias(typeof(JsonElement), nameof(JsonElement)); + RegisterTypeAlias(typeof(JsonNode), nameof(JsonNode)); + RegisterTypeAlias(typeof(JsonObject), nameof(JsonObject)); + RegisterTypeAlias(typeof(JsonArray), nameof(JsonArray)); + RegisterTypeAlias(typeof(IDictionary), "StringDictionary"); + RegisterTypeAlias(typeof(IDictionary), "ObjectDictionary"); + RegisterTypeAlias(typeof(Dictionary), "StringMap"); + RegisterTypeAlias(typeof(Dictionary), "ObjectMap"); + } + + /// + /// Gets aliases and legacy names keyed by identifier. + /// + public IDictionary AliasTypeDictionary { get; } + + /// + /// Gets preferred aliases keyed by type. + /// + public IDictionary TypeAliasDictionary { get; } + + /// + /// Registers a preferred serialization alias. + /// + public SerializationTypeOptions RegisterTypeAlias(Type type, string alias) + { + _aliasTypeDictionary[alias] = type; + _typeAliasDictionary[type] = alias; + return this; + } + + /// + /// Registers a legacy serialization identifier for compatibility reads. + /// + public SerializationTypeOptions RegisterLegacyTypeName(Type type, string typeName) + { + _aliasTypeDictionary[typeName] = type; + return this; + } + + /// + /// Registers the type's simple assembly-qualified name as a legacy serialization identifier. + /// + public SerializationTypeOptions RegisterLegacySimpleAssemblyQualifiedName(Type type) => RegisterLegacyTypeName(type, type.GetSimpleAssemblyQualifiedName()); +} diff --git a/src/modules/Elsa.Common/Serialization/SerializationTypeRegistry.cs b/src/modules/Elsa.Common/Serialization/SerializationTypeRegistry.cs new file mode 100644 index 000000000..9b02f2d61 --- /dev/null +++ b/src/modules/Elsa.Common/Serialization/SerializationTypeRegistry.cs @@ -0,0 +1,60 @@ +using Microsoft.Extensions.Options; + +namespace Elsa.Common.Serialization; + +/// +public class SerializationTypeRegistry : ISerializationTypeRegistry +{ + private readonly Dictionary _aliasTypeDictionary = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _typeAliasDictionary = new(); + + /// + /// Creates a default registry. + /// + public static ISerializationTypeRegistry CreateDefault() + { + return new SerializationTypeRegistry(Microsoft.Extensions.Options.Options.Create(new SerializationTypeOptions())); + } + + /// + /// Initializes a new instance of the class. + /// + public SerializationTypeRegistry(IOptions options) + { + foreach (var entry in options.Value.AliasTypeDictionary) + RegisterTypeName(entry.Value, entry.Key); + + foreach (var entry in options.Value.TypeAliasDictionary) + RegisterType(entry.Key, entry.Value); + } + + /// + public void RegisterType(Type type, string alias) + { + _typeAliasDictionary[type] = alias; + RegisterTypeName(type, alias); + } + + /// + public bool TryGetAlias(Type type, out string alias) => _typeAliasDictionary.TryGetValue(type, out alias!); + + /// + public bool TryGetType(string alias, out Type type) => _aliasTypeDictionary.TryGetValue(alias, out type!); + + /// + public IEnumerable ListTypes() => _aliasTypeDictionary.Values.Distinct(); + + private void RegisterTypeName(Type type, string alias) + { + _aliasTypeDictionary[alias] = type; + + if (type.IsPrimitive || type.IsValueType && Nullable.GetUnderlyingType(type) == null) + { + var nullableType = typeof(Nullable<>).MakeGenericType(type); + _aliasTypeDictionary[$"{alias}?"] = nullableType; + + if (_typeAliasDictionary.ContainsKey(type)) + _typeAliasDictionary[nullableType] = $"{alias}?"; + } + } +} diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs b/src/modules/Elsa.Common/Serialization/SerializationTypeResolver.cs similarity index 60% rename from src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs rename to src/modules/Elsa.Common/Serialization/SerializationTypeResolver.cs index d5258b9ae..250a25326 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Helpers/WorkflowJsonTypeResolver.cs +++ b/src/modules/Elsa.Common/Serialization/SerializationTypeResolver.cs @@ -3,14 +3,13 @@ using System.Collections.ObjectModel; using System.Reflection; using System.Text.Json; using Elsa.Extensions; -using Elsa.Workflows.Serialization.Options; -namespace Elsa.Workflows.Serialization.Helpers; +namespace Elsa.Common.Serialization; /// -/// Resolves workflow JSON type aliases and CLR type names. +/// Resolves serialization type aliases without loading arbitrary CLR type names. /// -public static class WorkflowJsonTypeResolver +public static class SerializationTypeResolver { private static readonly IDictionary GenericCollectionTypes = new Dictionary(StringComparer.Ordinal) { @@ -52,47 +51,85 @@ public static class WorkflowJsonTypeResolver [typeof(IDictionary)] = typeof(Dictionary) }; - public static Type ResolveType(WorkflowJsonOptions workflowJsonOptions, string? typeAlias, bool allowLegacyClrTypeNames = true) + /// + /// Resolves the specified serialization type alias. + /// + public static Type ResolveType(ISerializationTypeRegistry serializationTypeRegistry, string? typeAlias) { if (string.IsNullOrWhiteSpace(typeAlias)) - throw new JsonException("The workflow JSON type alias is missing."); + throw new JsonException("The serialization type alias is missing."); - if (TryResolveType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, out var type)) + if (TryResolveType(serializationTypeRegistry, typeAlias, out var type)) return type; - var supportedTypeNames = allowLegacyClrTypeNames - ? "Registered aliases, supported compound aliases, and CLR type names" - : "Registered aliases, supported compound aliases, and registered legacy CLR type names"; - throw new JsonException($"Unknown workflow JSON type alias '{typeAlias}'. {supportedTypeNames} can be deserialized."); + throw new JsonException( + $"Unknown serialization type alias '{typeAlias}'. Only registered aliases and supported compound aliases can be deserialized."); } - public static bool TryResolveType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, out Type type) - { - return TryResolveType(workflowJsonOptions, typeAlias, true, out type); - } - - public static bool TryResolveType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, out Type type) + /// + /// Attempts to resolve the specified serialization type alias. + /// + public static bool TryResolveType(ISerializationTypeRegistry serializationTypeRegistry, string typeAlias, out Type type) { IReadOnlyList? registeredTypes = null; - return TryResolveType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type); + return TryResolveType(serializationTypeRegistry, typeAlias, ref registeredTypes, out type); } - public static bool TryGetAlias(WorkflowJsonOptions workflowJsonOptions, Type type, out string alias) + private static bool TryResolveType(ISerializationTypeRegistry serializationTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) { - if (workflowJsonOptions.TryGetAlias(type, out alias!)) + if (serializationTypeRegistry.TryGetType(typeAlias, out var registeredType)) + { + type = registeredType; + return true; + } + + if (TryResolveArrayType(serializationTypeRegistry, typeAlias, ref registeredTypes, out var arrayType)) + { + type = arrayType; + return true; + } + + if (TryResolveGenericCollectionType(serializationTypeRegistry, typeAlias, ref registeredTypes, out var genericCollectionType)) + { + type = genericCollectionType; + return true; + } + + if (TryResolveRegisteredLegacyTypeName(serializationTypeRegistry, typeAlias, ref registeredTypes, out var legacyType)) + { + type = legacyType; + return true; + } + + type = null!; + return false; + } + + /// + /// Attempts to return a serialization type alias that this resolver can read back. + /// + public static bool TryGetAlias(ISerializationTypeRegistry serializationTypeRegistry, Type type, out string alias) + { + if (serializationTypeRegistry.TryGetAlias(type, out alias!)) return true; - if (type.IsArray && TryGetAlias(workflowJsonOptions, type.GetElementType()!, out var elementTypeAlias)) + if (type.IsArray) { - alias = $"{elementTypeAlias}[]"; - return true; + var elementType = type.GetElementType()!; + + if (TryGetAlias(serializationTypeRegistry, elementType, out var elementTypeAlias)) + { + alias = $"{elementTypeAlias}[]"; + return true; + } } if (type is { IsGenericType: true, GenericTypeArguments.Length: 1 }) { var genericTypeDefinition = type.GetGenericTypeDefinition(); + if (TryGetWritableGenericCollectionAlias(genericTypeDefinition, out var genericTypeAlias) && - TryGetAlias(workflowJsonOptions, type.GenericTypeArguments[0], out elementTypeAlias)) + TryGetAlias(serializationTypeRegistry, type.GenericTypeArguments[0], out var elementTypeAlias)) { alias = $"{genericTypeAlias}<{elementTypeAlias}>"; return true; @@ -103,17 +140,9 @@ public static class WorkflowJsonTypeResolver return false; } - public static string GetAliasOrLegacyClrTypeName(WorkflowJsonOptions workflowJsonOptions, Type type) - { - if (TryGetAlias(workflowJsonOptions, type, out var alias)) - return alias; - - if (!workflowJsonOptions.AllowLegacyClrTypeNames) - throw new JsonException($"Type '{type}' is not registered as a workflow JSON type alias."); - - return type.GetSimpleAssemblyQualifiedName(); - } - + /// + /// Attempts to map a supported collection interface type to an instantiable concrete type. + /// public static bool TryGetInstantiableCollectionType(Type type, out Type instantiableType) { if (type.IsGenericType) @@ -133,41 +162,22 @@ public static class WorkflowJsonTypeResolver return false; } - private static bool TryResolveType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) - { - if (workflowJsonOptions.TryGetType(typeAlias, out type!)) - return true; - - if (TryResolveArrayType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) - return true; - - if (TryResolveGenericCollectionType(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) - return true; - - if (TryResolveRegisteredLegacyTypeName(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) - return true; - - if (allowLegacyClrTypeNames && TryResolveClrTypeName(typeAlias, out type)) - return true; - - type = null!; - return false; - } - - private static bool TryResolveArrayType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) + private static bool TryResolveArrayType(ISerializationTypeRegistry serializationTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) { type = null!; + if (!typeAlias.EndsWith("[]", StringComparison.Ordinal)) return false; - if (!TryResolveType(workflowJsonOptions, typeAlias[..^2], allowLegacyClrTypeNames, ref registeredTypes, out var elementType)) + var elementTypeAlias = typeAlias[..^2]; + if (!TryResolveType(serializationTypeRegistry, elementTypeAlias, ref registeredTypes, out var elementType)) return false; type = elementType.MakeArrayType(); return true; } - private static bool TryResolveGenericCollectionType(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) + private static bool TryResolveGenericCollectionType(ISerializationTypeRegistry serializationTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) { type = null!; var genericStart = typeAlias.IndexOf('<', StringComparison.Ordinal); @@ -175,10 +185,12 @@ public static class WorkflowJsonTypeResolver if (genericStart <= 0 || !typeAlias.EndsWith(">", StringComparison.Ordinal)) return false; - if (!GenericCollectionTypes.TryGetValue(typeAlias[..genericStart], out var genericTypeDefinition)) + var genericTypeAlias = typeAlias[..genericStart]; + if (!GenericCollectionTypes.TryGetValue(genericTypeAlias, out var genericTypeDefinition)) return false; - if (!TryResolveType(workflowJsonOptions, typeAlias[(genericStart + 1)..^1], allowLegacyClrTypeNames, ref registeredTypes, out var elementType)) + var elementTypeAlias = typeAlias[(genericStart + 1)..^1]; + if (!TryResolveType(serializationTypeRegistry, elementTypeAlias, ref registeredTypes, out var elementType)) return false; type = genericTypeDefinition.MakeGenericType(elementType); @@ -192,60 +204,59 @@ public static class WorkflowJsonTypeResolver if (GenericCollectionInterfaceMappings.TryGetValue(genericTypeDefinition, out var instantiableGenericTypeDefinition) && GenericCollectionAliases.TryGetValue(instantiableGenericTypeDefinition, out alias!)) + { return true; + } alias = null!; return false; } - private static bool TryResolveClrTypeName(string typeAlias, out Type type) + private static bool TryResolveRegisteredLegacyTypeName(ISerializationTypeRegistry serializationTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) { - try - { - type = Type.GetType(typeAlias, false)!; - return type != null; - } - catch (Exception e) when (e is ArgumentException or FileLoadException or FileNotFoundException or TypeLoadException or BadImageFormatException) - { - type = null!; - return false; - } - } - - private static bool TryResolveRegisteredLegacyTypeName(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) - { - registeredTypes ??= workflowJsonOptions.ListTypes().ToArray(); + registeredTypes ??= GetRegisteredTypes(serializationTypeRegistry); var registeredTypeSnapshot = registeredTypes; - type = registeredTypeSnapshot.FirstOrDefault(x => - string.Equals(x.GetSimpleAssemblyQualifiedName(), typeAlias, StringComparison.Ordinal) || - string.Equals(x.AssemblyQualifiedName, typeAlias, StringComparison.Ordinal))!; - - if (type != null) + if (TryResolveRegisteredSimpleAssemblyQualifiedName(registeredTypeSnapshot, typeAlias, out type)) return true; - if (TryResolveLegacyGenericCollectionTypeName(workflowJsonOptions, typeAlias, allowLegacyClrTypeNames, ref registeredTypes, out type)) + if (TryResolveLegacyGenericCollectionTypeName(serializationTypeRegistry, typeAlias, ref registeredTypes, out type)) return true; + Type? resolvedType; + try { - var resolvedType = Type.GetType( + resolvedType = Type.GetType( typeAlias, assemblyName => ResolveAssembly(registeredTypeSnapshot, assemblyName), (assembly, typeName, ignoreCase) => ResolveType(registeredTypeSnapshot, assembly, typeName, ignoreCase), false); - - type = resolvedType!; - return resolvedType != null; } catch (Exception e) when (e is ArgumentException or FileLoadException) { - type = null!; - return false; + resolvedType = null; } + + type = resolvedType!; + return resolvedType != null; } - private static bool TryResolveLegacyGenericCollectionTypeName(WorkflowJsonOptions workflowJsonOptions, string typeAlias, bool allowLegacyClrTypeNames, ref IReadOnlyList? registeredTypes, out Type type) + private static IReadOnlyList GetRegisteredTypes(ISerializationTypeRegistry serializationTypeRegistry) + { + return serializationTypeRegistry.ListTypes().ToArray(); + } + + private static bool TryResolveRegisteredSimpleAssemblyQualifiedName(IEnumerable registeredTypes, string typeAlias, out Type type) + { + type = registeredTypes.FirstOrDefault(x => + string.Equals(x.GetSimpleAssemblyQualifiedName(), typeAlias, StringComparison.Ordinal) || + string.Equals(x.AssemblyQualifiedName, typeAlias, StringComparison.Ordinal))!; + + return type != null; + } + + private static bool TryResolveLegacyGenericCollectionTypeName(ISerializationTypeRegistry serializationTypeRegistry, string typeAlias, ref IReadOnlyList? registeredTypes, out Type type) { type = null!; @@ -261,9 +272,11 @@ public static class WorkflowJsonTypeResolver if (!string.Equals(assemblyName, genericTypeDefinition.Assembly.GetName().Name, StringComparison.Ordinal)) continue; - if (!TryResolveType(workflowJsonOptions, typeAlias[prefix.Length..separatorIndex], allowLegacyClrTypeNames, ref registeredTypes, out var elementType)) + var elementTypeAlias = typeAlias[prefix.Length..separatorIndex]; + if (!TryResolveType(serializationTypeRegistry, elementTypeAlias, ref registeredTypes, out var elementType)) return false; + // The resolver only closes known collection definitions over registered element types. #pragma warning disable IL2055 type = genericTypeDefinition.MakeGenericType(elementType); #pragma warning restore IL2055 diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs index b4b0e42fb..3579ac646 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Contracts/ElsaConsoleLogFilter.cs @@ -5,21 +5,21 @@ namespace Elsa.Diagnostics.ConsoleLogs.Contracts; /// /// Console log filter accepted by Elsa REST and SignalR endpoints. /// -public sealed class ElsaConsoleLogFilter +public sealed record ElsaConsoleLogFilter { - public string? SourceId { get; set; } + public string? SourceId { get; init; } [JsonConverter(typeof(ConsoleStreamJsonConverter))] - public global::ConsoleLogStreaming.Core.Models.ConsoleStream? Stream { get; set; } - public string? Query { get; set; } - public string? WorkflowInstanceId { get; set; } - public string? WorkflowDefinitionId { get; set; } - public string? WorkflowDefinitionVersionId { get; set; } - public string? ActivityInstanceId { get; set; } - public string? ActivityId { get; set; } - public string? ActivityNodeId { get; set; } - public IDictionary? Metadata { get; set; } - public DateTimeOffset? From { get; set; } - public DateTimeOffset? To { get; set; } - public int? Limit { get; set; } -} + public global::ConsoleLogStreaming.Core.Models.ConsoleStream? Stream { get; init; } + public string? Query { get; init; } + public string? WorkflowInstanceId { get; init; } + public string? WorkflowDefinitionId { get; init; } + public string? WorkflowDefinitionVersionId { get; init; } + public string? ActivityInstanceId { get; init; } + public string? ActivityId { get; init; } + public string? ActivityNodeId { get; init; } + public IReadOnlyDictionary? Metadata { get; init; } + public DateTimeOffset? From { get; init; } + public DateTimeOffset? To { get; init; } + public int? Limit { get; init; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs b/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs index 81858b72b..39246d9b7 100644 --- a/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs +++ b/src/modules/Elsa.Diagnostics.ConsoleLogs/Endpoints/ConsoleLogs/Sources/Endpoint.cs @@ -2,6 +2,7 @@ using ConsoleLogStreaming.Core; using Elsa.Abstractions; using Elsa.Diagnostics.ConsoleLogs.Permissions; using JetBrains.Annotations; +using ConsoleLogSource = ConsoleLogStreaming.Core.Models.ConsoleLogSource; namespace Elsa.Diagnostics.ConsoleLogs.Endpoints.ConsoleLogs.Sources; @@ -16,6 +17,7 @@ internal class Endpoint(IConsoleLogProvider provider) : ElsaEndpointWithoutReque public override async Task> ExecuteAsync(CancellationToken cancellationToken) { - return await provider.ListSourcesAsync(cancellationToken); + var sources = await provider.ListSourcesAsync(cancellationToken); + return sources.ToList(); } } diff --git a/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs b/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs index 043008a60..23c0a8281 100644 --- a/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs +++ b/src/modules/Elsa.Expressions.JavaScript/Features/JavaScriptFeature.cs @@ -1,4 +1,5 @@ using Elsa.Caching.Features; +using Elsa.Expressions.Options; using Elsa.Common.Features; using Elsa.Expressions.Features; using Elsa.Extensions; @@ -15,7 +16,9 @@ using Elsa.Expressions.JavaScript.Services; using Elsa.Expressions.JavaScript.TypeDefinitions.Contracts; using Elsa.Expressions.JavaScript.TypeDefinitions.Services; using Elsa.Workflows; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Expressions.JavaScript.Features; @@ -59,6 +62,8 @@ public class JavaScriptFeature : FeatureBase public override void Apply() { Services.Configure(JintOptions); + Services.Configure(JavaScriptExceptionTypeAliasRegistrar.Register); + Services.Configure(JavaScriptExceptionTypeAliasRegistrar.Register); // JavaScript services. Services @@ -72,7 +77,7 @@ public class JavaScriptFeature : FeatureBase .AddScoped() .AddScoped() .AddScoped() - .AddSingleton() + .AddSingleton() .AddFunctionDefinitionProvider() .AddFunctionDefinitionProvider() .AddFunctionDefinitionProvider() @@ -94,4 +99,4 @@ public class JavaScriptFeature : FeatureBase // UI property handlers. Services.AddScoped(); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs b/src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs new file mode 100644 index 000000000..7ad876ba6 --- /dev/null +++ b/src/modules/Elsa.Expressions.JavaScript/JavaScriptExceptionTypeAliasRegistrar.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using Acornima; +using Elsa.Expressions.Options; +using Elsa.Workflows.Options; +using Jint; +using Jint.Runtime; +using Elsa.Common.Serialization; + +namespace Elsa.Expressions.JavaScript; + +internal static class JavaScriptExceptionTypeAliasRegistrar +{ + public static void Register(ExpressionOptions options) + { + options.RegisterTypeAlias(typeof(ScriptPreparationException), nameof(ScriptPreparationException)); + options.RegisterTypeAlias(typeof(JavaScriptException), nameof(JavaScriptException)); + options.RegisterTypeAlias(typeof(SyntaxErrorException), nameof(SyntaxErrorException)); + + var wrapperExceptionType = typeof(JavaScriptException).GetNestedType("JavaScriptErrorWrapperException", BindingFlags.Public | BindingFlags.NonPublic); + if (wrapperExceptionType != null) + options.RegisterTypeAlias(wrapperExceptionType, "Jint.JavaScriptErrorWrapperException"); + } + + public static void Register(SerializationTypeOptions options) + { + options.RegisterTypeAlias(typeof(ScriptPreparationException), nameof(ScriptPreparationException)); + options.RegisterTypeAlias(typeof(JavaScriptException), nameof(JavaScriptException)); + options.RegisterTypeAlias(typeof(SyntaxErrorException), nameof(SyntaxErrorException)); + + var wrapperExceptionType = typeof(JavaScriptException).GetNestedType("JavaScriptErrorWrapperException", BindingFlags.Public | BindingFlags.NonPublic); + if (wrapperExceptionType != null) + options.RegisterTypeAlias(wrapperExceptionType, "Jint.JavaScriptErrorWrapperException"); + } +} diff --git a/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs b/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs index 8111b335b..27edd192c 100644 --- a/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs +++ b/src/modules/Elsa.Expressions.JavaScript/ShellFeatures/JavaScriptFeature.cs @@ -8,11 +8,14 @@ using Elsa.Expressions.JavaScript.Providers; using Elsa.Expressions.JavaScript.Services; using Elsa.Expressions.JavaScript.TypeDefinitions.Contracts; using Elsa.Expressions.JavaScript.TypeDefinitions.Services; +using Elsa.Expressions.Options; using Elsa.Extensions; using Elsa.PackageManifest.Generator.Hints; using Elsa.Workflows; +using Elsa.Workflows.Options; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Expressions.JavaScript.ShellFeatures; @@ -104,6 +107,8 @@ public class JavaScriptFeature : IShellFeature options.DisableWrappers = DisableWrappers; options.DisableVariableCopying = DisableVariableCopying; }); + services.Configure(JavaScriptExceptionTypeAliasRegistrar.Register); + services.Configure(JavaScriptExceptionTypeAliasRegistrar.Register); // JavaScript services. services @@ -115,7 +120,7 @@ public class JavaScriptFeature : IShellFeature .AddScoped() .AddScoped() .AddScoped() - .AddSingleton() + .AddSingleton() .AddFunctionDefinitionProvider() .AddFunctionDefinitionProvider() .AddFunctionDefinitionProvider() diff --git a/src/modules/Elsa.Expressions/Extensions/TypeExtensions.cs b/src/modules/Elsa.Expressions/Extensions/TypeExtensions.cs index 09b5990a4..b88e4e1ad 100644 --- a/src/modules/Elsa.Expressions/Extensions/TypeExtensions.cs +++ b/src/modules/Elsa.Expressions/Extensions/TypeExtensions.cs @@ -1,4 +1,3 @@ -using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Text; using Elsa.Expressions.Models; @@ -11,18 +10,6 @@ namespace Elsa.Extensions; /// public static class TypeExtensions { - private static readonly ConcurrentDictionary SimpleAssemblyQualifiedTypeNameCache = new(); - - /// - /// Gets the assembly-qualified name of the type, without any version info etc. - /// E.g. "System.String, System.Private.CoreLib" - /// - public static string GetSimpleAssemblyQualifiedName(this Type type) - { - if (type is null) throw new ArgumentNullException(nameof(type)); - return SimpleAssemblyQualifiedTypeNameCache.GetOrAdd(type, GetSimplifiedName); - } - /// /// Returns the default value for the specified type. /// @@ -113,24 +100,4 @@ public static class TypeExtensions return sb.ToString(); } - private static string GetSimplifiedName(Type type) - { - var assemblyName = type.Assembly.GetName().Name; - - if (type.IsGenericType) - { - var genericTypeName = type.GetGenericTypeDefinition().FullName!; - var backtickIndex = genericTypeName.IndexOf('`'); - var typeNameWithoutArity = genericTypeName[..backtickIndex]; - var arity = genericTypeName[backtickIndex..]; - - var genericArguments = type.GetGenericArguments(); - var simplifiedGenericArguments = genericArguments.Select(GetSimplifiedName); - - return $"{typeNameWithoutArity}{arity}[[{string.Join("],[", simplifiedGenericArguments)}]], {assemblyName}"; - } - - var typeName = type.FullName; - return $"{typeName}, {assemblyName}"; - } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Http/Features/HttpFeature.cs b/src/modules/Elsa.Http/Features/HttpFeature.cs index 6df56020f..6e406665a 100644 --- a/src/modules/Elsa.Http/Features/HttpFeature.cs +++ b/src/modules/Elsa.Http/Features/HttpFeature.cs @@ -1,5 +1,4 @@ using System.Net; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -21,12 +20,14 @@ using Elsa.Http.UIHints; using Elsa.Resilience.Extensions; using Elsa.Resilience.Features; using Elsa.Workflows; +using Elsa.Workflows.Options; using FluentStorage; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Http.Features; @@ -247,22 +248,22 @@ public class HttpFeature(IModule module) : FeatureBase(module) foreach (var httpWorkflowInstanceIdSelectorType in HttpWorkflowInstanceIdSelectorTypes) Services.AddScoped(typeof(IHttpWorkflowInstanceIdSelector), httpWorkflowInstanceIdSelectorType); - Services.Configure(options => + Services.Configure(options => { - options.AddTypeAlias("HttpRequest"); - options.AddTypeAlias("HttpResponse"); - options.AddTypeAlias("HttpResponseMessage"); - options.AddTypeAlias("HttpHeaders"); - options.AddTypeAlias("RouteData"); - options.AddTypeAlias("FormFile"); - options.AddTypeAlias("FormFile[]"); - options.AddTypeAlias("HttpFile"); - options.AddTypeAlias("HttpFile[]"); - options.AddTypeAlias("Downloadable"); - options.AddTypeAlias("Downloadable[]"); - options.AddTypeAlias(); - options.AddTypeAlias(); - options.AddTypeAlias(); + options.RegisterTypeAlias(typeof(HttpRequest), "HttpRequest"); + options.RegisterTypeAlias(typeof(HttpResponse), "HttpResponse"); + options.RegisterTypeAlias(typeof(HttpResponseMessage), "HttpResponseMessage"); + options.RegisterTypeAlias(typeof(HttpHeaders), "HttpHeaders"); + options.RegisterTypeAlias(typeof(HttpRouteData), "RouteData"); + options.RegisterTypeAlias(typeof(IFormFile), "FormFile"); + options.RegisterTypeAlias(typeof(IFormFile[]), "FormFile[]"); + options.RegisterTypeAlias(typeof(HttpFile), "HttpFile"); + options.RegisterTypeAlias(typeof(HttpFile[]), "HttpFile[]"); + options.RegisterTypeAlias(typeof(Downloadable), "Downloadable"); + options.RegisterTypeAlias(typeof(Downloadable[]), "Downloadable[]"); + options.RegisterTypeAlias(typeof(HttpStatusCode), nameof(HttpStatusCode)); + options.RegisterTypeAlias(typeof(HttpRequestException), nameof(HttpRequestException)); + options.RegisterTypeAlias(typeof(HttpEndpointBookmarkPayload), nameof(HttpEndpointBookmarkPayload)); }); } } diff --git a/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs b/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs index b59c0874b..7f333e191 100644 --- a/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs +++ b/src/modules/Elsa.Http/ShellFeatures/HttpFeature.cs @@ -1,7 +1,6 @@ using System.Net; using CShells.AspNetCore.Features; using CShells.Features; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Http.Bookmarks; using Elsa.Http.ContentWriters; @@ -20,6 +19,7 @@ using Elsa.Http.UIHints; using Elsa.Resilience.Extensions; using Elsa.Workflows; using Elsa.Workflows.Management.Extensions; +using Elsa.Workflows.Options; using FluentStorage; using JetBrains.Annotations; using Microsoft.AspNetCore.Builder; @@ -28,6 +28,7 @@ using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Http.ShellFeatures; @@ -218,22 +219,22 @@ public class HttpFeature : IMiddlewareShellFeature foreach (var httpWorkflowInstanceIdSelectorType in HttpWorkflowInstanceIdSelectorTypes) services.AddScoped(typeof(IHttpWorkflowInstanceIdSelector), httpWorkflowInstanceIdSelectorType); - services.Configure(options => + services.Configure(options => { - options.AddTypeAlias("HttpRequest"); - options.AddTypeAlias("HttpResponse"); - options.AddTypeAlias("HttpResponseMessage"); - options.AddTypeAlias("HttpHeaders"); - options.AddTypeAlias("RouteData"); - options.AddTypeAlias("FormFile"); - options.AddTypeAlias("FormFile[]"); - options.AddTypeAlias("HttpFile"); - options.AddTypeAlias("HttpFile[]"); - options.AddTypeAlias("Downloadable"); - options.AddTypeAlias("Downloadable[]"); - options.AddTypeAlias(); - options.AddTypeAlias(); - options.AddTypeAlias(); + options.RegisterTypeAlias(typeof(HttpRequest), "HttpRequest"); + options.RegisterTypeAlias(typeof(HttpResponse), "HttpResponse"); + options.RegisterTypeAlias(typeof(HttpResponseMessage), "HttpResponseMessage"); + options.RegisterTypeAlias(typeof(HttpHeaders), "HttpHeaders"); + options.RegisterTypeAlias(typeof(HttpRouteData), "RouteData"); + options.RegisterTypeAlias(typeof(IFormFile), "FormFile"); + options.RegisterTypeAlias(typeof(IFormFile[]), "FormFile[]"); + options.RegisterTypeAlias(typeof(HttpFile), "HttpFile"); + options.RegisterTypeAlias(typeof(HttpFile[]), "HttpFile[]"); + options.RegisterTypeAlias(typeof(Downloadable), "Downloadable"); + options.RegisterTypeAlias(typeof(Downloadable[]), "Downloadable[]"); + options.RegisterTypeAlias(typeof(HttpStatusCode), nameof(HttpStatusCode)); + options.RegisterTypeAlias(typeof(HttpRequestException), nameof(HttpRequestException)); + options.RegisterTypeAlias(typeof(HttpEndpointBookmarkPayload), nameof(HttpEndpointBookmarkPayload)); }); } diff --git a/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs b/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs index 0c8e27392..b13b41a41 100644 --- a/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs +++ b/src/modules/Elsa.Persistence.EFCore/Modules/Management/WorkflowDefinitionPersistenceFeature.cs @@ -1,7 +1,9 @@ +using Elsa.Expressions.Options; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Features; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Persistence.EFCore.Modules.Management; @@ -28,4 +30,4 @@ public class EFCoreWorkflowDefinitionPersistenceFeature(IModule module) : Persis base.Apply(); AddEntityStore(); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Resilience/Features/ResilienceFeature.cs b/src/modules/Elsa.Resilience/Features/ResilienceFeature.cs index 5cc8f6d3e..887ff7de5 100644 --- a/src/modules/Elsa.Resilience/Features/ResilienceFeature.cs +++ b/src/modules/Elsa.Resilience/Features/ResilienceFeature.cs @@ -10,8 +10,10 @@ using Elsa.Resilience.Recorders; using Elsa.Resilience.Serialization; using Elsa.Resilience.StrategySources; using Elsa.Workflows; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Elsa.Common.Serialization; namespace Elsa.Resilience.Features; @@ -66,6 +68,11 @@ public class ResilienceFeature(IModule module) : FeatureBase(module) { options.AddTypeAlias>("RetryAttemptRecordList"); }); + + Services.Configure(options => + { + options.RegisterTypeAlias(typeof(List), "RetryAttemptRecordList"); + }); } public override void Apply() diff --git a/src/modules/Elsa.Resilience/ShellFeatures/ResilienceFeature.cs b/src/modules/Elsa.Resilience/ShellFeatures/ResilienceFeature.cs index 4e57ce778..dedacd3c5 100644 --- a/src/modules/Elsa.Resilience/ShellFeatures/ResilienceFeature.cs +++ b/src/modules/Elsa.Resilience/ShellFeatures/ResilienceFeature.cs @@ -10,8 +10,10 @@ using Elsa.Resilience.Recorders; using Elsa.Resilience.Serialization; using Elsa.Resilience.StrategySources; using Elsa.Workflows; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Elsa.Common.Serialization; namespace Elsa.Resilience.ShellFeatures; @@ -26,6 +28,11 @@ public class ResilienceFeature : IFastEndpointsShellFeature { options.AddTypeAlias>("RetryAttemptRecordList"); }); + + services.Configure(options => + { + options.RegisterTypeAlias(typeof(List), "RetryAttemptRecordList"); + }); services.AddOptions(); services.AddOptions(); diff --git a/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs b/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs index df06db78e..20efd0a61 100644 --- a/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs +++ b/src/modules/Elsa.Scheduling/Features/SchedulingFeature.cs @@ -1,6 +1,5 @@ using Elsa.Common.Features; using Elsa.Common.Multitenancy; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -11,7 +10,9 @@ using Elsa.Scheduling.Services; using Elsa.Scheduling.StartupTasks; using Elsa.Scheduling.TriggerPayloadValidators; using Elsa.Workflows.Management.Features; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Scheduling.Features; @@ -58,14 +59,14 @@ public class SchedulingFeature : FeatureBase // Graceful shutdown: register scheduled-trigger ingress for diagnostic visibility (FR-006). .AddSingleton(); - Services.Configure(options => + Services.Configure(options => { - options.AddTypeAlias(); - options.AddTypeAlias(); - options.AddTypeAlias(); - options.AddTypeAlias(); - options.AddTypeAlias(); - options.AddTypeAlias(); + options.RegisterTypeAlias(typeof(CronBookmarkPayload), nameof(CronBookmarkPayload)); + options.RegisterTypeAlias(typeof(CronTriggerPayload), nameof(CronTriggerPayload)); + options.RegisterTypeAlias(typeof(DelayPayload), nameof(DelayPayload)); + options.RegisterTypeAlias(typeof(StartAtPayload), nameof(StartAtPayload)); + options.RegisterTypeAlias(typeof(TimerBookmarkPayload), nameof(TimerBookmarkPayload)); + options.RegisterTypeAlias(typeof(TimerTriggerPayload), nameof(TimerTriggerPayload)); }); Module.Configure(management => management.AddActivitiesFrom()); diff --git a/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs b/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs index 1459795d7..79eb86831 100644 --- a/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs +++ b/src/modules/Elsa.Scheduling/ShellFeatures/SchedulingFeature.cs @@ -1,8 +1,8 @@ using CShells.Features; using Elsa.Common.Multitenancy; using Elsa.Common.ShellFeatures; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; +using Elsa.Workflows.Options; using Elsa.Scheduling.Bookmarks; using Elsa.Scheduling.Handlers; using Elsa.Scheduling.Services; @@ -11,6 +11,7 @@ using Elsa.Scheduling.TriggerPayloadValidators; using Elsa.Workflows.Management.Extensions; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Scheduling.ShellFeatures; @@ -51,7 +52,7 @@ public class SchedulingFeature : IShellFeature .AddTriggerPayloadValidator() .AddActivitiesFrom(); - services.Configure(options => + services.Configure(options => { options.AddTypeAlias(); options.AddTypeAlias(); diff --git a/src/modules/Elsa.Workflows.Api/AssemblyInfo.cs b/src/modules/Elsa.Workflows.Api/AssemblyInfo.cs index 2c63c1354..e6bd2a3d1 100644 --- a/src/modules/Elsa.Workflows.Api/AssemblyInfo.cs +++ b/src/modules/Elsa.Workflows.Api/AssemblyInfo.cs @@ -1,3 +1,4 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Elsa.Workflows.IntegrationTests")] \ No newline at end of file +[assembly: InternalsVisibleTo("Elsa.Workflows.IntegrationTests")] +[assembly: InternalsVisibleTo("Elsa.Workflows.Api.UnitTests")] diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/IncidentStrategies/List/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/IncidentStrategies/List/Endpoint.cs index cafa9453d..95c87902b 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/IncidentStrategies/List/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/IncidentStrategies/List/Endpoint.cs @@ -2,16 +2,17 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Reflection; using Elsa.Abstractions; -using Elsa.Extensions; using Elsa.Models; +using Elsa.Workflows; using Humanizer; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Api.Endpoints.IncidentStrategies.List; /// /// Returns list of available implementations. /// -internal class List(IEnumerable strategies) : ElsaEndpointWithoutRequest> +internal class List(IEnumerable strategies, ISerializationTypeRegistry workflowJsonTypeRegistry) : ElsaEndpointWithoutRequest> { public override void Configure() { @@ -21,15 +22,15 @@ internal class List(IEnumerable strategies) : ElsaEndpointWit public override Task> ExecuteAsync(CancellationToken cancellationToken) { - var descriptors = strategies.Select(IncidentStrategyDescriptor.FromStrategy).OrderBy(x => x.DisplayName).ToList(); - var response =new ListResponse(descriptors); + var descriptors = strategies.Select(x => IncidentStrategyDescriptor.FromStrategy(x, workflowJsonTypeRegistry)).OrderBy(x => x.DisplayName).ToList(); + var response = new ListResponse(descriptors); return Task.FromResult(response); } } internal record IncidentStrategyDescriptor(string DisplayName, string Description, string TypeName) { - public static IncidentStrategyDescriptor FromStrategy(IIncidentStrategy strategy) + public static IncidentStrategyDescriptor FromStrategy(IIncidentStrategy strategy, ISerializationTypeRegistry workflowJsonTypeRegistry) { var type = strategy.GetType(); var displayNameAttribute = type.GetCustomAttribute(); @@ -38,6 +39,7 @@ internal record IncidentStrategyDescriptor(string DisplayName, string Descriptio var displayName = displayNameAttribute?.DisplayName ?? displayAttribute?.Name ?? type.Name.Replace("Strategy", "").Humanize(); var description = descriptionAttribute?.Description ?? displayAttribute?.Description ?? ""; - return new IncidentStrategyDescriptor(displayName, description, type.GetSimpleAssemblyQualifiedName()); + var typeName = workflowJsonTypeRegistry.TryGetAlias(type, out var alias) ? alias : type.FullName!; + return new IncidentStrategyDescriptor(displayName, description, typeName); } -} \ No newline at end of file +} diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs index 71bfbb4a6..afa42aaf6 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs @@ -4,10 +4,9 @@ using Elsa.Extensions; using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Memory; using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; using JetBrains.Annotations; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Activities.Flowchart.Serialization; @@ -15,7 +14,7 @@ namespace Elsa.Workflows.Activities.Flowchart.Serialization; /// A JSON converter for . /// [UsedImplicitly] -public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IOptions workflowJsonOptions, ILoggerFactory loggerFactory) : JsonConverter +public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, ISerializationTypeRegistry workflowJsonTypeRegistry, ILoggerFactory loggerFactory) : JsonConverter { private const string AllActivitiesKey = "allActivities"; private const string AllConnectionsKey = "allConnections"; @@ -48,7 +47,7 @@ public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IOptio var variables = variablesElement.ValueKind != JsonValueKind.Undefined ? variablesElement.Deserialize>(options) ?? new List() : new List(); var polymorphicOptions = options.Clone(); - polymorphicOptions.Converters.Add(new PolymorphicDictionaryConverter(options, workflowJsonOptions.Value)); + polymorphicOptions.Converters.Add(new PolymorphicDictionaryConverter(options, workflowJsonTypeRegistry)); var metadataElement = doc.RootElement.TryGetProperty("metadata", out var metadataEl) ? metadataEl : default; var metadata = metadataElement.ValueKind != JsonValueKind.Undefined ? metadataElement.Deserialize>(polymorphicOptions) ?? new Dictionary() : new Dictionary(); @@ -106,7 +105,7 @@ public class FlowchartJsonConverter(IIdentityGenerator identityGenerator, IOptio var flowchartSerializerOptions = new JsonSerializerOptions(options); flowchartSerializerOptions.Converters.Add(new ConnectionJsonConverter(activityDictionary, loggerFactory)); - flowchartSerializerOptions.Converters.Add(new PolymorphicDictionaryConverter(options, workflowJsonOptions.Value)); + flowchartSerializerOptions.Converters.Add(new PolymorphicDictionaryConverter(options, workflowJsonTypeRegistry)); JsonSerializer.Serialize(writer, model, flowchartSerializerOptions); } diff --git a/src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs deleted file mode 100644 index 851cc8214..000000000 --- a/src/modules/Elsa.Workflows.Core/Extensions/WorkflowJsonOptionsExtensions.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Elsa.Common.Models; -using Elsa.Extensions; -using Elsa.Workflows; -using Elsa.Workflows.Activities.Flowchart.Models; -using Elsa.Workflows.Exceptions; -using Elsa.Workflows.IncidentStrategies; -using Elsa.Workflows.Memory; -using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Options; -using Elsa.Workflows.Services; -using Elsa.Workflows.State; -using Newtonsoft.Json.Linq; - -// ReSharper disable once CheckNamespace -namespace Elsa.Extensions; - -/// -/// Extends . -/// -public static class WorkflowJsonOptionsExtensions -{ - /// - /// Registers using its CLR type name. - /// - public static void AddTypeAlias(this WorkflowJsonOptions options) => options.RegisterTypeAlias(typeof(T), typeof(T).Name); - - /// - /// Registers using the specified alias. - /// - public static void AddTypeAlias(this WorkflowJsonOptions options, string alias) => options.RegisterTypeAlias(typeof(T), alias); - - /// - /// Registers the built-in workflow JSON aliases. - /// - public static void RegisterWorkflowTypeAliases(this WorkflowJsonOptions options) - { - options.RegisterTypeAlias(typeof(ExceptionState), nameof(ExceptionState)); - options.RegisterTypeAlias(typeof(FaultException), nameof(FaultException)); - options.RegisterTypeAlias(typeof(VariablesDictionary), nameof(VariablesDictionary)); - options.RegisterTypeAlias(typeof(Token), nameof(Token)); - options.RegisterTypeAlias(typeof(FlowJoinMode), "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core"); - options.RegisterTypeAlias(typeof(FlowJoinMode), typeof(FlowJoinMode).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(FlowJoinMode), nameof(FlowJoinMode)); - options.RegisterTypeAlias(typeof(WorkflowStorageDriver), typeof(WorkflowStorageDriver).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); - options.RegisterTypeAlias(typeof(WorkflowInstanceStorageDriver), typeof(WorkflowInstanceStorageDriver).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(WorkflowInstanceStorageDriver), nameof(WorkflowInstanceStorageDriver)); - options.RegisterTypeAlias(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(MemoryStorageDriver), nameof(MemoryStorageDriver)); - options.RegisterTypeAlias(typeof(FaultStrategy), typeof(FaultStrategy).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(FaultStrategy), nameof(FaultStrategy)); - options.RegisterTypeAlias(typeof(ContinueWithIncidentsStrategy), typeof(ContinueWithIncidentsStrategy).GetSimpleAssemblyQualifiedName()); - options.RegisterTypeAlias(typeof(ContinueWithIncidentsStrategy), nameof(ContinueWithIncidentsStrategy)); - options.RegisterTypeAlias(typeof(Exception), nameof(Exception)); - options.RegisterTypeAlias(typeof(ArgumentException), nameof(ArgumentException)); - options.RegisterTypeAlias(typeof(ArgumentNullException), nameof(ArgumentNullException)); - options.RegisterTypeAlias(typeof(InvalidOperationException), nameof(InvalidOperationException)); - options.RegisterTypeAlias(typeof(NullReferenceException), nameof(NullReferenceException)); - options.RegisterTypeAlias(typeof(OperationCanceledException), nameof(OperationCanceledException)); - options.RegisterTypeAlias(typeof(TaskCanceledException), nameof(TaskCanceledException)); - options.RegisterTypeAlias(typeof(TimeoutException), nameof(TimeoutException)); - options.RegisterTypeAlias(typeof(NotSupportedException), nameof(NotSupportedException)); - options.RegisterTypeAlias(typeof(JObject), nameof(JObject)); - options.RegisterTypeAlias(typeof(JArray), nameof(JArray)); - } -} diff --git a/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs b/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs index 5414125df..8fb59634d 100644 --- a/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs +++ b/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs @@ -4,8 +4,9 @@ using Elsa.Features.Services; using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Activities.Flowchart.Options; using Elsa.Workflows.Activities.Flowchart.Serialization; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Features; @@ -35,6 +36,6 @@ public class FlowchartFeature : FeatureBase if (FlowchartOptionsConfigurator != null) Services.Configure(FlowchartOptionsConfigurator); - Services.Configure(options => options.AddTypeAlias("FlowScope")); + Services.Configure(options => options.AddTypeAlias("FlowScope")); } } diff --git a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs index 005b87d09..89c17f04c 100644 --- a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs +++ b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs @@ -2,19 +2,21 @@ using Elsa.Common; using Elsa.Common.Features; using Elsa.Common.Serialization; using Elsa.Expressions.Features; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Workflows.ActivationValidators; +using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Builders; using Elsa.Workflows.CommitStates; +using Elsa.Workflows.Exceptions; using Elsa.Workflows.IncidentStrategies; using Elsa.Workflows.LogPersistence; using Elsa.Workflows.LogPersistence.Strategies; using Elsa.Workflows.Middleware.Activities; using Elsa.Workflows.Middleware.Workflows; +using Elsa.Workflows.Options; using Elsa.Workflows.Pipelines.ActivityExecution; using Elsa.Workflows.Pipelines.WorkflowExecution; using Elsa.Workflows.PortResolvers; @@ -22,12 +24,14 @@ using Elsa.Workflows.Serialization.Configurators; using Elsa.Workflows.Serialization.Helpers; using Elsa.Workflows.Serialization.Serializers; using Elsa.Workflows.Services; +using Elsa.Workflows.State; using Elsa.Workflows.UIHints.CheckList; using Elsa.Workflows.UIHints.Dictionary; using Elsa.Workflows.UIHints.Dropdown; using Elsa.Workflows.UIHints.JsonEditor; using Elsa.Workflows.UIHints.RadioList; using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; namespace Elsa.Workflows.Features; @@ -165,7 +169,31 @@ public class WorkflowsFeature : FeatureBase private void AddElsaCore(IServiceCollection services) { - services.Configure(options => options.RegisterWorkflowTypeAliases()); + services.Configure(options => + { + options.AddTypeAlias(nameof(ExceptionState)); + options.AddTypeAlias(nameof(FaultException)); + options.AddTypeAlias(nameof(VariablesDictionary)); + options.AddTypeAlias(nameof(Token)); + options.RegisterLegacyTypeName(typeof(FlowJoinMode), "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core"); + options.AddTypeAliasWithLegacyName(nameof(FlowJoinMode)); + options.AddTypeAliasWithLegacyName(nameof(WorkflowStorageDriver)); + options.AddTypeAliasWithLegacyName(nameof(WorkflowInstanceStorageDriver)); + options.AddTypeAliasWithLegacyName(nameof(MemoryStorageDriver)); + options.AddTypeAliasWithLegacyName(nameof(FaultStrategy)); + options.AddTypeAliasWithLegacyName(nameof(ContinueWithIncidentsStrategy)); + options.AddTypeAlias(nameof(Exception)); + options.AddTypeAlias(nameof(ArgumentException)); + options.AddTypeAlias(nameof(ArgumentNullException)); + options.AddTypeAlias(nameof(InvalidOperationException)); + options.AddTypeAlias(nameof(NullReferenceException)); + options.AddTypeAlias(nameof(OperationCanceledException)); + options.AddTypeAlias(nameof(TaskCanceledException)); + options.AddTypeAlias(nameof(TimeoutException)); + options.AddTypeAlias(nameof(NotSupportedException)); + options.AddTypeAlias(nameof(JObject)); + options.AddTypeAlias(nameof(JArray)); + }); services @@ -237,6 +265,7 @@ public class WorkflowsFeature : FeatureBase .AddStorageDriver() // Serialization. + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs index 888c732e9..af9f90393 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/OutputJsonConverter.cs @@ -1,10 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; @@ -13,12 +12,12 @@ namespace Elsa.Workflows.Serialization.Converters; /// public class OutputJsonConverter : JsonConverter?> { - private readonly WorkflowJsonOptions _workflowJsonOptions; + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; /// - public OutputJsonConverter(IOptions workflowJsonOptions) + public OutputJsonConverter(ISerializationTypeRegistry workflowJsonTypeRegistry) { - _workflowJsonOptions = workflowJsonOptions.Value; + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; } /// @@ -51,7 +50,9 @@ public class OutputJsonConverter : JsonConverter?> public override void Write(Utf8JsonWriter writer, Output? value, JsonSerializerOptions options) { var valueType = typeof(T); - var valueTypeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, valueType); + var valueTypeAlias = SerializationTypeResolver.TryGetAlias(_workflowJsonTypeRegistry, valueType, out var alias) + ? alias + : valueType.GetSimpleAssemblyQualifiedName(); var model = new { diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs index 12653413a..347392765 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs @@ -1,6 +1,6 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Workflows.Serialization.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; @@ -12,9 +12,9 @@ public class PolymorphicDictionaryConverter : JsonConverter _objectConverter; /// - public PolymorphicDictionaryConverter(JsonSerializerOptions options, WorkflowJsonOptions workflowJsonOptions) + public PolymorphicDictionaryConverter(JsonSerializerOptions options, ISerializationTypeRegistry workflowJsonTypeRegistry) { - var factory = (JsonConverterFactory)(options.Converters.FirstOrDefault(x => x is PolymorphicObjectConverterFactory) ?? new PolymorphicObjectConverterFactory(workflowJsonOptions)); + var factory = (JsonConverterFactory)(options.Converters.FirstOrDefault(x => x is PolymorphicObjectConverterFactory) ?? new PolymorphicObjectConverterFactory(workflowJsonTypeRegistry)); _objectConverter = (JsonConverter)factory.CreateConverter(typeof(object), options)!; } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverter.cs index 6fd7d30aa..dd412376c 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverter.cs @@ -5,11 +5,9 @@ using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using Elsa.Extensions; -using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.ReferenceHandlers; -using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; @@ -24,30 +22,22 @@ public class PolymorphicObjectConverter : JsonConverter private const string IdPropertyName = "$id"; private const string RefPropertyName = "$ref"; private const string ValuesPropertyName = "$values"; - private readonly WorkflowJsonOptions _workflowJsonOptions; + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; /// /// Initializes a new instance of the class. /// - public PolymorphicObjectConverter(IOptions workflowJsonOptions) - : this(workflowJsonOptions.Value) + public PolymorphicObjectConverter(ISerializationTypeRegistry workflowJsonTypeRegistry) { - } - - /// - /// Initializes a new instance of the class. - /// - public PolymorphicObjectConverter(WorkflowJsonOptions workflowJsonOptions) - { - _workflowJsonOptions = workflowJsonOptions; + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; } /// /// Initializes a new instance of the class. /// public PolymorphicObjectConverter() - : this(new WorkflowJsonOptions()) { + _workflowJsonTypeRegistry = SerializationTypeRegistry.CreateDefault(); } /// @@ -358,12 +348,14 @@ public class PolymorphicObjectConverter : JsonConverter } // If we found the _type property, attempt to resolve the type. - return typeName != null ? WorkflowJsonTypeResolver.ResolveType(_workflowJsonOptions, typeName, _workflowJsonOptions.AllowLegacyClrTypeNames) : default; + return typeName != null ? SerializationTypeResolver.ResolveType(_workflowJsonTypeRegistry, typeName) : default; } private void WriteTypeMetadata(Utf8JsonWriter writer, Type type) { - var typeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, type); + if (!SerializationTypeResolver.TryGetAlias(_workflowJsonTypeRegistry, type, out var typeAlias)) + return; + writer.WritePropertyName(TypePropertyName); writer.WriteStringValue(typeAlias); } @@ -376,7 +368,7 @@ public class PolymorphicObjectConverter : JsonConverter if (!targetType.IsInterface && !targetType.IsAbstract) return targetType; - if (WorkflowJsonTypeResolver.TryGetInstantiableCollectionType(targetType, out var instantiableCollectionType)) + if (SerializationTypeResolver.TryGetInstantiableCollectionType(targetType, out var instantiableCollectionType)) return instantiableCollectionType; throw new JsonException($"Workflow JSON type alias resolved to non-instantiable type '{targetType}'."); diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs index d1994e820..0b7b73b69 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicObjectConverterFactory.cs @@ -1,8 +1,7 @@ using System.Dynamic; using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Workflows.Serialization.Options; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; @@ -11,30 +10,22 @@ namespace Elsa.Workflows.Serialization.Converters; /// public class PolymorphicObjectConverterFactory : JsonConverterFactory { - private readonly WorkflowJsonOptions _workflowJsonOptions; + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; /// /// A JSON converter factory that creates instances. /// - public PolymorphicObjectConverterFactory(IOptions workflowJsonOptions) - : this(workflowJsonOptions.Value) + public PolymorphicObjectConverterFactory(ISerializationTypeRegistry workflowJsonTypeRegistry) { - } - - /// - /// A JSON converter factory that creates instances. - /// - public PolymorphicObjectConverterFactory(WorkflowJsonOptions workflowJsonOptions) - { - _workflowJsonOptions = workflowJsonOptions; + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; } /// /// Default constructor for use with attributes. /// public PolymorphicObjectConverterFactory() - : this(new WorkflowJsonOptions()) { + _workflowJsonTypeRegistry = SerializationTypeRegistry.CreateDefault(); } /// @@ -57,8 +48,8 @@ public class PolymorphicObjectConverterFactory : JsonConverterFactory public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { if (typeof(IDictionary).IsAssignableFrom(typeToConvert)) - return new PolymorphicDictionaryConverter(options, _workflowJsonOptions); + return new PolymorphicDictionaryConverter(options, _workflowJsonTypeRegistry); - return new PolymorphicObjectConverter(_workflowJsonOptions); + return new PolymorphicObjectConverter(_workflowJsonTypeRegistry); } } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs index 34165b414..cf2c03385 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs @@ -1,36 +1,34 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; +using Elsa.Extensions; using JetBrains.Annotations; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; /// /// Serializes objects to a simple alias representing the type. +/// Unregistered types are written as metadata-only aliases and intentionally deserialize to instead of loading the original CLR type. /// [UsedImplicitly] public class TypeJsonConverter : JsonConverter { - private readonly WorkflowJsonOptions _workflowJsonOptions; + /// + /// Prefix for unregistered type metadata that is not used for CLR type loading during deserialization. + /// + private const string UnregisteredTypeAliasPrefix = "UnregisteredClrType:"; + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; + + /// + public TypeJsonConverter(ISerializationTypeRegistry workflowJsonTypeRegistry) + { + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; + } /// public TypeJsonConverter() - : this(new WorkflowJsonOptions()) { - } - - /// - public TypeJsonConverter(IOptions workflowJsonOptions) - : this(workflowJsonOptions.Value) - { - } - - /// - public TypeJsonConverter(WorkflowJsonOptions workflowJsonOptions) - { - _workflowJsonOptions = workflowJsonOptions; + _workflowJsonTypeRegistry = SerializationTypeRegistry.CreateDefault(); } /// @@ -43,14 +41,18 @@ public class TypeJsonConverter : JsonConverter public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var typeAlias = reader.GetString(); + if (typeAlias?.StartsWith(UnregisteredTypeAliasPrefix, StringComparison.Ordinal) == true) + return typeof(Exception); - return WorkflowJsonTypeResolver.ResolveType(_workflowJsonOptions, typeAlias, _workflowJsonOptions.AllowLegacyClrTypeNames); + return SerializationTypeResolver.ResolveType(_workflowJsonTypeRegistry, typeAlias); } /// public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) { - var typeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, value); + if (!SerializationTypeResolver.TryGetAlias(_workflowJsonTypeRegistry, value, out var typeAlias)) + typeAlias = $"{UnregisteredTypeAliasPrefix}{value.GetSimpleAssemblyQualifiedName()}"; + writer.WriteStringValue(typeAlias); } } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs index b5f7bf522..18184d4da 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverter.cs @@ -2,9 +2,8 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; @@ -18,16 +17,9 @@ public class VariableConverter : JsonConverter /// // ReSharper disable once ContextualLoggerProblem - public VariableConverter(ILogger logger) + public VariableConverter(ISerializationTypeRegistry workflowJsonTypeRegistry, ILogger logger) { - _mapper = new VariableMapper(logger); - } - - /// - // ReSharper disable once ContextualLoggerProblem - public VariableConverter(ILogger logger, IOptions workflowJsonOptions) - { - _mapper = new VariableMapper(logger, workflowJsonOptions); + _mapper = new VariableMapper(workflowJsonTypeRegistry, logger); } /// diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs index 56971c510..f7aaab283 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/VariableConverterFactory.cs @@ -1,9 +1,8 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Workflows.Memory; -using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Converters; @@ -12,31 +11,20 @@ namespace Elsa.Workflows.Serialization.Converters; /// public class VariableConverterFactory : JsonConverterFactory { + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; private readonly ILoggerFactory _loggerFactory; - private readonly IOptions? _workflowJsonOptions; /// // ReSharper disable once ContextualLoggerProblem - public VariableConverterFactory(ILoggerFactory loggerFactory) + public VariableConverterFactory(ISerializationTypeRegistry workflowJsonTypeRegistry, ILoggerFactory loggerFactory) { + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; _loggerFactory = loggerFactory; } - /// - // ReSharper disable once ContextualLoggerProblem - public VariableConverterFactory(ILoggerFactory loggerFactory, IOptions workflowJsonOptions) - { - _loggerFactory = loggerFactory; - _workflowJsonOptions = workflowJsonOptions; - } - /// public override bool CanConvert(Type typeToConvert) => typeof(Variable).IsAssignableFrom(typeToConvert); /// - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var logger = _loggerFactory.CreateLogger(); - return _workflowJsonOptions != null ? new VariableConverter(logger, _workflowJsonOptions) : new VariableConverter(logger); - } + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => new VariableConverter(_workflowJsonTypeRegistry, _loggerFactory.CreateLogger()); } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs b/src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs deleted file mode 100644 index 204257a52..000000000 --- a/src/modules/Elsa.Workflows.Core/Serialization/Options/WorkflowJsonOptions.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Dynamic; -using System.Text.Json; -using System.Text.Json.Nodes; -using Elsa.Extensions; - -namespace Elsa.Workflows.Serialization.Options; - -/// -/// Options used by workflow JSON serializers to map stable type aliases to CLR types. -/// -public class WorkflowJsonOptions -{ - private readonly Dictionary _typesByAlias = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _aliasesByType = new(); - - /// - /// Initializes a new instance of the class. - /// - public WorkflowJsonOptions() - { - RegisterDefaultTypeAliases(); - } - - /// - /// Gets or sets a value indicating whether unrestricted CLR type names can be resolved for backwards compatibility. - /// - public bool AllowLegacyClrTypeNames { get; set; } = true; - - /// - /// Registers a type alias. - /// - public WorkflowJsonOptions RegisterTypeAlias(Type type, string alias) - { - _typesByAlias[alias] = type; - _aliasesByType[type] = alias; - - if (type.IsPrimitive || type.IsValueType && Nullable.GetUnderlyingType(type) == null) - { - var nullableType = typeof(Nullable<>).MakeGenericType(type); - var nullableAlias = alias + "?"; - _typesByAlias[nullableAlias] = nullableType; - _aliasesByType[nullableType] = nullableAlias; - } - - return this; - } - - /// - /// Attempts to resolve the specified alias to a type. - /// - public bool TryGetType(string alias, out Type type) => _typesByAlias.TryGetValue(alias, out type!); - - /// - /// Attempts to get the primary alias registered for the specified type. - /// - public bool TryGetAlias(Type type, out string alias) => _aliasesByType.TryGetValue(type, out alias!); - - /// - /// Lists all registered types. - /// - public IEnumerable ListTypes() => _typesByAlias.Values.Distinct(); - - private void RegisterDefaultTypeAliases() - { - this.AddTypeAlias("Int16"); - this.AddTypeAlias("Int32"); - this.AddTypeAlias("Int64"); - this.AddTypeAlias("Long"); - this.AddTypeAlias("Single"); - this.AddTypeAlias("Object"); - this.AddTypeAlias("String"); - this.AddTypeAlias("Boolean"); - this.AddTypeAlias("Decimal"); - this.AddTypeAlias("Double"); - this.AddTypeAlias("ByteArray"); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias("JSON"); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias(); - this.AddTypeAlias>("StringDictionary"); - this.AddTypeAlias>("ObjectDictionary"); - this.AddTypeAlias>("StringMap"); - this.AddTypeAlias>("ObjectMap"); - } -} diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs index 60899d5c2..a2a79b631 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/BookmarkPayloadSerializer.cs @@ -1,7 +1,6 @@ using System.Text.Json; using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Serialization.Serializers; @@ -13,15 +12,7 @@ public class BookmarkPayloadSerializer : IBookmarkPayloadSerializer /// /// Initializes a new instance of the class. /// - public BookmarkPayloadSerializer() - : this(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) - { - } - - /// - /// Initializes a new instance of the class. - /// - public BookmarkPayloadSerializer(IOptions workflowJsonOptions) + public BookmarkPayloadSerializer(ISerializationTypeRegistry workflowJsonTypeRegistry) { _settings = new JsonSerializerOptions { @@ -30,7 +21,7 @@ public class BookmarkPayloadSerializer : IBookmarkPayloadSerializer PropertyNameCaseInsensitive = true, }; - _settings.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); + _settings.Converters.Add(new TypeJsonConverter(workflowJsonTypeRegistry)); _settings.Converters.Add(new FuncExpressionValueConverter()); } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs index 989cf6265..93f8a807d 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonWorkflowStateSerializer.cs @@ -2,11 +2,9 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using Elsa.Common.Serialization; using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.ReferenceHandlers; using Elsa.Workflows.State; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Elsa.Workflows.Serialization.Serializers; @@ -14,26 +12,18 @@ namespace Elsa.Workflows.Serialization.Serializers; /// Serializes and deserializes workflow states from and to JSON. /// public class JsonWorkflowStateSerializer : ConfigurableSerializer, IWorkflowStateSerializer - { - private readonly ILoggerFactory _loggerFactory; - private readonly IOptions _workflowJsonOptions; +{ + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; + private readonly ILoggerFactory _loggerFactory; /// /// Initializes a new instance of the class. /// - public JsonWorkflowStateSerializer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) - : this(serviceProvider, loggerFactory, Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) - { - } - - /// - /// Initializes a new instance of the class. - /// - public JsonWorkflowStateSerializer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IOptions workflowJsonOptions) + public JsonWorkflowStateSerializer(IServiceProvider serviceProvider, ISerializationTypeRegistry workflowJsonTypeRegistry, ILoggerFactory loggerFactory) : base(serviceProvider) { + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; _loggerFactory = loggerFactory; - _workflowJsonOptions = workflowJsonOptions; } /// @@ -144,9 +134,9 @@ public class JsonWorkflowStateSerializer : ConfigurableSerializer, IWorkflowStat /// protected override void AddConverters(JsonSerializerOptions options) { - options.Converters.Add(new TypeJsonConverter(_workflowJsonOptions)); - options.Converters.Add(new PolymorphicObjectConverterFactory(_workflowJsonOptions)); - options.Converters.Add(new VariableConverterFactory(_loggerFactory, _workflowJsonOptions)); + options.Converters.Add(new TypeJsonConverter(_workflowJsonTypeRegistry)); + options.Converters.Add(new PolymorphicObjectConverterFactory(_workflowJsonTypeRegistry)); + options.Converters.Add(new VariableConverterFactory(_workflowJsonTypeRegistry, _loggerFactory)); options.Converters.Add(new FuncExpressionValueConverter()); } } diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs index 9a828338f..c2fadbd2a 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/SafeSerializer.cs @@ -71,9 +71,10 @@ public class SafeSerializer : ConfigurableSerializer, ISafeSerializer protected override void AddConverters(JsonSerializerOptions options) { var expressionDescriptorRegistry = ServiceProvider.GetRequiredService(); + var workflowJsonTypeRegistry = ServiceProvider.GetRequiredService(); options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); - options.Converters.Add(CreateInstance()); + options.Converters.Add(new TypeJsonConverter(workflowJsonTypeRegistry)); options.Converters.Add(new SafeValueConverterFactory()); options.Converters.Add(new ExpressionJsonConverterFactory(expressionDescriptorRegistry)); options.Converters.Add(new FuncExpressionValueConverter()); diff --git a/src/modules/Elsa.Workflows.Core/Services/Hasher.cs b/src/modules/Elsa.Workflows.Core/Services/Hasher.cs index b80b373a8..be018cd7d 100644 --- a/src/modules/Elsa.Workflows.Core/Services/Hasher.cs +++ b/src/modules/Elsa.Workflows.Core/Services/Hasher.cs @@ -3,8 +3,7 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows; @@ -13,12 +12,7 @@ public class Hasher : IHasher { private readonly JsonSerializerOptions _serializerOptions; - public Hasher() - : this(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) - { - } - - public Hasher(IOptions workflowJsonOptions) + public Hasher(ISerializationTypeRegistry workflowJsonTypeRegistry) { _serializerOptions = new JsonSerializerOptions { @@ -27,7 +21,7 @@ public class Hasher : IHasher DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; - _serializerOptions.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); + _serializerOptions.Converters.Add(new TypeJsonConverter(workflowJsonTypeRegistry)); _serializerOptions.Converters.Add(new ExcludeFromHashConverterFactory()); } diff --git a/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs b/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs index cb4fc0019..430c746f1 100644 --- a/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs +++ b/src/modules/Elsa.Workflows.Core/Services/VariableMapper.cs @@ -2,11 +2,10 @@ using Elsa.Expressions.Helpers; using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Services; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows; @@ -16,40 +15,21 @@ namespace Elsa.Workflows; public class VariableMapper { private readonly ILogger _logger; - private readonly WorkflowJsonOptions _workflowJsonOptions; + private readonly ISerializationTypeRegistry _workflowJsonTypeRegistry; /// /// Initializes a new instance of the class. /// + /// The serialization type registry. /// The logger. - public VariableMapper(ILogger logger) - : this(logger, Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions())) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The workflow JSON options. - public VariableMapper(ILogger logger, IOptions workflowJsonOptions) - : this(logger, workflowJsonOptions.Value) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The workflow JSON options. - public VariableMapper(ILogger logger, WorkflowJsonOptions workflowJsonOptions) + public VariableMapper(ISerializationTypeRegistry workflowJsonTypeRegistry, ILogger logger) { + _workflowJsonTypeRegistry = workflowJsonTypeRegistry; _logger = logger; - _workflowJsonOptions = workflowJsonOptions; } /// - public VariableMapper() : this(NullLogger.Instance) + public VariableMapper() : this(SerializationTypeRegistry.CreateDefault(), NullLogger.Instance) { } @@ -60,6 +40,7 @@ public class VariableMapper public Variable Map(VariableModel source) { var type = ResolveVariableType(source.TypeName); + var variableGenericType = typeof(Variable<>).MakeGenericType(type); var variable = (Variable)Activator.CreateInstance(variableGenericType)!; @@ -84,19 +65,27 @@ public class VariableMapper var variableType = source.GetType(); var value = source.Value; var valueType = variableType.IsConstructedGenericType ? variableType.GetGenericArguments().FirstOrDefault() ?? typeof(object) : typeof(object); - var valueTypeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, valueType); - var storageDriverTypeName = source.StorageDriverType != null ? WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, source.StorageDriverType) : null; + var valueTypeAlias = SerializationTypeResolver.TryGetAlias(_workflowJsonTypeRegistry, valueType, out var alias) ? alias : valueType.GetSimpleAssemblyQualifiedName(); + var storageDriverTypeName = GetTypeName(source.StorageDriverType); var serializedValue = value.Format(); return new(source.Id, source.Name, valueTypeAlias, serializedValue, storageDriverTypeName); } + private string? GetTypeName(Type? type) + { + if (type == null) + return null; + + return SerializationTypeResolver.TryGetAlias(_workflowJsonTypeRegistry, type, out var alias) ? alias : type.GetSimpleAssemblyQualifiedName(); + } + private Type ResolveVariableType(string? typeAlias) { if (string.IsNullOrWhiteSpace(typeAlias)) return typeof(object); - if (WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, typeAlias, _workflowJsonOptions.AllowLegacyClrTypeNames, out var type)) + if (SerializationTypeResolver.TryResolveType(_workflowJsonTypeRegistry, typeAlias, out var type)) return type; _logger.LogWarning("Failed to resolve variable type alias {VariableTypeName}", typeAlias); @@ -108,7 +97,7 @@ public class VariableMapper if (string.IsNullOrWhiteSpace(typeAlias)) return null; - if (WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, typeAlias, _workflowJsonOptions.AllowLegacyClrTypeNames, out var type) && IsStorageDriverType(type)) + if (SerializationTypeResolver.TryResolveType(_workflowJsonTypeRegistry, typeAlias, out var type) && IsStorageDriverType(type)) return type; _logger.LogWarning("Failed to resolve storage driver type alias {StorageDriverTypeName}", typeAlias); diff --git a/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs b/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs index 9efb4ce38..6307b5ae8 100644 --- a/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs +++ b/src/modules/Elsa.Workflows.Core/ShellFeatures/FlowchartFeature.cs @@ -3,9 +3,10 @@ using Elsa.Extensions; using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Activities.Flowchart.Options; using Elsa.Workflows.Activities.Flowchart.Serialization; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Workflows.ShellFeatures; @@ -33,6 +34,6 @@ public class FlowchartFeature : IShellFeature if (FlowchartOptionsConfigurator != null) services.Configure(FlowchartOptionsConfigurator); - services.Configure(options => options.AddTypeAlias("FlowScope")); + services.Configure(options => options.AddTypeAlias("FlowScope")); } } diff --git a/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs index 04e3b6bc8..a9c6a065e 100644 --- a/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs +++ b/src/modules/Elsa.Workflows.Core/ShellFeatures/WorkflowsFeature.cs @@ -5,29 +5,33 @@ using Elsa.Common.ShellFeatures; using Elsa.Expressions.ShellFeatures; using Elsa.Extensions; using Elsa.Workflows.ActivationValidators; +using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Activities.Flowchart.Options; using Elsa.Workflows.Activities.Flowchart.Serialization; using Elsa.Workflows.Builders; using Elsa.Workflows.CommitStates; +using Elsa.Workflows.Exceptions; using Elsa.Workflows.IncidentStrategies; using Elsa.Workflows.LogPersistence; using Elsa.Workflows.LogPersistence.Strategies; using Elsa.Workflows.Middleware.Activities; using Elsa.Workflows.Middleware.Workflows; +using Elsa.Workflows.Options; using Elsa.Workflows.Pipelines.ActivityExecution; using Elsa.Workflows.Pipelines.WorkflowExecution; using Elsa.Workflows.PortResolvers; using Elsa.Workflows.Serialization.Configurators; using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.Serializers; using Elsa.Workflows.Services; +using Elsa.Workflows.State; using Elsa.Workflows.UIHints.CheckList; using Elsa.Workflows.UIHints.Dictionary; using Elsa.Workflows.UIHints.Dropdown; using Elsa.Workflows.UIHints.JsonEditor; using Elsa.Workflows.UIHints.RadioList; using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; namespace Elsa.Workflows.ShellFeatures; @@ -84,7 +88,31 @@ public class WorkflowsFeature : IShellFeature public void ConfigureServices(IServiceCollection services) { - services.Configure(options => options.RegisterWorkflowTypeAliases()); + services.Configure(options => + { + options.AddTypeAlias(nameof(ExceptionState)); + options.AddTypeAlias(nameof(FaultException)); + options.AddTypeAlias(nameof(VariablesDictionary)); + options.AddTypeAlias(nameof(Token)); + options.RegisterLegacyTypeName(typeof(FlowJoinMode), "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core"); + options.AddTypeAliasWithLegacyName(nameof(FlowJoinMode)); + options.AddTypeAliasWithLegacyName(nameof(WorkflowStorageDriver)); + options.AddTypeAliasWithLegacyName(nameof(WorkflowInstanceStorageDriver)); + options.AddTypeAliasWithLegacyName(nameof(MemoryStorageDriver)); + options.AddTypeAliasWithLegacyName(nameof(FaultStrategy)); + options.AddTypeAliasWithLegacyName(nameof(ContinueWithIncidentsStrategy)); + options.AddTypeAlias(nameof(Exception)); + options.AddTypeAlias(nameof(ArgumentException)); + options.AddTypeAlias(nameof(ArgumentNullException)); + options.AddTypeAlias(nameof(InvalidOperationException)); + options.AddTypeAlias(nameof(NullReferenceException)); + options.AddTypeAlias(nameof(OperationCanceledException)); + options.AddTypeAlias(nameof(TaskCanceledException)); + options.AddTypeAlias(nameof(TimeoutException)); + options.AddTypeAlias(nameof(NotSupportedException)); + options.AddTypeAlias(nameof(JObject)); + options.AddTypeAlias(nameof(JArray)); + }); services // Core. @@ -155,6 +183,7 @@ public class WorkflowsFeature : IShellFeature .AddStorageDriver() // Serialization. + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() @@ -192,7 +221,7 @@ public class WorkflowsFeature : IShellFeature // Logging .AddLogging(); - + // Overridable services services.AddScoped(); } diff --git a/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs index 8dbdc87e3..6b83d8e39 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/ManagementServiceCollectionExtensions.cs @@ -1,9 +1,10 @@ using System.Reflection; -using Elsa.Extensions; +using Elsa.Expressions.Extensions; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Options; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; // ReSharper disable once CheckNamespace namespace Elsa.Workflows.Management.Extensions; @@ -99,8 +100,9 @@ public static class ManagementServiceCollectionExtensions /// public static IServiceCollection AddVariableTypeAndAlias(this IServiceCollection services, string alias, string category) { + services.Configure(options => options.RegisterTypeAlias(typeof(T), alias)); return services .AddVariableDescriptor(category) - .Configure(options => options.AddTypeAlias(alias)); + .AddTypeAlias(alias); } } diff --git a/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs index be1d8ecba..36cc410ae 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/ModuleExtensions.cs @@ -2,8 +2,9 @@ using Elsa.Features.Services; using Elsa.Workflows; using Elsa.Workflows.Activities; using Elsa.Workflows.Management.Features; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; // ReSharper disable once CheckNamespace namespace Elsa.Extensions; @@ -74,9 +75,11 @@ public static class ModuleExtensions /// public static IModule AddVariableTypeAndAlias(this IModule module, string alias, string category) { - module.UseWorkflowManagement(management => management.AddVariableType(category)); - module.Services.Configure(options => options.AddTypeAlias(alias)); - return module; + module.Services.Configure(options => options.RegisterTypeAlias(typeof(T), alias)); + + return module + .UseWorkflowManagement(management => management.AddVariableType(category)) + .AddTypeAlias(alias); } /// diff --git a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs index 57801be2d..58ab08a73 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowManagementFeatureExtensions.cs @@ -1,8 +1,9 @@ using Elsa.Extensions; using Elsa.Workflows.Management.Features; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Management; @@ -17,7 +18,8 @@ public static class WorkflowManagementFeatureExtensions public static WorkflowManagementFeature AddVariableTypeAndAlias(this WorkflowManagementFeature management, string alias, string category) { management.AddVariableType(category); - management.Module.Services.Configure(options => options.AddTypeAlias(alias)); + management.Module.AddTypeAlias(alias); + management.Module.Services.Configure(options => options.RegisterTypeAlias(typeof(T), alias)); return management; } } diff --git a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs index d6769d71f..0a26da083 100644 --- a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs +++ b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs @@ -8,7 +8,7 @@ using Elsa.Caching.Features; using Elsa.Common.Codecs; using Elsa.Common.Features; using Elsa.Expressions.Contracts; -using Elsa.Workflows.Serialization.Options; +using Elsa.Expressions.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -27,10 +27,12 @@ using Elsa.Workflows.Management.Options; using Elsa.Workflows.Management.Providers; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Management.Stores; +using Elsa.Workflows.Options; using Elsa.Workflows.Serialization.Serializers; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Management.Features; @@ -313,8 +315,9 @@ public class WorkflowManagementFeature(IModule module) : FeatureBase(module) options.IsReadOnlyMode = IsReadOnlyMode; }); + Services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); + Services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); Services.Configure(_ => { }); Services.Configure(_ => { }); - Services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); } } diff --git a/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs b/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs index 0f6644630..80568cc9b 100644 --- a/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs +++ b/src/modules/Elsa.Workflows.Management/Mappers/VariableDefinitionMapper.cs @@ -2,27 +2,24 @@ using Elsa.Expressions.Helpers; using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Management.Mappers; /// /// Maps s to s and vice versa. /// -public class VariableDefinitionMapper(IOptions workflowJsonOptions, IServiceScopeFactory scopeFactory, ILogger logger) +public class VariableDefinitionMapper(ISerializationTypeRegistry workflowJsonTypeRegistry, IServiceScopeFactory scopeFactory, ILogger logger) { - private readonly WorkflowJsonOptions _workflowJsonOptions = workflowJsonOptions.Value; - /// /// Maps a to a . /// public Variable? Map(VariableDefinition source) { - var type = WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, source.TypeName, _workflowJsonOptions.AllowLegacyClrTypeNames, out var resolvedType) ? resolvedType : null; + var type = SerializationTypeResolver.TryResolveType(workflowJsonTypeRegistry, source.TypeName, out var resolvedType) ? resolvedType : null; if (type == null) { @@ -72,10 +69,14 @@ public class VariableDefinitionMapper(IOptions workflowJson { var variableType = source.GetType(); var valueType = variableType.IsConstructedGenericType ? variableType.GetGenericArguments().FirstOrDefault() ?? typeof(object) : typeof(object); - var valueTypeAlias = WorkflowJsonTypeResolver.TryGetAlias(_workflowJsonOptions, valueType, out var alias) ? alias : null; + var valueTypeAlias = SerializationTypeResolver.TryGetAlias(workflowJsonTypeRegistry, valueType, out var alias) ? alias : null; var value = source.Value; var serializedValue = value.Format(); - var storageDriverTypeName = source.StorageDriverType != null ? WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, source.StorageDriverType) : null; + var storageDriverTypeName = source.StorageDriverType != null + ? SerializationTypeResolver.TryGetAlias(workflowJsonTypeRegistry, source.StorageDriverType, out var storageDriverAlias) + ? storageDriverAlias + : source.StorageDriverType.GetSimpleAssemblyQualifiedName() + : null; // Handles the case where an alias exists for an array or collection type. E.g. byte[] -> ByteArray. if (valueTypeAlias != null && (valueType.IsArray || valueType.IsCollectionType())) @@ -84,7 +85,9 @@ public class VariableDefinitionMapper(IOptions workflowJson var isArray = valueType.IsArray; var isCollection = valueType.IsCollectionType(); var elementValueType = isArray ? valueType.GetElementType()! : isCollection ? valueType.GenericTypeArguments[0] : valueType; - var elementTypeAlias = WorkflowJsonTypeResolver.GetAliasOrLegacyClrTypeName(_workflowJsonOptions, elementValueType); + var elementTypeAlias = SerializationTypeResolver.TryGetAlias(workflowJsonTypeRegistry, elementValueType, out var elementAlias) + ? elementAlias + : elementValueType.GetSimpleAssemblyQualifiedName(); return new(source.Id, source.Name, elementTypeAlias, isArray, serializedValue, storageDriverTypeName); } @@ -99,7 +102,7 @@ public class VariableDefinitionMapper(IOptions workflowJson if (string.IsNullOrEmpty(storageDriverTypeName)) return null; - if (WorkflowJsonTypeResolver.TryResolveType(_workflowJsonOptions, storageDriverTypeName, _workflowJsonOptions.AllowLegacyClrTypeNames, out var type) && typeof(IStorageDriver).IsAssignableFrom(type)) + if (SerializationTypeResolver.TryResolveType(workflowJsonTypeRegistry, storageDriverTypeName, out var type) && typeof(IStorageDriver).IsAssignableFrom(type)) return type; // TODO: The following code handles backward compatibility with variable definitions referencing older .NET type namespaces. diff --git a/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs b/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs index 2622f6be7..b16f21d03 100644 --- a/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs +++ b/src/modules/Elsa.Workflows.Management/ShellFeatures/WorkflowManagementFeature.cs @@ -5,9 +5,9 @@ using CShells.Features; using Elsa.Caching.Features; using Elsa.Common.Features; using Elsa.Expressions.Contracts; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Attributes; +using Elsa.Workflows.Options; using Elsa.Workflows.Features; using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; using Elsa.Workflows.Management.Contracts; @@ -25,6 +25,7 @@ using Elsa.Workflows.Management.Stores; using Elsa.Workflows.Serialization.Serializers; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Management.ShellFeatures; @@ -133,6 +134,6 @@ public class WorkflowManagementFeature : IShellFeature // Register the default variable descriptors declared on this feature. services.AddVariableDescriptors(VariableDescriptors); - services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); + services.Configure(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext), nameof(ClrWorkflowMaterializerContext))); } } diff --git a/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs b/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs index 17a05faf8..dea87c00c 100644 --- a/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs +++ b/src/modules/Elsa.Workflows.Runtime/Comparers/WorkflowTriggerEqualityComparer.cs @@ -3,8 +3,8 @@ using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; -using Microsoft.Extensions.Options; +using Elsa.Workflows.Services; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Runtime.Comparers; @@ -18,23 +18,14 @@ public class WorkflowTriggerEqualityComparer : IEqualityComparer /// /// Initializes a new instance of the class. /// - public WorkflowTriggerEqualityComparer() - : this(new WorkflowJsonOptions()) + public WorkflowTriggerEqualityComparer() : this(SerializationTypeRegistry.CreateDefault()) { } /// /// Initializes a new instance of the class. /// - public WorkflowTriggerEqualityComparer(IOptions workflowJsonOptions) - : this(workflowJsonOptions.Value) - { - } - - /// - /// Initializes a new instance of the class. - /// - public WorkflowTriggerEqualityComparer(WorkflowJsonOptions workflowJsonOptions) + public WorkflowTriggerEqualityComparer(ISerializationTypeRegistry workflowJsonTypeRegistry) { _settings = new() { @@ -53,8 +44,8 @@ public class WorkflowTriggerEqualityComparer : IEqualityComparer // polymorphic object properties serialize identically to their stored representation. _settings.Converters.Add(new JsonStringEnumConverter()); _settings.Converters.Add(JsonMetadataServices.TimeSpanConverter); - _settings.Converters.Add(new PolymorphicObjectConverterFactory(workflowJsonOptions)); - _settings.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); + _settings.Converters.Add(new PolymorphicObjectConverterFactory(workflowJsonTypeRegistry)); + _settings.Converters.Add(new TypeJsonConverter(workflowJsonTypeRegistry)); } /// diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs index 614c0d4c6..b99773b31 100644 --- a/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/DependencyInjectionExtensions.cs @@ -1,8 +1,8 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Workflows; +using Elsa.Workflows.Options; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Discovery; @@ -10,6 +10,7 @@ using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Providers; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; // ReSharper disable once CheckNamespace namespace Microsoft.Extensions.DependencyInjection; @@ -93,6 +94,6 @@ public static class DependencyInjectionExtensions private static void AddWorkflowRegistration(IServiceCollection services, Type workflowType) { services.PostConfigure(options => options.Workflows.Add(workflowType)); - services.Configure(options => options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName())); + services.Configure(options => options.AddSimpleAssemblyQualifiedTypeAlias(workflowType)); } } diff --git a/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs b/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs index 8393bf829..9d50fe713 100644 --- a/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs +++ b/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs @@ -4,7 +4,6 @@ using Elsa.Common; using Elsa.Common.DistributedHosting; using Elsa.Common.Features; using Elsa.Common.RecurringTasks; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; @@ -14,13 +13,16 @@ using Elsa.Workflows.Features; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Services; +using Elsa.Workflows.Options; using Elsa.Workflows.Runtime.ActivationValidators; -using Elsa.Workflows.Runtime.Comparers; +using Elsa.Workflows.Runtime.Bookmarks; using Elsa.Workflows.Runtime.Discovery; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Handlers; +using Elsa.Workflows.Runtime.Models; using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Providers; +using Elsa.Workflows.Runtime.Stimuli; using Elsa.Workflows.Runtime.Stores; using Elsa.Workflows.Runtime.Tasks; using Elsa.Workflows.Runtime.UIHints; @@ -29,6 +31,7 @@ using Medallion.Threading.FileSystem; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Runtime.Features; @@ -45,6 +48,7 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) /// A list of workflow builders configured during application startup. /// public IDictionary>> Workflows { get; set; } = new Dictionary>>(); + private ISet WorkflowTypes { get; } = new HashSet(); /// /// A factory that instantiates a concrete . @@ -200,7 +204,7 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) public WorkflowRuntimeFeature AddWorkflow(Type workflowType) { Workflows.Add(workflowType); - Services.Configure(options => options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName())); + WorkflowTypes.Add(workflowType); return this; } @@ -267,6 +271,7 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) Services.Configure(WorkflowInboxCleanupOptions); Services.Configure(WorkflowDispatcherOptions); Services.Configure(BookmarkQueuePurgeOptions); + Services.Configure(RegisterWorkflowTypeAliases); Services.Configure(options => { options.Workflows = Workflows; }); Services.Configure(options => { @@ -305,7 +310,6 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) Services // Core. - .AddSingleton() .AddScoped() .AddScoped() .AddScoped() @@ -439,4 +443,34 @@ public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module) Services.TryAddScoped(WorkflowDispatchOutboxStore); Services.TryAddScoped(); } + + private void RegisterWorkflowTypeAliases(SerializationTypeOptions options) + { + WorkflowRuntimeTypeAliasRegistrar.Register(options, GetRegisteredWorkflowTypes()); + } + + private IEnumerable GetRegisteredWorkflowTypes() + { + return WorkflowTypes + .Concat(Workflows.Keys.Select(TryResolveWorkflowType).Where(type => type != null).Select(type => type!)) + .Distinct(); + } + + private static Type? TryResolveWorkflowType(string typeName) + { + Type? type; + + try + { + type = Type.GetType(typeName, false); + } + catch (Exception e) when (e is ArgumentException or FileLoadException or FileNotFoundException or TypeLoadException or BadImageFormatException) + { + return null; + } + + return type != null && typeof(IWorkflow).IsAssignableFrom(type) && type is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false } + ? type + : null; + } } diff --git a/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs b/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs index b04d0f130..fa8c68c7a 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/TriggerIndexer.cs @@ -15,6 +15,7 @@ using Medallion.Threading; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Open.Linq.AsyncExtensions; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Runtime; @@ -31,9 +32,9 @@ public class TriggerIndexer : ITriggerIndexer private readonly IServiceProvider _serviceProvider; private readonly IStimulusHasher _hasher; private readonly IDistributedLockProvider _distributedLockProvider; + private readonly WorkflowTriggerEqualityComparer _triggerEqualityComparer; private readonly DistributedLockingOptions _lockingOptions; private readonly ILogger _logger; - private readonly WorkflowTriggerEqualityComparer _triggerEqualityComparer; /// /// Constructor. @@ -49,8 +50,8 @@ public class TriggerIndexer : ITriggerIndexer IServiceProvider serviceProvider, IStimulusHasher hasher, IDistributedLockProvider distributedLockProvider, + ISerializationTypeRegistry workflowJsonTypeRegistry, IOptions lockingOptions, - WorkflowTriggerEqualityComparer triggerEqualityComparer, ILogger logger) { _activityVisitor = activityVisitor; @@ -62,8 +63,8 @@ public class TriggerIndexer : ITriggerIndexer _serviceProvider = serviceProvider; _hasher = hasher; _distributedLockProvider = distributedLockProvider; + _triggerEqualityComparer = new WorkflowTriggerEqualityComparer(workflowJsonTypeRegistry); _lockingOptions = lockingOptions.Value; - _triggerEqualityComparer = triggerEqualityComparer; _logger = logger; _workflowDefinitionService = workflowDefinitionService; } diff --git a/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs b/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs index d680b6529..1ec183a7e 100644 --- a/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs +++ b/src/modules/Elsa.Workflows.Runtime/ShellFeatures/WorkflowRuntimeFeature.cs @@ -3,15 +3,14 @@ using System.Reflection; using CShells.Features; using Elsa.Common; using Elsa.Common.RecurringTasks; -using Elsa.Workflows.Serialization.Options; using Elsa.Extensions; using Elsa.Mediator.Contracts; using Elsa.Workflows.CommitStates; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Services; +using Elsa.Workflows.Options; using Elsa.Workflows.Runtime.ActivationValidators; -using Elsa.Workflows.Runtime.Comparers; using Elsa.Workflows.Runtime.Discovery; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Handlers; @@ -26,6 +25,7 @@ using Medallion.Threading.FileSystem; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Runtime.ShellFeatures; @@ -185,7 +185,7 @@ public class WorkflowRuntimeFeature : IShellFeature public void ConfigureServices(IServiceCollection services) { // Options. - services.Configure(RegisterWorkflowTypeAliases); + services.Configure(RegisterWorkflowTypeAliases); services.Configure(options => { options.Workflows = Workflows; }); services.Configure(options => { @@ -227,7 +227,6 @@ public class WorkflowRuntimeFeature : IShellFeature .AddTransient() // Core. - .AddSingleton() .AddScoped() .AddScoped() .AddScoped() @@ -237,7 +236,6 @@ public class WorkflowRuntimeFeature : IShellFeature .AddScoped(StimulusDispatcher) .AddScoped(WorkflowCancellationDispatcher) .AddScoped(RunTaskDispatcher) - .AddScoped(DispatchWorkflowCommandHandler) .AddScoped(ActivityExecutionLogSink) .AddScoped(WorkflowExecutionLogSink) .AddSingleton(BackgroundActivityScheduler) @@ -364,9 +362,33 @@ public class WorkflowRuntimeFeature : IShellFeature services.TryAddScoped(); } - private void RegisterWorkflowTypeAliases(WorkflowJsonOptions options) + private void RegisterWorkflowTypeAliases(SerializationTypeOptions options) { - foreach (var workflowType in WorkflowTypes) - options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName()); + WorkflowRuntimeTypeAliasRegistrar.Register(options, GetRegisteredWorkflowTypes()); + } + + private IEnumerable GetRegisteredWorkflowTypes() + { + return WorkflowTypes + .Concat(Workflows.Keys.Select(TryResolveWorkflowType).Where(type => type != null).Select(type => type!)) + .Distinct(); + } + + private static Type? TryResolveWorkflowType(string typeName) + { + Type? type; + + try + { + type = Type.GetType(typeName, false); + } + catch (Exception e) when (e is ArgumentException or FileLoadException or FileNotFoundException or TypeLoadException or BadImageFormatException) + { + return null; + } + + return type != null && typeof(IWorkflow).IsAssignableFrom(type) && type is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false } + ? type + : null; } } diff --git a/src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs b/src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs new file mode 100644 index 000000000..31a52542d --- /dev/null +++ b/src/modules/Elsa.Workflows.Runtime/WorkflowRuntimeTypeAliasRegistrar.cs @@ -0,0 +1,36 @@ +using Elsa.Extensions; +using Elsa.Workflows; +using Elsa.Workflows.Options; +using Elsa.Workflows.Runtime.Bookmarks; +using Elsa.Workflows.Runtime.Stimuli; +using Elsa.Common.Serialization; + +namespace Elsa.Workflows.Runtime; + +internal static class WorkflowRuntimeTypeAliasRegistrar +{ + public static void Register(SerializationTypeOptions options, IEnumerable workflowTypes) + { + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + options.AddTypeAlias(); + + foreach (var workflowType in workflowTypes.Where(IsConcreteWorkflowType).Distinct()) + options.RegisterTypeAlias(workflowType, workflowType.GetSimpleAssemblyQualifiedName()); + } + + private static bool IsConcreteWorkflowType(Type type) + { + return typeof(IWorkflow).IsAssignableFrom(type) && type is { IsAbstract: false, IsInterface: false, ContainsGenericParameters: false }; + } +} diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs index e8e6343a9..1953f511e 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/JsonSerialization/Tests.cs @@ -1,5 +1,7 @@ using System.Text.Json; using System.Text.Json.Nodes; +using Elsa.Common.Serialization; +using Elsa.Extensions; using Elsa.Testing.Shared; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; @@ -9,7 +11,9 @@ namespace Elsa.Workflows.IntegrationTests.Serialization.JsonSerialization; public class SerializationTests(ITestOutputHelper testOutputHelper) { - private readonly IServiceProvider _services = new TestApplicationBuilder(testOutputHelper).Build(); + private readonly IServiceProvider _services = new TestApplicationBuilder(testOutputHelper) + .ConfigureServices(services => services.Configure(options => options.AddTypeAlias())) + .Build(); [Theory(DisplayName = "write")] [InlineData(typeof(JsonObject), "JsonObjectIsland")] @@ -182,4 +186,4 @@ public class SerializationTests(ITestOutputHelper testOutputHelper) public class TestObject { public string? Data { get; set; } -} \ No newline at end of file +} diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs index fe1f0cd8d..a99897a4d 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/Tests.cs @@ -2,9 +2,11 @@ using System.Dynamic; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; +using Elsa.Workflows.Options; using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; using Elsa.Workflows.Serialization.ReferenceHandlers; +using Elsa.Workflows.Services; +using Elsa.Common.Serialization; namespace Elsa.Workflows.IntegrationTests.Serialization.Polymorphism; @@ -14,7 +16,7 @@ public class Tests public void Test1() { var model = CreateModel(); - var expectedJson = File.ReadAllText("Serialization/Polymorphism/data.json").Trim(); + var expectedJson = File.ReadAllText("Serialization/Polymorphism/data.json").TrimEnd(); var actualJson = JsonSerializer.Serialize(model, GetSerializerOptions()); Assert.Equal(expectedJson, actualJson); } @@ -74,6 +76,10 @@ public class Tests private JsonSerializerOptions GetSerializerOptions() { var referenceHandler = new CrossScopedReferenceHandler(); + var workflowJsonTypeRegistry = new SerializationTypeRegistry(Microsoft.Extensions.Options.Options.Create(new SerializationTypeOptions())); + workflowJsonTypeRegistry.RegisterType(typeof(Model), nameof(Model)); + workflowJsonTypeRegistry.RegisterType(typeof(CustomDictionary), nameof(CustomDictionary)); + var options = new JsonSerializerOptions { ReferenceHandler = referenceHandler, @@ -84,7 +90,7 @@ public class Tests options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(JsonMetadataServices.TimeSpanConverter); - options.Converters.Add(new PolymorphicObjectConverterFactory(new WorkflowJsonOptions())); + options.Converters.Add(new PolymorphicObjectConverterFactory(workflowJsonTypeRegistry)); return options; } diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json index 623a5cacc..35109c75a 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/Polymorphism/data.json @@ -1 +1 @@ -{"$id":"1","text":"Hello World","number":123,"flag":true,"items":{"$id":"2","$values":[{"$id":"3","text":"Hello","number":1,"flag":true,"items":{"$id":"4","$values":[{"$id":"5","number":0,"flag":false,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$id":"6","$values":[{"$id":"7","text":"Hello","number":1,"flag":true,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$id":"8","content-type":["application/json"],"_type":"Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.CustomDictionary, Elsa.Workflows.IntegrationTests"}}},{"$id":"9","text":"World","number":2,"flag":false}],"_type":"System.Collections.Generic.List\u00601[[Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.Model, Elsa.Workflows.IntegrationTests]], System.Private.CoreLib"},"CustomDictionary":{"$ref":"8"}}}]}},{"$id":"10","text":"World","number":2,"flag":false}]},"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$ref":"8"}},"payload":{"$id":"11","text":"Payload","number":0,"flag":false,"_type":"Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.Model, Elsa.Workflows.IntegrationTests"},"hashSet":{"$id":"12","$values":[{"$id":"13","text":"I\u0027m a model in a set!","number":0,"flag":false}],"_type":"System.Collections.Generic.HashSet\u00601[[Elsa.Workflows.IntegrationTests.Serialization.Polymorphism.Model, Elsa.Workflows.IntegrationTests]], System.Private.CoreLib"},"properties":{"$id":"14","Hello":{"$id":"15","text":"Hello","number":1,"flag":true},"World":{"$id":"16","text":"World","number":2,"flag":false}}} \ No newline at end of file +{"$id":"1","text":"Hello World","number":123,"flag":true,"items":{"$id":"2","$values":[{"$id":"3","text":"Hello","number":1,"flag":true,"items":{"$id":"4","$values":[{"$id":"5","number":0,"flag":false,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$id":"6","$values":[{"$id":"7","text":"Hello","number":1,"flag":true,"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$id":"8","content-type":["application/json"],"_type":"CustomDictionary"}}},{"$id":"9","text":"World","number":2,"flag":false}],"_type":"List\u003CModel\u003E"},"CustomDictionary":{"$ref":"8"}}}]}},{"$id":"10","text":"World","number":2,"flag":false}]},"metadata":{"Foo":"Bar","Number":123,"Flag":true,"Models":{"$ref":"6"},"CustomDictionary":{"$ref":"8"}},"payload":{"$id":"11","text":"Payload","number":0,"flag":false,"_type":"Model"},"hashSet":{"$id":"12","$values":[{"$id":"13","text":"I\u0027m a model in a set!","number":0,"flag":false}],"_type":"HashSet\u003CModel\u003E"},"properties":{"$id":"14","Hello":{"$id":"15","text":"Hello","number":1,"flag":true},"World":{"$id":"16","text":"World","number":2,"flag":false}}} diff --git a/test/unit/Elsa.Http.UnitTests/RateLimiting/IngressRateLimitingTests.cs b/test/unit/Elsa.Http.UnitTests/RateLimiting/IngressRateLimitingTests.cs index 4bdffea11..ec5eb2d7c 100644 --- a/test/unit/Elsa.Http.UnitTests/RateLimiting/IngressRateLimitingTests.cs +++ b/test/unit/Elsa.Http.UnitTests/RateLimiting/IngressRateLimitingTests.cs @@ -314,11 +314,15 @@ public class IngressRateLimitingTests app => app.UseWorkflowsApiRateLimiting("elsa/api", PolicyName), options => AddFixedWindowLimiter(options, "other")); - app.Configure(); - await app.StartAsync(); - var client = app.GetTestClient(); + var exception = await Record.ExceptionAsync(async () => + { + app.Configure(); + await app.StartAsync(); + var client = app.GetTestClient(); + await client.GetAsync("/elsa/api/ping"); + }); - await Assert.ThrowsAsync(() => client.GetAsync("/elsa/api/ping")); + Assert.IsType(exception); } [Fact] diff --git a/test/unit/Elsa.Workflows.Api.UnitTests/Endpoints/IncidentStrategies/ListTests.cs b/test/unit/Elsa.Workflows.Api.UnitTests/Endpoints/IncidentStrategies/ListTests.cs new file mode 100644 index 000000000..9bcbe5b90 --- /dev/null +++ b/test/unit/Elsa.Workflows.Api.UnitTests/Endpoints/IncidentStrategies/ListTests.cs @@ -0,0 +1,28 @@ +using Elsa.Extensions; +using Elsa.Workflows.Api.Endpoints.IncidentStrategies.List; +using Elsa.Workflows.IncidentStrategies; +using Elsa.Workflows.Options; +using Elsa.Workflows.Services; +using Elsa.Common.Serialization; + +namespace Elsa.Workflows.Api.UnitTests.Endpoints.IncidentStrategies; + +public class ListTests +{ + [Fact] + public async Task ExecuteAsync_ReturnsWorkflowJsonTypeIdentifier_ForIncidentStrategyTypeName() + { + var options = new SerializationTypeOptions(); + options.RegisterTypeAlias(typeof(ContinueWithIncidentsStrategy), nameof(ContinueWithIncidentsStrategy)); + options.RegisterLegacySimpleAssemblyQualifiedName(typeof(ContinueWithIncidentsStrategy)); + var registry = new SerializationTypeRegistry(Microsoft.Extensions.Options.Options.Create(options)); + var endpoint = new List([new ContinueWithIncidentsStrategy()], registry); + + var response = await endpoint.ExecuteAsync(CancellationToken.None); + + var descriptor = Assert.Single(response.Items); + Assert.Equal(nameof(ContinueWithIncidentsStrategy), descriptor.TypeName); + Assert.True(registry.TryGetType(typeof(ContinueWithIncidentsStrategy).GetSimpleAssemblyQualifiedName(), out var legacyType)); + Assert.Equal(typeof(ContinueWithIncidentsStrategy), legacyType); + } +} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs index c90ab0a78..7782aeb13 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs @@ -1,5 +1,6 @@ using System.Text.Json; using Elsa.Common.Serialization; +using Elsa.Expressions.Services; using Elsa.Workflows.Activities; using Elsa.Workflows.Helpers; using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; @@ -8,7 +9,6 @@ using Elsa.Workflows.Models; using Elsa.Workflows.Serialization.Configurators; using Elsa.Workflows.Serialization.Converters; using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; using Microsoft.Extensions.Logging; using NSubstitute; @@ -162,7 +162,7 @@ public sealed class ActivityJsonConverterTests Converters = { sut, - new TypeJsonConverter(new WorkflowJsonOptions()), + new TypeJsonConverter(), new PolymorphicObjectConverterFactory() }, TypeInfoResolver = new ModifiableJsonTypeInfoResolver(new CustomConstructorConfigurator().GetModifiers()) diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/SerializationTypeResolverTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/SerializationTypeResolverTests.cs new file mode 100644 index 000000000..e392d6d09 --- /dev/null +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/SerializationTypeResolverTests.cs @@ -0,0 +1,396 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using Elsa.Expressions.Options; +using Elsa.Expressions.Services; +using Elsa.Extensions; +using Elsa.Workflows.Exceptions; +using Elsa.Workflows.Memory; +using Elsa.Workflows.Options; +using Elsa.Workflows.Serialization.Converters; +using Elsa.Workflows.Services; +using Elsa.Workflows.State; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using Elsa.Common.Serialization; + +namespace Elsa.Workflows.Core.UnitTests.Serialization.Converters; + +public sealed class SerializationTypeResolverTests +{ + private static readonly string UnsafeAssemblyQualifiedTypeAlias = typeof(System.Text.StringBuilder).AssemblyQualifiedName!; + private readonly SerializationTypeRegistry _workflowJsonTypeRegistry = new(Microsoft.Extensions.Options.Options.Create(new SerializationTypeOptions())); + private readonly JsonSerializerOptions _options; + + public SerializationTypeResolverTests() + { + _workflowJsonTypeRegistry.RegisterType(typeof(ExceptionState), nameof(ExceptionState)); + _workflowJsonTypeRegistry.RegisterType(typeof(FaultException), nameof(FaultException)); + _workflowJsonTypeRegistry.RegisterType(typeof(RegisteredPayload), "RegisteredPayload"); + _options = CreateOptions(_workflowJsonTypeRegistry); + } + + [Theory] + [InlineData("String", typeof(string))] + [InlineData("String[]", typeof(string[]))] + [InlineData("String[][]", typeof(string[][]))] + [InlineData("List", typeof(List))] + [InlineData("List", typeof(List))] + [InlineData("List>", typeof(List>))] + [InlineData("ExceptionState", typeof(ExceptionState))] + [InlineData("FaultException", typeof(FaultException))] + [InlineData("ObjectDictionary", typeof(IDictionary))] + public void When_DeserializeRegisteredTypeAlias_Then_ReturnsExpectedType(string typeAlias, Type expectedType) + { + var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _options); + + Assert.Equal(expectedType, result); + } + + [Fact] + public void When_DeserializeRegisteredLegacyAssemblyQualifiedTypeAlias_Then_ReturnsExpectedType() + { + var typeAlias = typeof(RegisteredPayload).GetSimpleAssemblyQualifiedName(); + + var result = JsonSerializer.Deserialize(JsonString(typeAlias), _options); + + Assert.Equal(typeof(RegisteredPayload), result); + } + + [Fact] + public void When_DeserializeRegisteredTypeAliasWithDifferentCasing_Then_ReturnsExpectedType() + { + var result = JsonSerializer.Deserialize(JsonString("registeredpayload"), _options); + + Assert.Equal(typeof(RegisteredPayload), result); + } + + [Fact] + public void When_DeserializeRegisteredLegacyGenericCollectionTypeAlias_Then_ReturnsExpectedType() + { + var typeAlias = typeof(List).GetSimpleAssemblyQualifiedName(); + + var result = JsonSerializer.Deserialize(JsonString(typeAlias), _options); + + Assert.Equal(typeof(List), result); + } + + [Theory] + [InlineData(typeof(string), "String")] + [InlineData(typeof(string[]), "String[]")] + [InlineData(typeof(string[][]), "String[][]")] + [InlineData(typeof(List), "List")] + [InlineData(typeof(List), "List")] + [InlineData(typeof(List>), "List>")] + [InlineData(typeof(ExceptionState), "ExceptionState")] + [InlineData(typeof(FaultException), "FaultException")] + public void When_SerializeSupportedType_Then_EmitsAliasThatCanBeDeserialized(Type type, string expectedAlias) + { + var json = JsonSerializer.Serialize(type, _options); + var alias = JsonSerializer.Deserialize(json); + var result = JsonSerializer.Deserialize(json, _options); + + Assert.Equal(expectedAlias, alias); + Assert.Equal(type, result); + } + + [Theory] + [InlineData(typeof(IEnumerable), "List", typeof(List))] + [InlineData(typeof(ICollection), "List", typeof(List))] + [InlineData(typeof(IList), "List", typeof(List))] + [InlineData(typeof(IReadOnlyCollection), "List", typeof(List))] + [InlineData(typeof(IReadOnlyList), "List", typeof(List))] + [InlineData(typeof(ISet), "HashSet", typeof(HashSet))] + public void When_SerializeInterfaceCollectionType_Then_EmitsInstantiableAlias(Type type, string expectedAlias, Type expectedRoundTripType) + { + var json = JsonSerializer.Serialize(type, _options); + var alias = JsonSerializer.Deserialize(json); + var result = JsonSerializer.Deserialize(json, _options); + + Assert.Equal(expectedAlias, alias); + Assert.Equal(expectedRoundTripType, result); + } + + [Theory] + [MemberData(nameof(JsonIslandValues))] + public void When_SerializeSpecialJsonIslandType_Then_CanBeDeserialized(object value, Type expectedType) + { + _workflowJsonTypeRegistry.RegisterType(typeof(JObject), nameof(JObject)); + _workflowJsonTypeRegistry.RegisterType(typeof(JArray), nameof(JArray)); + + var json = JsonSerializer.Serialize(value, _options); + var result = JsonSerializer.Deserialize(json, _options); + + Assert.IsType(expectedType, result); + } + + [Theory] + [InlineData(typeof(System.Text.StringBuilder))] + [InlineData(typeof(System.Text.StringBuilder[]))] + [InlineData(typeof(List))] + public void When_SerializeUnsupportedType_Then_EmitsSafeUnregisteredTypeAlias(Type type) + { + var json = JsonSerializer.Serialize(type, _options); + var alias = JsonSerializer.Deserialize(json); + var result = JsonSerializer.Deserialize(json, _options); + + Assert.StartsWith("UnregisteredClrType:", alias); + Assert.Equal(typeof(Exception), result); + } + + [Fact] + public void When_SerializeExceptionStateWithUnregisteredExceptionType_Then_DoesNotThrow() + { + var exceptionState = ExceptionState.FromException(new NullReferenceException("Test")); + + var json = JsonSerializer.Serialize(exceptionState, _options); + var result = JsonSerializer.Deserialize(json, _options)!; + + Assert.Contains("UnregisteredClrType:", json); + Assert.Equal(typeof(Exception), result.Type); + Assert.Equal("Test", result.Message); + } + + [Fact] + public void When_ConfigureWorkflowsFeature_Then_RegistersCoreAliases() + { + var services = new ServiceCollection(); + var module = services.CreateModule(); + module.UseWorkflows(); + module.Apply(); + using var serviceProvider = services.BuildServiceProvider(); + var registry = serviceProvider.GetRequiredService(); + + var aliasRegistered = registry.TryGetAlias(typeof(NullReferenceException), out var alias); + var typeRegistered = registry.TryGetType(nameof(NullReferenceException), out var type); + + Assert.True(aliasRegistered); + Assert.Equal(nameof(NullReferenceException), alias); + Assert.True(typeRegistered); + Assert.Equal(typeof(NullReferenceException), type); + Assert.True(registry.TryGetAlias(typeof(MemoryStorageDriver), out var memoryStorageDriverAlias)); + Assert.Equal(nameof(MemoryStorageDriver), memoryStorageDriverAlias); + Assert.True(registry.TryGetType(nameof(MemoryStorageDriver), out var memoryStorageDriverType)); + Assert.Equal(typeof(MemoryStorageDriver), memoryStorageDriverType); + Assert.True(registry.TryGetType(typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName(), out var legacyMemoryStorageDriverType)); + Assert.Equal(typeof(MemoryStorageDriver), legacyMemoryStorageDriverType); + Assert.True(registry.TryGetAlias(typeof(Elsa.Workflows.IncidentStrategies.ContinueWithIncidentsStrategy), out var incidentStrategyAlias)); + Assert.Equal(nameof(Elsa.Workflows.IncidentStrategies.ContinueWithIncidentsStrategy), incidentStrategyAlias); + Assert.True(registry.TryGetType(typeof(Elsa.Workflows.IncidentStrategies.ContinueWithIncidentsStrategy).GetSimpleAssemblyQualifiedName(), out var legacyIncidentStrategyType)); + Assert.Equal(typeof(Elsa.Workflows.IncidentStrategies.ContinueWithIncidentsStrategy), legacyIncidentStrategyType); + } + + [Fact] + public void When_TypeAliasExistsOnlyInExpressionOptions_Then_WorkflowJsonDoesNotResolveIt() + { + var expressionOptions = new ExpressionOptions(); + expressionOptions.RegisterTypeAlias(typeof(ExpressionOnlyPayload), "ExpressionOnlyPayload"); + var expressionRegistry = new WellKnownTypeRegistry(Microsoft.Extensions.Options.Options.Create(expressionOptions)); + + Assert.True(expressionRegistry.TryGetType("ExpressionOnlyPayload", out _)); + Assert.Throws(() => JsonSerializer.Deserialize(JsonString("ExpressionOnlyPayload"), _options)); + } + + [Fact] + public void When_SerializePolymorphicObjectWithUnregisteredType_Then_OmitsTypeMetadata() + { + var json = JsonSerializer.Serialize(new UnregisteredPayload { Name = "Alice" }, _options); + + var result = JsonSerializer.Deserialize(json, _options); + + Assert.DoesNotContain("\"_type\"", json); + var payload = Assert.IsAssignableFrom>(result); + Assert.Equal("Alice", payload["name"]); + } + + [Fact] + public void When_DeserializeUnknownAssemblyQualifiedTypeAlias_Then_ThrowsJsonException() + { + Assert.Throws(() => JsonSerializer.Deserialize(JsonString(UnsafeAssemblyQualifiedTypeAlias), _options)); + } + + [Fact] + public void When_DeserializeUnknownGenericElementTypeAlias_Then_ThrowsJsonException() + { + var typeAlias = $"List<{UnsafeAssemblyQualifiedTypeAlias}>"; + + Assert.Throws(() => JsonSerializer.Deserialize(JsonString(typeAlias), _options)); + } + + [Fact] + public void When_DeserializePolymorphicObjectWithRegisteredTypeAlias_Then_ReturnsTypedObject() + { + var json = """ + { + "name": "Alice", + "_type": "RegisteredPayload" + } + """; + + var result = JsonSerializer.Deserialize(json, _options); + + var payload = Assert.IsType(result); + Assert.Equal("Alice", payload.Name); + } + + [Theory] + [InlineData("IEnumerable", typeof(List))] + [InlineData("ICollection", typeof(List))] + [InlineData("IList", typeof(List))] + [InlineData("IReadOnlyCollection", typeof(List))] + [InlineData("IReadOnlyList", typeof(List))] + [InlineData("ISet", typeof(HashSet))] + public void When_DeserializePolymorphicCollectionInterface_Then_ReturnsConcreteCollection(string typeAlias, Type expectedType) + { + var json = $$""" + { + "_items": ["Alice"], + "_type": "{{typeAlias}}" + } + """; + + var result = JsonSerializer.Deserialize(json, _options); + + Assert.IsType(expectedType, result); + } + + [Fact] + public void When_DeserializePolymorphicObjectWithNonInstantiableType_Then_ThrowsJsonException() + { + _workflowJsonTypeRegistry.RegisterType(typeof(AbstractPayload), "AbstractPayload"); + var json = """ + { + "_type": "AbstractPayload" + } + """; + + Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); + } + + [Fact] + public void When_DeserializePolymorphicObjectWithUnknownAssemblyQualifiedType_Then_ThrowsJsonException() + { + var json = $$""" + { + "capacity": 16, + "_type": {{JsonString(UnsafeAssemblyQualifiedTypeAlias)}} + } + """; + + Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); + } + + [Fact] + public void When_DeserializePolymorphicObjectWithoutTypeJsonConverterAndUnknownAssemblyQualifiedType_Then_ThrowsJsonException() + { + var options = CreatePolymorphicOnlyOptions(_workflowJsonTypeRegistry); + var json = $$""" + { + "capacity": 16, + "_type": {{JsonString(UnsafeAssemblyQualifiedTypeAlias)}} + } + """; + + Assert.Throws(() => JsonSerializer.Deserialize(json, options)); + } + + [Fact] + public void When_DeserializeDictionaryObjectPayloadWithRegisteredTypeAlias_Then_ReturnsTypedObjectValue() + { + var json = """ + { + "payload": { + "name": "Alice", + "_type": "RegisteredPayload" + } + } + """; + + var result = JsonSerializer.Deserialize>(json, _options)!; + + var payload = Assert.IsType(result["payload"]); + Assert.Equal("Alice", payload.Name); + } + + [Fact] + public void When_DeserializeDictionaryObjectPayloadWithUnknownAssemblyQualifiedType_Then_ThrowsJsonException() + { + var json = $$""" + { + "payload": { + "capacity": 16, + "_type": {{JsonString(UnsafeAssemblyQualifiedTypeAlias)}} + } + } + """; + + Assert.Throws(() => JsonSerializer.Deserialize>(json, _options)); + } + + [Fact] + public void When_RegistryChangesAfterLegacyResolutionAttempt_Then_LegacyResolutionUsesCurrentRegistry() + { + var typeAlias = typeof(LateRegisteredPayload).GetSimpleAssemblyQualifiedName(); + Assert.False(SerializationTypeResolver.TryResolveType(_workflowJsonTypeRegistry, typeAlias, out _)); + + _workflowJsonTypeRegistry.RegisterType(typeof(LateRegisteredPayload), "LateRegisteredPayload"); + + Assert.True(SerializationTypeResolver.TryResolveType(_workflowJsonTypeRegistry, typeAlias, out var result)); + Assert.Equal(typeof(LateRegisteredPayload), result); + } + + private static JsonSerializerOptions CreateOptions(ISerializationTypeRegistry workflowJsonTypeRegistry) => new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + Converters = + { + new PolymorphicObjectConverterFactory(workflowJsonTypeRegistry), + new TypeJsonConverter(workflowJsonTypeRegistry) + } + }; + + private static JsonSerializerOptions CreatePolymorphicOnlyOptions(ISerializationTypeRegistry workflowJsonTypeRegistry) => new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + Converters = + { + new PolymorphicObjectConverterFactory(workflowJsonTypeRegistry) + } + }; + + private static string JsonString(string value) => JsonSerializer.Serialize(value); + + public static TheoryData JsonIslandValues() => new() + { + { new JObject { ["name"] = "Alice" }, typeof(JObject) }, + { new JArray("Alice", "Bob"), typeof(JArray) }, + { new JsonObject { ["name"] = "Alice" }, typeof(JsonObject) }, + { new JsonArray("Alice", "Bob"), typeof(JsonArray) } + }; + + public sealed class RegisteredPayload + { + public string? Name { get; set; } + } + + public sealed class UnregisteredPayload + { + public string? Name { get; set; } + } + + public abstract class AbstractPayload + { + public string? Name { get; set; } + } + + public sealed class LateRegisteredPayload + { + public string? Name { get; set; } + } + + public sealed class ExpressionOnlyPayload + { + public string? Name { get; set; } + } +} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs deleted file mode 100644 index 71f2b1396..000000000 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/WorkflowJsonTypeResolverTests.cs +++ /dev/null @@ -1,268 +0,0 @@ -using System.Text.Json; -using Elsa.Expressions.Models; -using Elsa.Extensions; -using Elsa.Workflows.Activities.Flowchart.Models; -using Elsa.Workflows.Exceptions; -using Elsa.Workflows.IncidentStrategies; -using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Helpers; -using Elsa.Workflows.Serialization.Options; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Elsa.Workflows.Core.UnitTests.Serialization.Converters; - -public class WorkflowJsonTypeResolverTests -{ - private static readonly string UnsafeAssemblyQualifiedTypeAlias = typeof(System.Text.StringBuilder).AssemblyQualifiedName!; - private static readonly string TrustedAssemblyQualifiedTypeAlias = typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(); - private readonly JsonSerializerOptions _options; - private readonly JsonSerializerOptions _strictOptions; - - public WorkflowJsonTypeResolverTests() - { - _options = CreateOptions(); - _strictOptions = CreateOptions(false); - } - - [Fact] - public void TypeJsonConverter_ResolvesClrAssemblyQualifiedType() - { - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(UnsafeAssemblyQualifiedTypeAlias), _options); - - Assert.Equal(typeof(System.Text.StringBuilder), result); - } - - [Fact] - public void TypeJsonConverter_RejectsUnregisteredClrAssemblyQualifiedType_WhenLegacyClrTypeNamesDisabled() - { - Assert.Throws(() => JsonSerializer.Deserialize(JsonSerializer.Serialize(UnsafeAssemblyQualifiedTypeAlias), _strictOptions)); - } - - [Fact] - public void TypeJsonConverter_ResolvesTrustedClrAssemblyQualifiedType() - { - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(TrustedAssemblyQualifiedTypeAlias), _options); - - Assert.Equal(typeof(UnregisteredPayload), result); - } - - [Fact] - public void TypeJsonConverter_ResolvesIncidentStrategyClrType() - { - var typeAlias = typeof(ContinueWithIncidentsStrategy).GetSimpleAssemblyQualifiedName(); - - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _options); - - Assert.Equal(typeof(ContinueWithIncidentsStrategy), result); - } - - [Fact] - public void TypeJsonConverter_ResolvesFaultExceptionClrType() - { - var typeAlias = typeof(FaultException).GetSimpleAssemblyQualifiedName(); - - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _options); - - Assert.Equal(typeof(FaultException), result); - } - - [Fact] - public void PolymorphicObjectConverter_ResolvesClrAssemblyQualifiedType() - { - var json = $$""" - { - "name": "Alice", - "_type": {{JsonSerializer.Serialize(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName())}} - } - """; - - var result = JsonSerializer.Deserialize(json, _options); - - var payload = Assert.IsType(result); - Assert.Equal("Alice", payload.Name); - } - - [Fact] - public void PolymorphicObjectConverter_RejectsUnregisteredClrAssemblyQualifiedType_WhenLegacyClrTypeNamesDisabled() - { - var json = $$""" - { - "name": "Alice", - "_type": {{JsonSerializer.Serialize(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName())}} - } - """; - - Assert.Throws(() => JsonSerializer.Deserialize(json, _strictOptions)); - } - - [Fact] - public void PolymorphicObjectConverter_ResolvesRegisteredTypeAlias() - { - var json = """ - { - "name": "Alice", - "_type": "RegisteredPayload" - } - """; - - var result = JsonSerializer.Deserialize(json, _options); - - var payload = Assert.IsType(result); - Assert.Equal("Alice", payload.Name); - } - - [Fact] - public void PolymorphicObjectConverter_WritesClrTypeMetadataForUnregisteredTypes() - { - var json = JsonSerializer.Serialize(new UnregisteredPayload { Name = "Alice" }, _options); - var result = JsonSerializer.Deserialize(json, _options); - - Assert.Contains("\"_type\"", json); - var payload = Assert.IsType(result); - Assert.Equal("Alice", payload.Name); - } - - [Fact] - public void PolymorphicObjectConverter_RejectsUnregisteredClrTypeMetadata_WhenLegacyClrTypeNamesDisabled() - { - Assert.Throws(() => JsonSerializer.Serialize(new UnregisteredPayload { Name = "Alice" }, _strictOptions)); - } - - [Fact] - public void TypeJsonConverter_WritesUnregisteredTypesAsClrTypeNames() - { - var json = JsonSerializer.Serialize(typeof(UnregisteredPayload), _options); - var alias = JsonSerializer.Deserialize(json); - var result = JsonSerializer.Deserialize(json, _options); - - Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), alias); - Assert.Equal(typeof(UnregisteredPayload), result); - } - - [Fact] - public void TypeJsonConverter_RejectsUnregisteredClrTypeMetadata_WhenLegacyClrTypeNamesDisabled() - { - Assert.Throws(() => JsonSerializer.Serialize(typeof(UnregisteredPayload), _strictOptions)); - } - - [Fact] - public void OutputJsonConverter_WritesUnregisteredTypesAsClrTypeNames() - { - var options = CreateOptions(); - options.Converters.Add(new OutputJsonConverter(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions()))); - var output = new Output(new MemoryBlockReference("result")); - - var json = JsonSerializer.Serialize(output, options); - - using var doc = JsonDocument.Parse(json); - Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), doc.RootElement.GetProperty("typeName").GetString()); - } - - [Fact] - public void OutputJsonConverter_RejectsUnregisteredClrTypeMetadata_WhenLegacyClrTypeNamesDisabled() - { - var workflowJsonOptions = new WorkflowJsonOptions - { - AllowLegacyClrTypeNames = false - }; - var options = CreateOptions(); - options.Converters.Add(new OutputJsonConverter(Microsoft.Extensions.Options.Options.Create(workflowJsonOptions))); - var output = new Output(new MemoryBlockReference("result")); - - Assert.Throws(() => JsonSerializer.Serialize(output, options)); - } - - [Fact] - public void TypeJsonConverter_ResolvesRegisteredLegacyAssemblyQualifiedName() - { - var typeAlias = typeof(RegisteredPayload).GetSimpleAssemblyQualifiedName(); - - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize(typeAlias), _strictOptions); - - Assert.Equal(typeof(RegisteredPayload), result); - } - - [Fact] - public void TypeJsonConverter_ResolvesRegisteredAliasesCaseInsensitively() - { - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize("registeredpayload"), _strictOptions); - - Assert.Equal(typeof(RegisteredPayload), result); - } - - [Fact] - public void TypeJsonConverter_WritesPreferredAlias_WhenTypeHasMultipleAliases() - { - var json = JsonSerializer.Serialize(typeof(FlowJoinMode), _strictOptions); - - Assert.Equal("\"FlowJoinMode\"", json); - } - - [Fact] - public void TypeJsonConverter_RoundTripsNullableValueTypeAliases_WhenLegacyClrTypeNamesDisabled() - { - var json = JsonSerializer.Serialize(typeof(int?), _strictOptions); - var result = JsonSerializer.Deserialize(JsonSerializer.Serialize("int32?"), _strictOptions); - - Assert.Equal("\"Int32?\"", json); - Assert.Equal(typeof(int?), result); - } - - [Fact] - public void ShellWorkflowsFeature_RegistersWorkflowJsonTypeAliases() - { - var services = new ServiceCollection(); - new Elsa.Workflows.ShellFeatures.WorkflowsFeature().ConfigureServices(services); - var workflowJsonOptions = services.BuildServiceProvider().GetRequiredService>().Value; - - var faultStrategy = WorkflowJsonTypeResolver.ResolveType(workflowJsonOptions, nameof(FaultStrategy), false); - - Assert.Equal(typeof(FaultStrategy), faultStrategy); - } - - [Fact] - public void ShellFlowchartFeature_RegistersFlowScopeTypeAlias() - { - var services = new ServiceCollection(); - new Elsa.Workflows.ShellFeatures.FlowchartFeature().ConfigureServices(services); - var workflowJsonOptions = services.BuildServiceProvider().GetRequiredService>().Value; - - var flowScope = WorkflowJsonTypeResolver.ResolveType(workflowJsonOptions, "FlowScope", false); - - Assert.Equal(typeof(FlowScope), flowScope); - } - - private JsonSerializerOptions CreateOptions(bool allowLegacyClrTypeNames = true) - { - var workflowJsonOptions = new WorkflowJsonOptions - { - AllowLegacyClrTypeNames = allowLegacyClrTypeNames - }; - workflowJsonOptions.RegisterWorkflowTypeAliases(); - workflowJsonOptions.RegisterTypeAlias(typeof(RegisteredPayload), "RegisteredPayload"); - workflowJsonOptions.RegisterTypeAlias(typeof(FaultStrategy), nameof(FaultStrategy)); - - return new() - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - PropertyNameCaseInsensitive = true, - Converters = - { - new PolymorphicObjectConverterFactory(workflowJsonOptions), - new TypeJsonConverter(workflowJsonOptions) - } - }; - } - - public sealed class RegisteredPayload - { - public string? Name { get; set; } - } - - public sealed class UnregisteredPayload - { - public string? Name { get; set; } - } -} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs index 62c6042ab..24dea445c 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Services/VariableMapperTests.cs @@ -1,24 +1,24 @@ -using System.Text.Json; using Elsa.Extensions; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; using Elsa.Workflows.Services; using Microsoft.Extensions.Logging.Abstractions; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Core.UnitTests.Services; public class VariableMapperTests { - private readonly WorkflowJsonOptions _workflowJsonOptions = new(); + private readonly SerializationTypeRegistry _registry = new(Microsoft.Extensions.Options.Options.Create(new SerializationTypeOptions())); private readonly VariableMapper _mapper; public VariableMapperTests() { - _workflowJsonOptions.RegisterTypeAlias(typeof(string), "String"); - _workflowJsonOptions.RegisterTypeAlias(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); - _workflowJsonOptions.RegisterTypeAlias(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); - _mapper = new(NullLogger.Instance, _workflowJsonOptions); + _registry.RegisterType(typeof(string), "String"); + _registry.RegisterType(typeof(WorkflowStorageDriver), nameof(WorkflowStorageDriver)); + _registry.RegisterType(typeof(MemoryStorageDriver), typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName()); + _mapper = new(_registry, NullLogger.Instance); } [Fact] @@ -38,13 +38,21 @@ public class VariableMapperTests } [Fact] - public void Map_ResolvesRegisteredStorageDriverAssemblyQualifiedName() + public void Map_ResolvesRegisteredMemoryStorageDriverAssemblyQualifiedName() { var variable = _mapper.Map(new VariableModel("id", "name", "String", "value", typeof(MemoryStorageDriver).GetSimpleAssemblyQualifiedName())); Assert.Equal(typeof(MemoryStorageDriver), variable.StorageDriverType); } + [Fact] + public void Map_WritesRegisteredStorageDriverAlias() + { + var model = _mapper.Map(new Variable("name", "") { StorageDriverType = typeof(WorkflowStorageDriver) }); + + Assert.Equal(nameof(WorkflowStorageDriver), model.StorageDriverTypeName); + } + [Fact] public void Map_DoesNotLoadUnregisteredStorageDriverAssemblyQualifiedName() { @@ -56,37 +64,10 @@ public class VariableMapperTests [Fact] public void Map_DoesNotUseRegisteredNonStorageDriverAliasAsStorageDriver() { - _workflowJsonOptions.RegisterTypeAlias(typeof(string), "NotAStorageDriver"); + _registry.RegisterType(typeof(string), "NotAStorageDriver"); var variable = _mapper.Map(new VariableModel("id", "name", "String", "value", "NotAStorageDriver")); Assert.Null(variable.StorageDriverType); } - - [Fact] - public void Map_WritesUnregisteredVariableTypeAsClrTypeName() - { - var variable = new Variable("payload", new()); - - var model = _mapper.Map(variable); - - Assert.Equal(typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), model.TypeName); - } - - [Fact] - public void Map_RejectsUnregisteredVariableType_WhenLegacyClrTypeNamesDisabled() - { - var workflowJsonOptions = new WorkflowJsonOptions - { - AllowLegacyClrTypeNames = false - }; - var mapper = new VariableMapper(NullLogger.Instance, workflowJsonOptions); - var variable = new Variable("payload", new()); - - Assert.Throws(() => mapper.Map(variable)); - } - - private sealed class UnregisteredPayload - { - } } diff --git a/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs b/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs index 2a6ba1acb..8110b8d3d 100644 --- a/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs +++ b/test/unit/Elsa.Workflows.Management.UnitTests/Mappers/VariableDefinitionMapperTests.cs @@ -1,51 +1,51 @@ -using System.Text.Json; using Elsa.Extensions; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Options; +using Elsa.Workflows.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using NSubstitute; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Management.UnitTests.Mappers; public class VariableDefinitionMapperTests { private readonly IServiceScopeFactory _scopeFactory = Substitute.For(); - private readonly WorkflowJsonOptions _workflowJsonOptions = new(); + private readonly SerializationTypeOptions _workflowJsonTypeOptions = new(); private readonly VariableDefinitionMapper _mapper; public VariableDefinitionMapperTests() { - _workflowJsonOptions.RegisterTypeAlias(typeof(string), "String"); - _workflowJsonOptions.RegisterTypeAlias(typeof(MemoryStorageDriver), nameof(MemoryStorageDriver)); - _mapper = CreateMapper(_workflowJsonOptions); + _workflowJsonTypeOptions.RegisterTypeAlias(typeof(string), "String"); + _workflowJsonTypeOptions.RegisterTypeAlias(typeof(MemoryStorageDriver), nameof(MemoryStorageDriver)); + _mapper = CreateMapper(_workflowJsonTypeOptions); } [Fact] - public void Map_ResolvesUnregisteredClrTypeName_WhenLegacyClrTypeNamesEnabled() + public void Map_DoesNotResolveUnregisteredClrTypeName() { var definition = new VariableDefinition("id", "payload", typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), false, null, null); var variable = _mapper.Map(definition); - Assert.IsType>(variable); + Assert.Null(variable); } [Fact] - public void Map_DoesNotResolveUnregisteredClrTypeName_WhenLegacyClrTypeNamesDisabled() + public void Map_ResolvesRegisteredLegacyClrTypeName() { - var workflowJsonOptions = new WorkflowJsonOptions - { - AllowLegacyClrTypeNames = false - }; - var mapper = CreateMapper(workflowJsonOptions); + var workflowJsonTypeOptions = new SerializationTypeOptions(); + workflowJsonTypeOptions.RegisterTypeAlias(typeof(UnregisteredPayload), nameof(UnregisteredPayload)); + workflowJsonTypeOptions.RegisterLegacySimpleAssemblyQualifiedName(typeof(UnregisteredPayload)); + var mapper = CreateMapper(workflowJsonTypeOptions); var definition = new VariableDefinition("id", "payload", typeof(UnregisteredPayload).GetSimpleAssemblyQualifiedName(), false, null, null); var variable = mapper.Map(definition); - Assert.Null(variable); + Assert.IsType>(variable); } [Fact] @@ -59,21 +59,22 @@ public class VariableDefinitionMapperTests } [Fact] - public void Map_RejectsUnregisteredVariableType_WhenLegacyClrTypeNamesDisabled() + public void Map_WritesRegisteredVariableTypeAsAlias() { - var workflowJsonOptions = new WorkflowJsonOptions - { - AllowLegacyClrTypeNames = false - }; - var mapper = CreateMapper(workflowJsonOptions); + var workflowJsonTypeOptions = new SerializationTypeOptions(); + workflowJsonTypeOptions.RegisterTypeAlias(typeof(UnregisteredPayload), nameof(UnregisteredPayload)); + var mapper = CreateMapper(workflowJsonTypeOptions); var variable = new Variable("payload", new()); - Assert.Throws(() => mapper.Map(variable)); + var definition = mapper.Map(variable); + + Assert.Equal(nameof(UnregisteredPayload), definition.TypeName); } - private VariableDefinitionMapper CreateMapper(WorkflowJsonOptions workflowJsonOptions) + private VariableDefinitionMapper CreateMapper(SerializationTypeOptions workflowJsonTypeOptions) { - return new(Microsoft.Extensions.Options.Options.Create(workflowJsonOptions), _scopeFactory, NullLogger.Instance); + var workflowJsonTypeRegistry = new SerializationTypeRegistry(Microsoft.Extensions.Options.Options.Create(workflowJsonTypeOptions)); + return new(workflowJsonTypeRegistry, _scopeFactory, NullLogger.Instance); } private sealed class UnregisteredPayload diff --git a/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs b/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs index 5e7eba5d3..1fe4344ae 100644 --- a/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs +++ b/test/unit/Elsa.Workflows.Management.UnitTests/Services/WorkflowDefinitionExporterRegressionTests.cs @@ -6,10 +6,11 @@ using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Models; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using NSubstitute; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Management.UnitTests.Services; @@ -61,7 +62,8 @@ public class WorkflowDefinitionExporterRegressionTests { var activitySerializer = Substitute.For(); var scopeFactory = Substitute.For(); - var variableDefinitionMapper = new VariableDefinitionMapper(Microsoft.Extensions.Options.Options.Create(new WorkflowJsonOptions()), scopeFactory, NullLogger.Instance); + var workflowJsonTypeRegistry = SerializationTypeRegistry.CreateDefault(); + var variableDefinitionMapper = new VariableDefinitionMapper(workflowJsonTypeRegistry, scopeFactory, NullLogger.Instance); var workflowDefinitionMapper = new WorkflowDefinitionMapper(activitySerializer, _workflowDefinitionService, variableDefinitionMapper); var fileNameSanitizer = new DefaultFileNameSanitizer(); diff --git a/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs b/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs index d20a45359..c283566b1 100644 --- a/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs +++ b/test/unit/Elsa.Workflows.Runtime.UnitTests/Comparers/WorkflowTriggerEqualityComparerTests.cs @@ -1,10 +1,11 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Workflows.Helpers; +using Elsa.Workflows.Options; using Elsa.Workflows.Runtime.Comparers; using Elsa.Workflows.Runtime.Entities; -using Elsa.Workflows.Serialization.Converters; -using Elsa.Workflows.Serialization.Options; +using Elsa.Workflows.Services; +using Elsa.Common.Serialization; namespace Elsa.Workflows.Runtime.UnitTests.Comparers; @@ -27,8 +28,8 @@ public class WorkflowTriggerEqualityComparerTests /// A simple payload class that mimics real trigger payloads like HttpEndpointBookmarkPayload. /// private record TestPayload(string Path, string Method); - - private record TypePayload(Type TargetType); + private record TypedPayload(Type PayloadType, object Value); + private record NestedPayload(string Name); [Fact(DisplayName = "Fresh and round-tripped triggers with identical logical content should be considered equal")] public void FreshAndRoundTrippedTriggers_ShouldBeEqual() @@ -41,7 +42,7 @@ public class WorkflowTriggerEqualityComparerTests var roundTrippedPayload = SimulatePayloadRoundTrip(freshPayload); var loadedTrigger = CreateTrigger("trigger-1", roundTrippedPayload); - var comparer = new WorkflowTriggerEqualityComparer(); + var comparer = new WorkflowTriggerEqualityComparer(CreateTypeRegistry()); // Act var areEqual = comparer.Equals(freshTrigger, loadedTrigger); @@ -72,7 +73,7 @@ public class WorkflowTriggerEqualityComparerTests var newTriggers = new List { freshTrigger }; // Act: this is exactly what TriggerIndexer.IndexTriggersInternalAsync does - var diff = Diff.For(currentTriggers, newTriggers, new WorkflowTriggerEqualityComparer()); + var diff = Diff.For(currentTriggers, newTriggers, new WorkflowTriggerEqualityComparer(CreateTypeRegistry())); // Assert: the diff should find no changes. // Before the fix, it reported Removed=[existingTrigger] and Added=[freshTrigger] @@ -82,22 +83,6 @@ public class WorkflowTriggerEqualityComparerTests Assert.Single(diff.Unchanged); } - [Fact(DisplayName = "Comparer should use configured type aliases when normalizing trigger payloads")] - public void FreshAndRoundTrippedTriggers_WithRegisteredTypeAlias_ShouldBeEqual() - { - var workflowJsonOptions = new WorkflowJsonOptions(); - workflowJsonOptions.RegisterTypeAlias(typeof(CustomAliasTarget), "CustomAlias"); - var payload = new TypePayload(typeof(CustomAliasTarget)); - var roundTrippedPayload = SimulatePayloadRoundTrip(payload, workflowJsonOptions); - var freshTrigger = CreateTrigger("trigger-1", payload); - var loadedTrigger = CreateTrigger("trigger-1", roundTrippedPayload); - var comparer = new WorkflowTriggerEqualityComparer(workflowJsonOptions); - - var areEqual = comparer.Equals(freshTrigger, loadedTrigger); - - Assert.True(areEqual); - } - [Fact(DisplayName = "Documents the underlying System.Text.Json casing behavior that necessitated the fix")] public void PayloadSerializationMismatch_ProducesDifferentJson() { @@ -126,6 +111,50 @@ public class WorkflowTriggerEqualityComparerTests Assert.Equal("{\"Path\":\"/api/test\",\"Method\":\"GET\"}", freshJson); Assert.Equal("{\"path\":\"/api/test\",\"method\":\"GET\"}", roundTrippedJson); } + + [Fact(DisplayName = "Comparer serializes typed payload properties using the registered type aliases")] + public void TypedPayloadProperties_ShouldSerializeWithRegisteredAliases() + { + var payload = new TypedPayload(typeof(NestedPayload), new NestedPayload("orders")); + var comparer = new WorkflowTriggerEqualityComparer(CreateTypeRegistry()); + var trigger = CreateTrigger("trigger-1", payload); + var expectedAliasPayload = JsonSerializer.Deserialize( + """ + { + "payloadType": "NestedPayload", + "value": { + "name": "orders", + "_type": "NestedPayload" + } + } + """, + PayloadSerializerOptions); + var assemblyQualifiedPayload = JsonSerializer.Deserialize( + $$""" + { + "payloadType": "{{typeof(NestedPayload).AssemblyQualifiedName}}", + "value": { + "name": "orders", + "_type": "{{typeof(NestedPayload).AssemblyQualifiedName}}" + } + } + """, + PayloadSerializerOptions); + var missingTypePayload = JsonSerializer.Deserialize( + """ + { + "payloadType": "NestedPayload", + "value": { + "name": "orders" + } + } + """, + PayloadSerializerOptions); + + Assert.True(comparer.Equals(trigger, CreateTrigger("trigger-2", expectedAliasPayload!))); + Assert.False(comparer.Equals(trigger, CreateTrigger("trigger-3", assemblyQualifiedPayload!))); + Assert.False(comparer.Equals(trigger, CreateTrigger("trigger-4", missingTypePayload!))); + } /// /// IPayloadSerializer options: camelCase with case-insensitive deserialization. @@ -162,20 +191,13 @@ public class WorkflowTriggerEqualityComparerTests return deserialized!; } - private static object SimulatePayloadRoundTrip(object payload, WorkflowJsonOptions workflowJsonOptions) + private static ISerializationTypeRegistry CreateTypeRegistry() { - var options = CreatePayloadSerializerOptions(workflowJsonOptions); - var json = JsonSerializer.Serialize(payload, options); - return JsonSerializer.Deserialize(json, options)!; - } - - private static JsonSerializerOptions CreatePayloadSerializerOptions(WorkflowJsonOptions workflowJsonOptions) - { - var options = new JsonSerializerOptions(PayloadSerializerOptions); - options.Converters.Add(new JsonStringEnumConverter()); - options.Converters.Add(new PolymorphicObjectConverterFactory(workflowJsonOptions)); - options.Converters.Add(new TypeJsonConverter(workflowJsonOptions)); - return options; + var registry = new SerializationTypeRegistry(Microsoft.Extensions.Options.Options.Create(new SerializationTypeOptions())); + registry.RegisterType(typeof(TestPayload), nameof(TestPayload)); + registry.RegisterType(typeof(TypedPayload), nameof(TypedPayload)); + registry.RegisterType(typeof(NestedPayload), nameof(NestedPayload)); + return registry; } /// @@ -198,6 +220,4 @@ public class WorkflowTriggerEqualityComparerTests Hash = hash, Payload = payload }; - - private sealed class CustomAliasTarget; } diff --git a/test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs b/test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs new file mode 100644 index 000000000..ea633c152 --- /dev/null +++ b/test/unit/Elsa.Workflows.Runtime.UnitTests/Features/WorkflowRuntimeFeatureTests.cs @@ -0,0 +1,214 @@ +using System.Reflection; +using Elsa.Features.Attributes; +using Elsa.Features.Services; +using Elsa.Extensions; +using Elsa.Workflows; +using Elsa.Workflows.Activities; +using Elsa.Workflows.Features; +using Elsa.Workflows.Options; +using Elsa.Workflows.Runtime.Options; +using Elsa.Workflows.Runtime.Providers; +using NSubstitute; +using RuntimeFeature = Elsa.Workflows.Runtime.Features.WorkflowRuntimeFeature; +using ShellRuntimeFeature = Elsa.Workflows.Runtime.ShellFeatures.WorkflowRuntimeFeature; +using Elsa.Common.Serialization; + +namespace Elsa.Workflows.Runtime.UnitTests.Features; + +public class WorkflowRuntimeFeatureTests +{ + private readonly RuntimeFeature _feature = new(Substitute.For()); + private readonly ShellRuntimeFeature _shellFeature = new(); + + [Fact] + public void AddWorkflow_Throws_WhenTypeDoesNotImplementWorkflow() + { + Assert.Throws(() => _feature.AddWorkflow(typeof(NotAWorkflow))); + } + + [Theory] + [MemberData(nameof(NonInstantiableWorkflowTypes))] + public void AddWorkflow_Throws_WhenWorkflowTypeIsNotInstantiable(Type workflowType) + { + Assert.Throws(() => _feature.AddWorkflow(workflowType)); + } + + [Fact] + public void ShellAddWorkflow_Throws_WhenTypeDoesNotImplementWorkflow() + { + Assert.Throws(() => _shellFeature.AddWorkflow(typeof(NotAWorkflow))); + } + + [Theory] + [MemberData(nameof(NonInstantiableWorkflowTypes))] + public void ShellAddWorkflow_Throws_WhenWorkflowTypeIsNotInstantiable(Type workflowType) + { + Assert.Throws(() => _shellFeature.AddWorkflow(workflowType)); + } + + [Fact] + public void AddWorkflow_AllowsClosedGenericWorkflowType() + { + var workflowType = typeof(GenericWorkflow); + + _feature.AddWorkflow(workflowType); + + Assert.Contains(workflowType.GetSimpleAssemblyQualifiedName(), _feature.Workflows.Keys); + Assert.Contains(workflowType.FullName!, _feature.Workflows.Keys); + } + + [Fact] + public void ShellAddWorkflow_AllowsClosedGenericWorkflowType() + { + var workflowType = typeof(GenericWorkflow); + + _shellFeature.AddWorkflow(workflowType); + + Assert.Contains(workflowType.GetSimpleAssemblyQualifiedName(), _shellFeature.Workflows.Keys); + Assert.Contains(workflowType.FullName!, _shellFeature.Workflows.Keys); + } + + [Fact] + public void WorkflowsAdd_RegistersWorkflowTypeAlias() + { + var workflowType = typeof(GenericWorkflow); + var options = new SerializationTypeOptions(); + + _feature.Workflows.Add(workflowType); + + RegisterWorkflowTypeAliases(_feature, options); + + Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); + } + + [Fact] + public void WorkflowsAdd_DoesNotThrow_WhenLegacyKeyAlreadyExists() + { + var workflowType = typeof(GenericWorkflow); + _feature.Workflows.Add(workflowType.FullName!, _ => new ValueTask(new GenericWorkflow())); + + _feature.Workflows.Add(workflowType); + + Assert.Contains(workflowType.GetSimpleAssemblyQualifiedName(), _feature.Workflows.Keys); + Assert.Contains(workflowType.FullName!, _feature.Workflows.Keys); + Assert.Same(_feature.Workflows[workflowType.FullName!], _feature.Workflows[workflowType.GetSimpleAssemblyQualifiedName()]); + } + + [Fact] + public async Task ClrWorkflowsProvider_MaterializesWorkflowOnce_WhenCanonicalAndLegacyKeysExist() + { + CountingWorkflow.CreatedCount = 0; + var builder = Substitute.For(); + var builderFactory = Substitute.For(); + var provider = new ClrWorkflowsProvider( + Microsoft.Extensions.Options.Options.Create(new RuntimeOptions { Workflows = _feature.Workflows }), + builderFactory, + Substitute.For()); + builderFactory.CreateBuilder().Returns(builder); + builder.BuildWorkflowAsync(Arg.Any()).Returns(new Workflow()); + + _feature.Workflows.Add(typeof(CountingWorkflow)); + var workflows = await provider.GetWorkflowsAsync(); + + Assert.Single(workflows); + Assert.Equal(1, CountingWorkflow.CreatedCount); + } + + [Fact] + public void ShellWorkflowsAdd_RegistersWorkflowTypeAlias() + { + var workflowType = typeof(GenericWorkflow); + var options = new SerializationTypeOptions(); + + _shellFeature.Workflows.Add(workflowType); + + RegisterWorkflowTypeAliases(_shellFeature, options); + + Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); + } + + [Fact] + public void WorkflowsAdd_Throws_WhenTypeDoesNotImplementWorkflow() + { + Assert.Throws(() => _feature.Workflows.Add(typeof(NotAWorkflow))); + } + + [Fact] + public void RuntimeFeature_DependsOnWorkflowsFeature() + { + var dependencyTypes = typeof(RuntimeFeature) + .GetCustomAttributes() + .Select(x => x.Type); + + Assert.Contains(typeof(WorkflowsFeature), dependencyTypes); + } + + [Fact] + public void RegisterWorkflowTypeAliases_RegistersOnlyTrackedWorkflowTypes() + { + var workflowType = typeof(GenericWorkflow); + var options = new SerializationTypeOptions(); + _feature.AddWorkflow(workflowType); + _feature.Workflows[typeof(NotAWorkflow).AssemblyQualifiedName!] = _ => new ValueTask(new GenericWorkflow()); + + RegisterWorkflowTypeAliases(_feature, options); + + Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); + Assert.DoesNotContain(typeof(NotAWorkflow).AssemblyQualifiedName!, options.AliasTypeDictionary.Keys); + } + + [Fact] + public void ShellRegisterWorkflowTypeAliases_RegistersOnlyTrackedWorkflowTypes() + { + var workflowType = typeof(GenericWorkflow); + var options = new SerializationTypeOptions(); + _shellFeature.AddWorkflow(workflowType); + _shellFeature.Workflows[typeof(NotAWorkflow).AssemblyQualifiedName!] = _ => new ValueTask(new GenericWorkflow()); + + RegisterWorkflowTypeAliases(_shellFeature, options); + + Assert.Equal(workflowType, options.AliasTypeDictionary[workflowType.GetSimpleAssemblyQualifiedName()]); + Assert.DoesNotContain(typeof(NotAWorkflow).AssemblyQualifiedName!, options.AliasTypeDictionary.Keys); + } + + public static TheoryData NonInstantiableWorkflowTypes() => new() + { + typeof(IWorkflow), + typeof(WorkflowBase), + typeof(GenericWorkflow<>) + }; + + private sealed class NotAWorkflow + { + } + + private sealed class GenericWorkflow : IWorkflow + { + public ValueTask BuildAsync(IWorkflowBuilder builder, CancellationToken cancellationToken = default) + { + return ValueTask.CompletedTask; + } + } + + public sealed class CountingWorkflow : IWorkflow + { + public static int CreatedCount { get; set; } + + public CountingWorkflow() + { + CreatedCount++; + } + + public ValueTask BuildAsync(IWorkflowBuilder builder, CancellationToken cancellationToken = default) + { + return ValueTask.CompletedTask; + } + } + + private static void RegisterWorkflowTypeAliases(object feature, SerializationTypeOptions options) + { + feature.GetType() + .GetMethod("RegisterWorkflowTypeAliases", BindingFlags.Instance | BindingFlags.NonPublic)! + .Invoke(feature, new object[] { options }); + } +}