diff --git a/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs b/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs index 76418baa2..1a718a482 100644 --- a/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs +++ b/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs @@ -3,6 +3,7 @@ using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.JavaScript.Notifications; using Elsa.Mediator.Contracts; +using Elsa.Workflows.Core.Contracts; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Activities; using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; @@ -38,27 +39,41 @@ public class WorkflowDefinitionActivityJavaScriptHandler : INotificationHandler< var engine = notification.Engine; var context = notification.Context; - // If we are already evaluating inputs, then we're in a circular evaluation loop. In this case, we should not attempt to evaluate the inputs. - if(context.TransientProperties.TryGetValue("EvaluatingInputs", out var evaluatingInputs) && (bool)evaluatingInputs) - return; + // Always create workflow input accessors. + CreateWorkflowInputAccessors(engine, context); + // If we are already evaluating inputs, then we're in a circular evaluation loop. In this case, we should not attempt to evaluate the inputs. + if (context.TransientProperties.TryGetValue("EvaluatingInputs", out var evaluatingInputs) && (bool)evaluatingInputs) + return; + // To prevent a circular evaluation loop, set a flag on the context to indicate that we're currently evaluating the inputs. context.TransientProperties["EvaluatingInputs"] = true; - + // Create input getters. await CreateInputAccessorsAsync(engine, context); } + private void CreateWorkflowInputAccessors(Engine engine, ExpressionExecutionContext context) + { + var input = context.GetWorkflowExecutionContext().Input; + + foreach (var inputEntry in input) + { + var inputPascalName = inputEntry.Key.Pascalize(); + var inputValue = inputEntry.Value; + engine.SetValue($"get{inputPascalName}", (Func)(() => inputValue)); + } + } + private async Task CreateInputAccessorsAsync(Engine engine, ExpressionExecutionContext context) { - var workflowDefinitionActivity = GetFirstWorkflowDefinitionActivity(context); - + var workflowDefinitionActivity = context.GetActivityExecutionContext().GetFirstWorkflowDefinitionActivity(); if (workflowDefinitionActivity == null) return; - var descriptor = _activityRegistry.Find(workflowDefinitionActivity.Type, workflowDefinitionActivity.Version)!; - var inputDefinitions = descriptor.Inputs; - + var workflowDefinitionActivityDescriptor = _activityRegistry.Find(workflowDefinitionActivity.Type, workflowDefinitionActivity.Version); + var inputDefinitions = workflowDefinitionActivityDescriptor?.Inputs ?? Enumerable.Empty(); + foreach (var inputDefinition in inputDefinitions) { var inputPascalName = inputDefinition.Name.Pascalize(); @@ -68,7 +83,4 @@ public class WorkflowDefinitionActivityJavaScriptHandler : INotificationHandler< engine.SetValue($"get{inputPascalName}", (Func)(() => evaluatedExpression)); } } - - private static WorkflowDefinitionActivity? GetFirstWorkflowDefinitionActivity(ExpressionExecutionContext context) => - context.GetActivityExecutionContext().GetFirstWorkflowDefinitionActivity(); } \ No newline at end of file diff --git a/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs b/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs index e21922272..6c3e0821c 100644 --- a/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs +++ b/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs @@ -70,6 +70,7 @@ public class JintJavaScriptEvaluator : IJavaScriptEvaluator engine.SetValue("setCorrelationId", (Action)(value => context.GetActivityExecutionContext().WorkflowExecutionContext.CorrelationId = value)); engine.SetValue("setVariable", (Action)((name, value) => context.SetVariable(name, value))); engine.SetValue("getVariable", (Func)(name => context.GetVariable(name))); + engine.SetValue("getInput", (Func)(name => context.GetWorkflowExecutionContext().Input.GetValue(name))); // Create variable & input setters and getters for each variable. CreateMemoryBlockAccessors(engine, context); diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs b/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs index 1d32c6138..f048cddc6 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs @@ -42,6 +42,11 @@ internal class CommonFunctionsDefinitionProvider : FunctionDefinitionProvider .Parameter("name", "string") .ReturnType("any")); + yield return CreateFunctionDefinition(builder => builder + .Name("getInput") + .Parameter("name", "string") + .ReturnType("any")); + yield return CreateFunctionDefinition(builder => builder .Name("isNullOrWhiteSpace") .Parameter("value", "string") diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs index cc4748e0e..dc7b7e17a 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Endpoint.cs @@ -34,11 +34,15 @@ internal class Endpoint : ElsaEndpoint await SendNotFoundAsync(cancellationToken); return; } + + var correlationId = request.CorrelationId; + var input = (IDictionary?)request.Input; - var result = await _workflowDispatcher.DispatchAsync(new DispatchWorkflowDefinitionRequest( + await _workflowDispatcher.DispatchAsync(new DispatchWorkflowDefinitionRequest( request.DefinitionId, VersionOptions.Published, - CorrelationId: request.CorrelationId), + input, + correlationId), cancellationToken); await SendOkAsync(new Response(), cancellationToken); diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs index 06eb8fee9..2ccae5689 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Dispatch/Models.cs @@ -1,11 +1,17 @@ +using System.Text.Json.Serialization; +using Elsa.Workflows.Core.Serialization.Converters; + namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Dispatch; -public class Request +internal class Request { public string DefinitionId { get; set; } = default!; public string? CorrelationId { get; set; } + + [JsonConverter(typeof(ExpandoObjectConverter))] + public object? Input { get; set; } } -public class Response +internal class Response { } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Handlers/RefreshActivityRegistryHandler.cs b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/RefreshActivityRegistryHandler.cs similarity index 95% rename from src/modules/Elsa.Workflows.Management/Handlers/RefreshActivityRegistryHandler.cs rename to src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/RefreshActivityRegistryHandler.cs index 786d7cb49..824953395 100644 --- a/src/modules/Elsa.Workflows.Management/Handlers/RefreshActivityRegistryHandler.cs +++ b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/RefreshActivityRegistryHandler.cs @@ -2,9 +2,8 @@ using Elsa.Mediator.Contracts; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Notifications; -using Elsa.Workflows.Management.Providers; -namespace Elsa.Workflows.Management.Handlers; +namespace Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; /// /// Refreshes the for the provider whenever an is published, retracted or deleted. diff --git a/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs index 0cb9cb2db..46df6e770 100644 --- a/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs +++ b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivityProvider.cs @@ -1,12 +1,10 @@ using Elsa.Common.Models; using Elsa.Workflows.Core.Models; -using Elsa.Workflows.Management.Activities; -using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Entities; using Humanizer; -namespace Elsa.Workflows.Management.Providers; +namespace Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; /// /// Provides activity descriptors based on s stored in the database.