Merge branch 'main' into custom-uiprovider
This commit is contained in:
commit
cfb3d032ea
|
|
@ -66,6 +66,7 @@
|
|||
"DefaultSender": "noreply@crmservices.com"
|
||||
},
|
||||
"Http": {
|
||||
"BaseUrl": "https://localhost:5001",
|
||||
"BasePath": "/api/workflows"
|
||||
},
|
||||
"Webhooks": {
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts;
|
||||
using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts;
|
||||
using Elsa.Api.Client.Resources.Scripting.Contracts;
|
||||
using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts;
|
||||
using Elsa.Api.Client.Resources.WorkflowInstances.Contracts;
|
||||
|
||||
namespace Elsa.Api.Client.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a client for the Elsa API. Each API is exposed as a property.
|
||||
/// </summary>
|
||||
public interface IElsaClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the workflow definitions API.
|
||||
/// </summary>
|
||||
IWorkflowDefinitionsApi WorkflowDefinitions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the activity descriptors API.
|
||||
/// </summary>
|
||||
IActivityDescriptorsApi ActivityDescriptors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the activity descriptor Options API
|
||||
/// </summary>
|
||||
IActivityDescriptorOptionsApi ActivityDescriptorOptions { get; }
|
||||
/// <summary>
|
||||
/// Gets the workflow instances API.
|
||||
/// </summary>
|
||||
IWorkflowInstancesApi WorkflowInstances { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the javascript API.
|
||||
/// </summary>
|
||||
IJavaScriptApi JavaScript { get; }
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
using Elsa.Api.Client.Options;
|
||||
|
||||
namespace Elsa.Api.Client.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// A factory for creating <see cref="IElsaClient"/> instances.
|
||||
/// </summary>
|
||||
public interface IElsaClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="IElsaClient"/> instance.
|
||||
/// </summary>
|
||||
IElsaClient CreateClient(Action<ElsaClientOptions> configureOptions, Action<ElsaClientBuilderOptions>? configureHttpClientBuilder = default);
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Elsa.Api.Client.Contracts;
|
||||
using Elsa.Api.Client.Converters;
|
||||
using Elsa.Api.Client.HttpMessageHandlers;
|
||||
using Elsa.Api.Client.Options;
|
||||
using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts;
|
||||
using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts;
|
||||
|
|
@ -17,7 +15,6 @@ 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 Elsa.Api.Client.Services;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -33,40 +30,39 @@ namespace Elsa.Api.Client.Extensions;
|
|||
public static class DependencyInjectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the Elsa client to the service collection.
|
||||
/// Adds the Elsa API client configured to use an API key to the service collection.
|
||||
/// </summary>
|
||||
/// <param name="services">The service collection.</param>
|
||||
/// <param name="baseAddress">The base address of the Elsa API.</param>
|
||||
/// <param name="apiKey">The API key to use for authentication.</param>
|
||||
/// <param name="configureOptions">An optional delegate that can be used to configure the client options.</param>
|
||||
/// <param name="configureBuilderOptions">An optional delegate that can be used to configure the client builder options.</param>
|
||||
public static IServiceCollection AddElsaClient(this IServiceCollection services, Uri baseAddress, string apiKey, Action<ElsaClientOptions>? configureOptions = default, Action<ElsaClientBuilderOptions>? configureBuilderOptions = default)
|
||||
public static IServiceCollection AddElsaApiKeyClient(this IServiceCollection services, Action<ElsaClientOptions> configureOptions)
|
||||
{
|
||||
services.AddScoped<ApiKeyHttpMessageHandler>();
|
||||
return services.AddElsaClient(
|
||||
options =>
|
||||
{
|
||||
options.BaseAddress = baseAddress;
|
||||
options.ApiKey = apiKey;
|
||||
configureOptions?.Invoke(options);
|
||||
},
|
||||
configureBuilderOptions: options =>
|
||||
{
|
||||
options.ConfigureHttpClientBuilder = builder => builder.AddHttpMessageHandler<ApiKeyHttpMessageHandler>();
|
||||
configureBuilderOptions?.Invoke(options);
|
||||
});
|
||||
var options = new ElsaClientOptions();
|
||||
configureOptions(options);
|
||||
|
||||
return services.AddElsaClient(client =>
|
||||
{
|
||||
client.BaseAddress = options.BaseAddress;
|
||||
client.ApiKey = options.ApiKey;
|
||||
client.ConfigureHttpClient = options.ConfigureHttpClient;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the Elsa client to the service collection.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddElsaClient(this IServiceCollection services, Action<ElsaClientOptions>? configureOptions = default, Action<ElsaClientBuilderOptions>? configureBuilderOptions = default)
|
||||
public static IServiceCollection AddElsaClient(this IServiceCollection services, Action<ElsaClientBuilderOptions> configureClient)
|
||||
{
|
||||
var builderOptions = new ElsaClientBuilderOptions();
|
||||
configureBuilderOptions?.Invoke(builderOptions);
|
||||
configureClient.Invoke(builderOptions);
|
||||
|
||||
builderOptions.ConfigureHttpClientBuilder += builder => builder.AddHttpMessageHandler(sp => (DelegatingHandler)sp.GetRequiredService(builderOptions.AuthenticationHandler));
|
||||
|
||||
services.Configure(configureOptions ?? (_ => { }));
|
||||
services.AddScoped<IElsaClient, ElsaClient>();
|
||||
services.AddScoped(builderOptions.AuthenticationHandler);
|
||||
|
||||
services.Configure<ElsaClientOptions>(options =>
|
||||
{
|
||||
options.BaseAddress = builderOptions.BaseAddress;
|
||||
options.ConfigureHttpClient = builderOptions.ConfigureHttpClient;
|
||||
options.ApiKey = builderOptions.ApiKey;
|
||||
});
|
||||
services.AddApi<IWorkflowDefinitionsApi>(builderOptions);
|
||||
services.AddApi<IWorkflowInstancesApi>(builderOptions);
|
||||
services.AddApi<IActivityDescriptorsApi>(builderOptions);
|
||||
|
|
|
|||
14
src/clients/Elsa.Api.Client/Extensions/HeaderExtensions.cs
Normal file
14
src/clients/Elsa.Api.Client/Extensions/HeaderExtensions.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using Elsa.Api.Client.Shared;
|
||||
|
||||
namespace Elsa.Api.Client.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Contains extension methods for the <see cref="HttpResponseMessage"/> class.
|
||||
/// </summary>
|
||||
public static class HttpResponseMessageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the workflow instance ID from the response.
|
||||
/// </summary>
|
||||
public static string? GetWorkflowInstanceId(this HttpResponseMessage response) => response.Headers.TryGetValues(HeaderNames.WorkflowInstanceId, out var values) ? values.FirstOrDefault() : default;
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using Elsa.Api.Client.HttpMessageHandlers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.Api.Client.Options;
|
||||
|
|
@ -7,10 +8,29 @@ namespace Elsa.Api.Client.Options;
|
|||
/// </summary>
|
||||
public class ElsaClientBuilderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the base address of the Elsa server.
|
||||
/// </summary>
|
||||
public Uri BaseAddress { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the API key function to use when authenticating with the Elsa server.
|
||||
/// </summary>
|
||||
public string? ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="DelegatingHandler"/> type that can be used to authenticate with the Elsa server.
|
||||
/// Defaults to <see cref="ApiKeyHttpMessageHandler"/>.
|
||||
/// </summary>
|
||||
public Type AuthenticationHandler { get; set; } = typeof(ApiKeyHttpMessageHandler);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a delegate that can be used to configure the HTTP client.
|
||||
/// </summary>
|
||||
public Action<IServiceProvider, HttpClient>? ConfigureHttpClient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a delegate that can be used to configure the HTTP client builder.
|
||||
/// </summary>
|
||||
public Action<IHttpClientBuilder>? ConfigureHttpClientBuilder { get; set; }
|
||||
|
||||
|
||||
public Action<IHttpClientBuilder> ConfigureHttpClientBuilder { get; set; } = _ => { };
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
using Elsa.Api.Client.Contracts;
|
||||
using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts;
|
||||
using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts;
|
||||
using Elsa.Api.Client.Resources.Scripting.Contracts;
|
||||
using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts;
|
||||
using Elsa.Api.Client.Resources.WorkflowInstances.Contracts;
|
||||
|
||||
namespace Elsa.Api.Client.Services;
|
||||
|
||||
/// <inheritdoc />
|
||||
public class ElsaClient : IElsaClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ElsaClient"/> class.
|
||||
/// </summary>
|
||||
public ElsaClient(IWorkflowDefinitionsApi workflowDefinitions
|
||||
, IWorkflowInstancesApi workflowInstances
|
||||
, IActivityDescriptorsApi activityDescriptors
|
||||
, IActivityDescriptorOptionsApi activityDescriptorOptions
|
||||
, IJavaScriptApi javaScript)
|
||||
{
|
||||
WorkflowDefinitions = workflowDefinitions;
|
||||
WorkflowInstances = workflowInstances;
|
||||
ActivityDescriptors = activityDescriptors;
|
||||
ActivityDescriptorOptions = activityDescriptorOptions;
|
||||
JavaScript = javaScript;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IWorkflowDefinitionsApi WorkflowDefinitions { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IActivityDescriptorsApi ActivityDescriptors { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IActivityDescriptorOptionsApi ActivityDescriptorOptions { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IWorkflowInstancesApi WorkflowInstances { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IJavaScriptApi JavaScript { get; }
|
||||
}
|
||||
12
src/clients/Elsa.Api.Client/Shared/HeaderNames.cs
Normal file
12
src/clients/Elsa.Api.Client/Shared/HeaderNames.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
namespace Elsa.Api.Client.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Contains header names used by the Elsa API.
|
||||
/// </summary>
|
||||
public static class HeaderNames
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the header that contains the workflow instance ID.
|
||||
/// </summary>
|
||||
public const string WorkflowInstanceId = "x-elsa-workflow-instance-id";
|
||||
}
|
||||
|
|
@ -30,6 +30,9 @@ public class JsonHttpContentParser : IHttpContentParser
|
|||
|
||||
using var reader = new StreamReader(content, leaveOpen: true);
|
||||
var json = await reader.ReadToEndAsync();
|
||||
|
||||
if(returnType == typeof(string))
|
||||
return json;
|
||||
|
||||
if (returnType == null || returnType.IsPrimitive)
|
||||
return json.ConvertTo(returnType ?? typeof(string))!;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ public class HttpEndpointPathUIHandler(IOptions<HttpActivityOptions> options) :
|
|||
public ValueTask<IDictionary<string, object>> GetUIPropertiesAsync(PropertyInfo propertyInfo, object? context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var baseUrl = options.Value.BaseUrl;
|
||||
var apiRoutePrefix = options.Value.ApiRoutePrefix;
|
||||
var completeBaseUrl = new Uri(baseUrl, apiRoutePrefix);
|
||||
var basePath = options.Value.BasePath;
|
||||
var completeBaseUrl = new Uri(baseUrl, basePath);
|
||||
|
||||
return new(new Dictionary<string, object>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,13 +44,5 @@ public class PythonGlobalInterpreterManager : IHostedService
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if(_mainThreadState != IntPtr.Zero)
|
||||
{
|
||||
PythonEngine.EndAllowThreads(_mainThreadState);
|
||||
PythonEngine.Shutdown();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using Elsa.Extensions;
|
|||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Models;
|
||||
using Elsa.Workflows.UIHints;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Elsa.Workflows.Activities;
|
||||
|
|
@ -100,7 +101,10 @@ public class SetVariable : CodeActivity
|
|||
/// <inheritdoc />
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
// Always refer to the variable by ID to ensure that the variable is resolved from the correct scope.
|
||||
var variableId = Variable.Id;
|
||||
var variable = context.ExpressionExecutionContext.EnumerateVariablesInScope().FirstOrDefault(x => x.Id == variableId);
|
||||
var value = context.Get(Value);
|
||||
context.SetVariable(Variable.Name, value);
|
||||
variable?.Set(context, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -314,6 +314,12 @@ public static class ExpressionExecutionContextExtensions
|
|||
|
||||
currentScope = currentScope.ParentContext;
|
||||
}
|
||||
|
||||
if (context.TryGetWorkflowExecutionContext(out var workflowExecutionContext))
|
||||
{
|
||||
if (workflowExecutionContext.Workflow.ResultVariable != null)
|
||||
yield return workflowExecutionContext.Workflow.ResultVariable;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Reference in a new issue