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;
}
}