using System.Runtime.CompilerServices; using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.JavaScript.Contracts; using Elsa.Workflows; using Elsa.Workflows.Attributes; using Elsa.Workflows.Models; using Elsa.Workflows.UIHints; using Jint; // ReSharper disable once CheckNamespace namespace Elsa.JavaScript.Activities; /// /// Executes JavaScript code. /// [Activity("Elsa", "Scripting", "Executes JavaScript code", DisplayName = "Run JavaScript")] public class RunJavaScript : CodeActivity { /// public RunJavaScript([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line) { } /// public RunJavaScript(string script, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : this(source, line) { Script = new Input(script); } /// /// The script to run. /// [Input( Description = "The script to run.", UIHint = InputUIHints.CodeEditor, UIHandler = typeof(RunJavaScriptOptionsProvider) )] public Input Script { get; set; } = new(""); /// /// A list of possible outcomes. Use "setOutcome()" to set the outcome. Use "setOutcomes" to set multiple outcomes. /// [Input(Description = "A list of possible outcomes.", UIHint = InputUIHints.DynamicOutcomes)] public Input> PossibleOutcomes { get; set; } = default!; /// protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) { var script = context.Get(Script); // If no script was specified, there's nothing to do. if (string.IsNullOrWhiteSpace(script)) return; // Get a JavaScript evaluator. var javaScriptEvaluator = context.GetRequiredService(); // Run the script. var result = await javaScriptEvaluator.EvaluateAsync( script, typeof(object), context.ExpressionExecutionContext, ExpressionEvaluatorOptions.Empty, engine => ConfigureEngine(engine, context), context.CancellationToken); // Set the result as output, if any. if (result is not null) context.Set(Result, result); // Get the outcome or outcomes set by the script, if any. If not set, use "Done". var outcomes = context.TransientProperties.GetValueOrDefault("Outcomes", () => new[] { "Done" })!; // Complete the activity with the outcome. await context.CompleteActivityWithOutcomesAsync(outcomes); } private static void ConfigureEngine(Engine engine, ActivityExecutionContext context) { engine.SetValue("setOutcome", (Action)(value => context.TransientProperties["Outcomes"] = new[] { value })); engine.SetValue("setOutcomes", (Action)(value => context.TransientProperties["Outcomes"] = value)); } }