| | | 1 | | using Elsa.Expressions.Models; |
| | | 2 | | using Elsa.Extensions; |
| | | 3 | | using Elsa.Expressions.JavaScript.Extensions; |
| | | 4 | | using Elsa.Expressions.JavaScript.Notifications; |
| | | 5 | | using Elsa.Expressions.JavaScript.Options; |
| | | 6 | | using Elsa.Mediator.Contracts; |
| | | 7 | | using Humanizer; |
| | | 8 | | using JetBrains.Annotations; |
| | | 9 | | using Jint; |
| | | 10 | | using Microsoft.Extensions.Options; |
| | | 11 | | |
| | | 12 | | namespace Elsa.Expressions.JavaScript.Handlers; |
| | | 13 | | |
| | | 14 | | /// <summary> |
| | | 15 | | /// A handler that configures the Jint engine with workflow input and output accessors. |
| | | 16 | | /// </summary> |
| | | 17 | | [UsedImplicitly] |
| | 520 | 18 | | public class ConfigureEngineWithVariablesAndInputOutputAccessors(IOptions<JintOptions> options) : INotificationHandler<E |
| | | 19 | | { |
| | | 20 | | /// <inheritdoc /> |
| | | 21 | | public async Task HandleAsync(EvaluatingJavaScript notification, CancellationToken cancellationToken) |
| | | 22 | | { |
| | 188 | 23 | | if (options.Value.DisableWrappers) |
| | 0 | 24 | | return; |
| | | 25 | | |
| | 188 | 26 | | var engine = notification.Engine; |
| | 188 | 27 | | var context = notification.Context; |
| | | 28 | | |
| | | 29 | | // The order of the next 3 lines is important. |
| | 188 | 30 | | CreateVariableAccessors(engine, context); |
| | 188 | 31 | | CreateWorkflowInputAccessors(engine, context); |
| | 188 | 32 | | await CreateActivityOutputAccessorsAsync(engine, context); |
| | 188 | 33 | | } |
| | | 34 | | |
| | | 35 | | private void CreateVariableAccessors(Engine engine, ExpressionExecutionContext context) |
| | | 36 | | { |
| | 188 | 37 | | var variableNames = context.GetVariableNamesInScope().FilterInvalidVariableNames().ToList(); |
| | | 38 | | |
| | 642 | 39 | | foreach (var variableName in variableNames) |
| | | 40 | | { |
| | 133 | 41 | | var pascalName = variableName.Pascalize(); |
| | 165 | 42 | | engine.SetValue($"get{pascalName}", (Func<object?>)(() => context.GetVariableInScope(variableName))); |
| | 133 | 43 | | engine.SetValue($"set{pascalName}", (Action<object?>)(value => |
| | 133 | 44 | | { |
| | 3 | 45 | | engine.SyncVariablesContainer(options, variableName, value); |
| | 3 | 46 | | context.SetVariableInScope(variableName, value); |
| | 136 | 47 | | })); |
| | | 48 | | } |
| | 188 | 49 | | } |
| | | 50 | | |
| | | 51 | | private void CreateWorkflowInputAccessors(Engine engine, ExpressionExecutionContext context) |
| | | 52 | | { |
| | | 53 | | // Create workflow input accessors - only if the current activity is not part of a composite activity definition |
| | | 54 | | // Otherwise, the workflow input accessors will hide the composite activity input accessors which rely on variab |
| | 188 | 55 | | if (context.IsContainedWithinCompositeActivity()) |
| | 8 | 56 | | return; |
| | | 57 | | |
| | 242 | 58 | | var inputs = context.GetWorkflowInputs().Where(x => x.Name.IsValidVariableName()).ToDictionary(x => x.Name, Stri |
| | | 59 | | |
| | 180 | 60 | | if (!context.TryGetWorkflowExecutionContext(out var workflowExecutionContext)) |
| | 69 | 61 | | return; |
| | | 62 | | |
| | 111 | 63 | | var inputDefinitions = workflowExecutionContext.Workflow.Inputs; |
| | | 64 | | |
| | 232 | 65 | | foreach (var inputDefinition in inputDefinitions) |
| | | 66 | | { |
| | 5 | 67 | | var input = inputs.GetValueOrDefault(inputDefinition.Name); |
| | 9 | 68 | | engine.SetValue($"get{inputDefinition.Name}", (Func<object?>)(() => input?.Value)); |
| | | 69 | | } |
| | 111 | 70 | | } |
| | | 71 | | |
| | | 72 | | private static async Task CreateActivityOutputAccessorsAsync(Engine engine, ExpressionExecutionContext context) |
| | | 73 | | { |
| | 188 | 74 | | var activityOutputs = context.GetActivityOutputs(); |
| | | 75 | | |
| | 476 | 76 | | await foreach (var activityOutput in activityOutputs) |
| | 200 | 77 | | foreach (var outputName in activityOutput.OutputNames.FilterInvalidVariableNames()) |
| | 51 | 78 | | engine.SetValue($"get{outputName}From{activityOutput.ActivityName.Pascalize()}", (Func<object?>)(() => conte |
| | 188 | 79 | | } |
| | | 80 | | } |