diff --git a/Elsa.sln b/Elsa.sln
index 0d380ec19..11f9750b8 100644
--- a/Elsa.sln
+++ b/Elsa.sln
@@ -46,10 +46,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MassTransit", "src\mod
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.IntegrationTests", "test\Elsa.IntegrationTests\Elsa.IntegrationTests.csproj", "{B066ED0A-86E0-4025-85C2-7E8F7139D8A4}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.UnitTests", "test\Elsa.UnitTests\Elsa.UnitTests.csproj", "{85A6862B-E523-45FA-A26B-BF98BE140E89}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Labels", "src\modules\Elsa.Labels\Elsa.Labels.csproj", "{80FF5821-E831-450D-AA0C-C76D07D878F4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bundles", "bundles", "{F06B9573-DF68-4606-866C-A7546A10A05A}"
@@ -161,6 +157,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ElasticsearchS
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.OutboundHttpRequests", "src\samples\console\Elsa.Samples.OutboundHttpRequests\Elsa.Samples.OutboundHttpRequests.csproj", "{39AB433B-F7A6-4DD3-873A-9527946B7BD8}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unit", "unit", "{18453B51-25EB-4317-A4B3-B10518252E92}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integration", "integration", "{1B8D5897-902E-4632-8698-E89CAF3DDF54}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "component", "component", "{08B41FFA-CEE3-46A7-B5C0-3EB65D37A16C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.JavaScript.UnitTests", "test\unit\Elsa.JavaScript.UnitTests\Elsa.JavaScript.UnitTests.csproj", "{0BB927FB-8C12-49B6-9150-64B733B2EBFD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.IntegrationTests", "test\integration\Elsa.IntegrationTests\Elsa.IntegrationTests.csproj", "{E9652738-2B3D-4357-B84B-54F0EA161382}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -199,14 +205,6 @@ Global
{BB983D0B-A939-4008-B9E3-C7C172BCF83A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BB983D0B-A939-4008-B9E3-C7C172BCF83A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BB983D0B-A939-4008-B9E3-C7C172BCF83A}.Release|Any CPU.Build.0 = Release|Any CPU
- {B066ED0A-86E0-4025-85C2-7E8F7139D8A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B066ED0A-86E0-4025-85C2-7E8F7139D8A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B066ED0A-86E0-4025-85C2-7E8F7139D8A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B066ED0A-86E0-4025-85C2-7E8F7139D8A4}.Release|Any CPU.Build.0 = Release|Any CPU
- {85A6862B-E523-45FA-A26B-BF98BE140E89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {85A6862B-E523-45FA-A26B-BF98BE140E89}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {85A6862B-E523-45FA-A26B-BF98BE140E89}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {85A6862B-E523-45FA-A26B-BF98BE140E89}.Release|Any CPU.Build.0 = Release|Any CPU
{80FF5821-E831-450D-AA0C-C76D07D878F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80FF5821-E831-450D-AA0C-C76D07D878F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80FF5821-E831-450D-AA0C-C76D07D878F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -411,6 +409,14 @@ Global
{39AB433B-F7A6-4DD3-873A-9527946B7BD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39AB433B-F7A6-4DD3-873A-9527946B7BD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39AB433B-F7A6-4DD3-873A-9527946B7BD8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0BB927FB-8C12-49B6-9150-64B733B2EBFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0BB927FB-8C12-49B6-9150-64B733B2EBFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0BB927FB-8C12-49B6-9150-64B733B2EBFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0BB927FB-8C12-49B6-9150-64B733B2EBFD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E9652738-2B3D-4357-B84B-54F0EA161382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E9652738-2B3D-4357-B84B-54F0EA161382}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E9652738-2B3D-4357-B84B-54F0EA161382}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E9652738-2B3D-4357-B84B-54F0EA161382}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{155227F0-A33B-40AA-A4B4-06F813EB921B} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F}
@@ -418,8 +424,6 @@ Global
{873BFC3E-63C2-4495-A503-5EC05DCD84E4} = {155227F0-A33B-40AA-A4B4-06F813EB921B}
{56C2FFB8-EA54-45B5-A095-4A78142EB4B5} = {155227F0-A33B-40AA-A4B4-06F813EB921B}
{5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F}
- {B066ED0A-86E0-4025-85C2-7E8F7139D8A4} = {90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}
- {85A6862B-E523-45FA-A26B-BF98BE140E89} = {90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}
{F06B9573-DF68-4606-866C-A7546A10A05A} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F}
{B2049499-D384-46DF-8837-F1180107DD54} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
{FC5D2CE9-FFB0-478D-8D54-E4109D1FD202} = {F06B9573-DF68-4606-866C-A7546A10A05A}
@@ -481,5 +485,10 @@ Global
{C25CFDCF-8E06-4DD8-A83E-FF7EF9FDA02E} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
{4A54379F-4775-41B6-9752-FF300288916A} = {56C2FFB8-EA54-45B5-A095-4A78142EB4B5}
{39AB433B-F7A6-4DD3-873A-9527946B7BD8} = {873BFC3E-63C2-4495-A503-5EC05DCD84E4}
+ {18453B51-25EB-4317-A4B3-B10518252E92} = {90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}
+ {1B8D5897-902E-4632-8698-E89CAF3DDF54} = {90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}
+ {08B41FFA-CEE3-46A7-B5C0-3EB65D37A16C} = {90031D64-CA0F-46D0-9AF4-8DC023A5FFCD}
+ {0BB927FB-8C12-49B6-9150-64B733B2EBFD} = {18453B51-25EB-4317-A4B3-B10518252E92}
+ {E9652738-2B3D-4357-B84B-54F0EA161382} = {1B8D5897-902E-4632-8698-E89CAF3DDF54}
EndGlobalSection
EndGlobal
diff --git a/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs b/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs
index d2ff8d3d1..6f25bff29 100644
--- a/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs
+++ b/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs
@@ -33,6 +33,13 @@ public class JavaScriptFeature : FeatureBase
///
public override void Configure()
{
+ Module.UseWorkflowManagement(management => management.AddActivitiesFrom());
+ }
+
+ ///
+ public override void Apply()
+ {
+ // JavaScript services.
Services
.AddSingleton()
.AddSingleton()
@@ -41,6 +48,7 @@ public class JavaScriptFeature : FeatureBase
.AddExpressionHandler()
;
+ // Type definition services.
Services
.AddSingleton()
.AddSingleton()
@@ -50,7 +58,8 @@ public class JavaScriptFeature : FeatureBase
.AddSingleton()
.AddSingleton()
;
-
- Module.UseWorkflowManagement(management => management.AddActivitiesFrom());
+
+ // Handlers.
+ Services.AddNotificationHandlersFrom();
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs b/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs
new file mode 100644
index 000000000..281d2a751
--- /dev/null
+++ b/src/modules/Elsa.JavaScript/Handlers/WorkflowDefinitionActivityJavaScriptHandler.cs
@@ -0,0 +1,73 @@
+using Elsa.Expressions.Models;
+using Elsa.Expressions.Services;
+using Elsa.Extensions;
+using Elsa.JavaScript.Notifications;
+using Elsa.Mediator.Services;
+using Elsa.Workflows.Core.Models;
+using Elsa.Workflows.Management.Activities;
+using Elsa.Workflows.Management.Extensions;
+using Elsa.Workflows.Management.Services;
+using Humanizer;
+using JetBrains.Annotations;
+using Jint;
+
+namespace Elsa.JavaScript.Handlers;
+
+///
+/// Configures the JavaScript engine with workflow input getters.
+///
+[PublicAPI]
+public class WorkflowDefinitionActivityJavaScriptHandler : INotificationHandler
+{
+ private readonly IActivityRegistry _activityRegistry;
+ private readonly IExpressionEvaluator _expressionEvaluator;
+
+ ///
+ /// Constructor.
+ ///
+ public WorkflowDefinitionActivityJavaScriptHandler(IActivityRegistry activityRegistry, IExpressionEvaluator expressionEvaluator)
+ {
+ _activityRegistry = activityRegistry;
+ _expressionEvaluator = expressionEvaluator;
+ }
+
+ ///
+ public async Task HandleAsync(EvaluatingJavaScript notification, CancellationToken cancellationToken)
+ {
+ 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;
+
+ // 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 async Task CreateInputAccessorsAsync(Engine engine, ExpressionExecutionContext context)
+ {
+ var workflowDefinitionActivity = GetFirstWorkflowDefinitionActivity(context);
+
+ if (workflowDefinitionActivity == null)
+ return;
+
+ var descriptor = _activityRegistry.Find(workflowDefinitionActivity.Type, workflowDefinitionActivity.Version)!;
+ var inputDefinitions = descriptor.Inputs;
+
+ foreach (var inputDefinition in inputDefinitions)
+ {
+ var inputPascalName = inputDefinition.Name.Pascalize();
+ var input = workflowDefinitionActivity.SyntheticProperties.TryGetValue(inputDefinition.Name, out var inputValue) ? (Input?)inputValue : default;
+ var evaluatedExpression = input != null ? await _expressionEvaluator.EvaluateAsync(input, context) : input;
+
+ engine.SetValue($"get{inputPascalName}", (Func