using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Design; using Elsa.Scripting.JavaScript.Events; using Elsa.Scripting.JavaScript.Messages; using Elsa.Scripting.JavaScript.Services; using Elsa.Services; using Elsa.Services.Models; using Jint; using MediatR; using NetBox.Extensions; // ReSharper disable once CheckNamespace namespace Elsa.Activities.JavaScript { [Action(Category = "Scripting", Description = "Run JavaScript code.")] public class RunJavaScript : Activity, INotificationHandler { private readonly IJavaScriptService _javaScriptService; public RunJavaScript(IJavaScriptService javaScriptService) { _javaScriptService = javaScriptService; } [ActivityProperty(Hint = "The JavaScript to run.", UIHint = ActivityPropertyUIHints.CodeEditor, OptionsProvider = nameof(GetOptions))] public string? Script { get; set; } [ActivityProperty(Hint = "The possible outcomes that can be set by the script.", UIHint = ActivityPropertyUIHints.MultiText)] public ICollection Outcomes { get; set; } = new List { OutcomeNames.Done }; protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context) { var script = Script; if (script is null or "") return Done(); var outcomes = new HashSet(); void ConfigureEngine(Engine engine) { void SetOutcome(string value) => outcomes.Add(value); void SetOutcomes(IEnumerable values) => outcomes.AddRange(values); engine.SetValue("setOutcome", (Action) SetOutcome); engine.SetValue("setOutcomes", (Action>) SetOutcomes); } var output = await _javaScriptService.EvaluateAsync(script, typeof(object), context, ConfigureEngine, context.CancellationToken); if (!outcomes.Any()) outcomes.Add(OutcomeNames.Done); return new CombinedResult(Output(output), new OutcomeResult(outcomes)); } private static object GetOptions() => new { EditorHeight = "Large", Context = nameof(RunJavaScript), Syntax = JavaScriptExpressionHandler.SyntaxName }; public Task Handle(RenderingTypeScriptDefinitions notification, CancellationToken cancellationToken) { var context = notification.Context; if (context != nameof(RunJavaScript)) return Task.CompletedTask; notification.Output.AppendLine("declare function setOutcome(name: string);"); notification.Output.AppendLine("declare function setOutcomes(names: Array);"); return Task.CompletedTask; } } }