using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Api.Client.Converters; using Elsa.Api.Client.Options; using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts; using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; using Elsa.Api.Client.Resources.ActivityExecutions.Contracts; using Elsa.Api.Client.Resources.Features.Contracts; using Elsa.Api.Client.Resources.Identity.Contracts; using Elsa.Api.Client.Resources.IncidentStrategies.Contracts; using Elsa.Api.Client.Resources.Scripting.Contracts; using Elsa.Api.Client.Resources.StorageDrivers.Contracts; using Elsa.Api.Client.Resources.VariableTypes.Contracts; using Elsa.Api.Client.Resources.WorkflowActivationStrategies.Contracts; using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; using Elsa.Api.Client.Resources.WorkflowExecutionContexts.Contracts; using Elsa.Api.Client.Resources.WorkflowInstances.Contracts; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Polly; using Refit; namespace Elsa.Api.Client.Extensions; /// /// Provides extension methods for dependency injection. /// [PublicAPI] public static class DependencyInjectionExtensions { /// /// Adds the Elsa API client configured to use an API key to the service collection. /// public static IServiceCollection AddElsaApiKeyClient(this IServiceCollection services, Action configureOptions) { var options = new ElsaClientOptions(); configureOptions(options); return services.AddElsaClient(client => { client.BaseAddress = options.BaseAddress; client.ApiKey = options.ApiKey; client.ConfigureHttpClient = options.ConfigureHttpClient; }); } /// /// Adds the Elsa client to the service collection. /// public static IServiceCollection AddElsaClient(this IServiceCollection services, Action configureClient) { var builderOptions = new ElsaClientBuilderOptions(); configureClient.Invoke(builderOptions); builderOptions.ConfigureHttpClientBuilder += builder => builder.AddHttpMessageHandler(sp => (DelegatingHandler)sp.GetRequiredService(builderOptions.AuthenticationHandler)); services.AddScoped(builderOptions.AuthenticationHandler); services.Configure(options => { options.BaseAddress = builderOptions.BaseAddress; options.ConfigureHttpClient = builderOptions.ConfigureHttpClient; options.ApiKey = builderOptions.ApiKey; }); var builderOptionsWithoutRetryPolicy = new ElsaClientBuilderOptions { ApiKey = builderOptions.ApiKey, AuthenticationHandler = builderOptions.AuthenticationHandler, BaseAddress = builderOptions.BaseAddress, ConfigureHttpClient = builderOptions.ConfigureHttpClient, ConfigureHttpClientBuilder = builderOptions.ConfigureHttpClientBuilder, ConfigureRetryPolicy = null }; services.AddApi(builderOptions); services.AddApi(builderOptionsWithoutRetryPolicy); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); return services; } /// /// Adds a refit client for the specified API type. /// /// The service collection. /// An options object that can be used to configure the HTTP client builder. /// The type representing the API. public static void AddApi(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class { var builder = services.AddRefitClient(CreateRefitSettings, typeof(T).Name).ConfigureHttpClient(ConfigureElsaApiHttpClient); httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder); httpClientBuilderOptions?.ConfigureRetryPolicy?.Invoke(builder); } /// /// Adds a refit client for the specified API type. /// /// The service collection. /// An options object that can be used to configure the HTTP client builder. /// The type representing the API. public static void AddApiWithoutRetryPolicy(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class { var builder = services.AddRefitClient(CreateRefitSettings, typeof(T).Name).ConfigureHttpClient(ConfigureElsaApiHttpClient); httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder); } /// /// Creates an API client for the specified API type. /// public static T CreateApi(this IServiceProvider serviceProvider, Uri baseAddress) where T : class { var httpClientFactory = serviceProvider.GetRequiredService(); var httpClient = httpClientFactory.CreateClient(typeof(T).Name); httpClient.BaseAddress = baseAddress; return CreateApi(serviceProvider, httpClient); } /// /// Creates an API client for the specified API type. /// public static T CreateApi(this IServiceProvider serviceProvider, HttpClient httpClient) where T : class { return RestService.For(httpClient, CreateRefitSettings(serviceProvider)); } private static void ConfigureElsaApiHttpClient(IServiceProvider serviceProvider, HttpClient httpClient) { var options = serviceProvider.GetRequiredService>().Value; httpClient.BaseAddress = options.BaseAddress; options.ConfigureHttpClient?.Invoke(serviceProvider, httpClient); } /// /// Creates a instance configured for Elsa. /// private static RefitSettings CreateRefitSettings(IServiceProvider serviceProvider) { JsonSerializerOptions serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }; serializerOptions.Converters.Add(new JsonStringEnumConverter()); serializerOptions.Converters.Add(new VersionOptionsJsonConverter()); var settings = new RefitSettings { ContentSerializer = new SystemTextJsonContentSerializer(serializerOptions), }; return settings; } }