From 02f4dc9b8cd97ed1a1b903ef606d1da116f171d2 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 13 Nov 2024 19:58:00 +0100 Subject: [PATCH] Add Variable Name Validation and Wrapper Control (#6117) * Refactor directory structure and add variable wrappers option Renamed TypeDefinitions/Providers to Providers for better clarity. Added a new configuration option to disable generating variable wrappers for scenarios requiring invalid JavaScript variable names. * Add variable name validation and wrapper control Introduced methods to validate variable names and filter invalid ones. Integrated `DisableWrappers` option to control the generation of variable wrappers, enhancing flexibility in variable management. * Remove unused item group from project file The item group containing the "TypeDefinitions\Providers\" folder was removed from the Elsa.JavaScript.csproj file. This folder was not serving any purpose and its removal helps in cleaning up the project structure. --- src/apps/Elsa.Server.Web/Program.cs | 2 ++ .../Extensions/VariableNameExtensions.cs | 19 +++++++++++++ .../Handlers/GenerateArgumentAccessors.cs | 27 ++++++++++-------- .../GenerateWorkflowInputAccessors.cs | 26 ++++++++++------- .../GenerateWorkflowVariableAccessors.cs | 27 +++++++++++------- .../Elsa.CSharp/Options/CSharpOptions.cs | 6 ++++ .../Extensions/VariableNameExtensions.cs | 21 ++++++++++++++ .../Features/JavaScriptFeature.cs | 1 - .../Handlers/ConfigureEngineWithVariables.cs | 15 ++++++++-- ...ineWithVariablesAndInputOutputAccessors.cs | 17 +++++++---- .../Helpers/VariableNameValidator.cs | 9 ++++++ .../Elsa.JavaScript/Options/JintOptions.cs | 6 ++++ ...tivityOutputFunctionsDefinitionProvider.cs | 14 +++++++--- .../CommonFunctionsDefinitionProvider.cs | 28 +++++++++++-------- .../CommonTypesDefinitionProvider.cs | 2 +- .../InputFunctionsDefinitionProvider.cs | 10 +++++-- .../VariableTypeDefinitionProvider.cs | 2 +- ...WorkflowVariablesTypeDefinitionProvider.cs | 12 ++++++-- .../WorkflowVariablesVariableProvider.cs | 9 ++++-- 19 files changed, 189 insertions(+), 64 deletions(-) create mode 100644 src/modules/Elsa.CSharp/Extensions/VariableNameExtensions.cs create mode 100644 src/modules/Elsa.JavaScript/Extensions/VariableNameExtensions.cs create mode 100644 src/modules/Elsa.JavaScript/Helpers/VariableNameValidator.cs rename src/modules/Elsa.JavaScript/{TypeDefinitions => }/Providers/ActivityOutputFunctionsDefinitionProvider.cs (70%) rename src/modules/Elsa.JavaScript/{TypeDefinitions => }/Providers/CommonFunctionsDefinitionProvider.cs (81%) rename src/modules/Elsa.JavaScript/{TypeDefinitions => }/Providers/CommonTypesDefinitionProvider.cs (92%) rename src/modules/Elsa.JavaScript/{TypeDefinitions => }/Providers/VariableTypeDefinitionProvider.cs (96%) rename src/modules/Elsa.JavaScript/{TypeDefinitions => }/Providers/WorkflowVariablesTypeDefinitionProvider.cs (67%) rename src/modules/Elsa.JavaScript/{TypeDefinitions => }/Providers/WorkflowVariablesVariableProvider.cs (56%) diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index b86702ea2..895ed12d4 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -71,6 +71,7 @@ const MassTransitBroker massTransitBroker = MassTransitBroker.Memory; const bool useMultitenancy = false; const bool useAgents = false; const bool useSecrets = true; +const bool disableVariableWrappers = false; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; @@ -314,6 +315,7 @@ services .UseJavaScript(options => { options.AllowClrAccess = true; + options.DisableWrappers = disableVariableWrappers; options.ConfigureEngine(engine => { engine.Execute("function greet(name) { return `Hello ${name}!`; }"); diff --git a/src/modules/Elsa.CSharp/Extensions/VariableNameExtensions.cs b/src/modules/Elsa.CSharp/Extensions/VariableNameExtensions.cs new file mode 100644 index 000000000..35584f207 --- /dev/null +++ b/src/modules/Elsa.CSharp/Extensions/VariableNameExtensions.cs @@ -0,0 +1,19 @@ +namespace Elsa.CSharp.Extensions; + +public static class VariableNameExtensions +{ + public static bool IsValidVariableName(this string name) + { + return !string.IsNullOrWhiteSpace(name) && name.All(char.IsLetterOrDigit); + } + + public static bool IsInvalidVariableName(this string name) + { + return !IsValidVariableName(name); + } + + public static IEnumerable FilterInvalidVariableNames(this IEnumerable names) + { + return names.Where(IsValidVariableName); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.CSharp/Handlers/GenerateArgumentAccessors.cs b/src/modules/Elsa.CSharp/Handlers/GenerateArgumentAccessors.cs index f2b5477aa..bcbc202f7 100644 --- a/src/modules/Elsa.CSharp/Handlers/GenerateArgumentAccessors.cs +++ b/src/modules/Elsa.CSharp/Handlers/GenerateArgumentAccessors.cs @@ -1,9 +1,12 @@ using System.Text; +using Elsa.CSharp.Extensions; using Elsa.CSharp.Notifications; +using Elsa.CSharp.Options; using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.Mediator.Contracts; using JetBrains.Annotations; +using Microsoft.Extensions.Options; namespace Elsa.CSharp.Handlers; @@ -11,7 +14,7 @@ namespace Elsa.CSharp.Handlers; /// Configures the C# evaluator with methods to access workflow variables. /// [UsedImplicitly] -public class GenerateArgumentAccessors : INotificationHandler +public class GenerateArgumentAccessors(IOptions options) : INotificationHandler { /// public Task HandleAsync(EvaluatingCSharp notification, CancellationToken cancellationToken) @@ -24,17 +27,19 @@ public class GenerateArgumentAccessors : INotificationHandler sb.AppendLine(); sb.AppendLine("\tpublic T? Get(string name) => Arguments.TryGetValue(name, out var v) ? (T?)v : default;"); sb.AppendLine(); - foreach (var argument in arguments) + + if (!options.Value.DisableWrappers) { - // var d = new Dictionary(); - // d.TryGetValue("", out var f); - var argumentName = argument.Key; - var variableType = argument.Value.GetType(); - var friendlyTypeName = variableType.GetFriendlyTypeName(Brackets.Angle); - sb.AppendLine($"\tpublic {friendlyTypeName} {argumentName}"); - sb.AppendLine("\t{"); - sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{argumentName}\");"); - sb.AppendLine("\t}"); + foreach (var argument in arguments.Where(x => x.Key.IsValidVariableName())) + { + var argumentName = argument.Key; + var variableType = argument.Value.GetType(); + var friendlyTypeName = variableType.GetFriendlyTypeName(Brackets.Angle); + sb.AppendLine($"\tpublic {friendlyTypeName} {argumentName}"); + sb.AppendLine("\t{"); + sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{argumentName}\");"); + sb.AppendLine("\t}"); + } } sb.AppendLine("}"); diff --git a/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowInputAccessors.cs b/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowInputAccessors.cs index ae6d3008d..1fcf00b72 100644 --- a/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowInputAccessors.cs +++ b/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowInputAccessors.cs @@ -1,9 +1,12 @@ using System.Text; +using Elsa.CSharp.Extensions; using Elsa.CSharp.Notifications; +using Elsa.CSharp.Options; using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.Mediator.Contracts; using JetBrains.Annotations; +using Microsoft.Extensions.Options; namespace Elsa.CSharp.Handlers; @@ -11,13 +14,12 @@ namespace Elsa.CSharp.Handlers; /// Configures the C# evaluator with methods to access workflow variables. /// [UsedImplicitly] -public class GenerateWorkflowInputAccessors : INotificationHandler +public class GenerateWorkflowInputAccessors(IOptions options) : INotificationHandler { /// public Task HandleAsync(EvaluatingCSharp notification, CancellationToken cancellationToken) { var expressionExecutionContext = notification.Context; - var workflowInputs = expressionExecutionContext.GetWorkflowInputs().ToList(); if (!expressionExecutionContext.TryGetWorkflowExecutionContext(out var workflowExecutionContext)) return Task.CompletedTask; @@ -31,15 +33,19 @@ public class GenerateWorkflowInputAccessors : INotificationHandler(string name) => ExecutionContext.GetInput(name);"); sb.AppendLine(); - foreach (var inputDefinition in inputDefinitions) + + if (!options.Value.DisableWrappers) { - var inputName = inputDefinition.Name; - var variableType = inputDefinition.Type; - var friendlyTypeName = variableType.GetFriendlyTypeName(Brackets.Angle); - sb.AppendLine($"\tpublic {friendlyTypeName} {inputName}"); - sb.AppendLine("\t{"); - sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{inputName}\");"); - sb.AppendLine("\t}"); + foreach (var inputDefinition in inputDefinitions.Where(x => x.Name.IsValidVariableName())) + { + var inputName = inputDefinition.Name; + var variableType = inputDefinition.Type; + var friendlyTypeName = variableType.GetFriendlyTypeName(Brackets.Angle); + sb.AppendLine($"\tpublic {friendlyTypeName} {inputName}"); + sb.AppendLine("\t{"); + sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{inputName}\");"); + sb.AppendLine("\t}"); + } } sb.AppendLine("}"); diff --git a/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs b/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs index 1b4e8d216..e63ed99d5 100644 --- a/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs +++ b/src/modules/Elsa.CSharp/Handlers/GenerateWorkflowVariableAccessors.cs @@ -1,10 +1,13 @@ using System.Text; +using Elsa.CSharp.Extensions; using Elsa.CSharp.Notifications; +using Elsa.CSharp.Options; using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.Mediator.Contracts; using Humanizer; using JetBrains.Annotations; +using Microsoft.Extensions.Options; namespace Elsa.CSharp.Handlers; @@ -12,7 +15,7 @@ namespace Elsa.CSharp.Handlers; /// Configures the C# evaluator with methods to access workflow variables. /// [UsedImplicitly] -public class GenerateWorkflowVariableAccessors : INotificationHandler +public class GenerateWorkflowVariableAccessors(IOptions options) : INotificationHandler { /// public Task HandleAsync(EvaluatingCSharp notification, CancellationToken cancellationToken) @@ -28,16 +31,20 @@ public class GenerateWorkflowVariableAccessors : INotificationHandler ExecutionContext.GetVariable(name);"); sb.AppendLine("\tpublic void Set(string name, object? value) => ExecutionContext.SetVariable(name, value);"); sb.AppendLine(); - foreach (var variable in variables) + + if (!options.Value.DisableWrappers) { - var variableName = variable.Name.Pascalize(); - var variableType = variable.GetVariableType(); - var friendlyTypeName = variableType.GetFriendlyTypeName(Brackets.Angle); - sb.AppendLine($"\tpublic {friendlyTypeName} {variableName}"); - sb.AppendLine("\t{"); - sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{variableName}\");"); - sb.AppendLine($"\t\tset => Set(\"{variableName}\", value);"); - sb.AppendLine("\t}"); + foreach (var variable in variables.Where(x => x.Name.IsValidVariableName())) + { + var variableName = variable.Name.Pascalize(); + var variableType = variable.GetVariableType(); + var friendlyTypeName = variableType.GetFriendlyTypeName(Brackets.Angle); + sb.AppendLine($"\tpublic {friendlyTypeName} {variableName}"); + sb.AppendLine("\t{"); + sb.AppendLine($"\t\tget => Get<{friendlyTypeName}>(\"{variableName}\");"); + sb.AppendLine($"\t\tset => Set(\"{variableName}\", value);"); + sb.AppendLine("\t}"); + } } sb.AppendLine("}"); diff --git a/src/modules/Elsa.CSharp/Options/CSharpOptions.cs b/src/modules/Elsa.CSharp/Options/CSharpOptions.cs index afec04716..4c9d5d07d 100644 --- a/src/modules/Elsa.CSharp/Options/CSharpOptions.cs +++ b/src/modules/Elsa.CSharp/Options/CSharpOptions.cs @@ -49,6 +49,12 @@ public class CSharpOptions typeof(JsonNode).Namespace!, // System.Text.Json.Nodes typeof(IDictionary).Namespace!, // System.Collections.Generic }); + + /// + /// Disables the generation of variable wrappers. E.g. Variables.MyVariable will no longer be available for variables. Instead, you can only access variables using Variables.Get("MyVariable") and the typed Variables.Get<T>("MyVariable") function. + /// This is useful if your application requires the use of invalid JavaScript variable names. + /// + public bool DisableWrappers { get; set; } /// /// Configures the . diff --git a/src/modules/Elsa.JavaScript/Extensions/VariableNameExtensions.cs b/src/modules/Elsa.JavaScript/Extensions/VariableNameExtensions.cs new file mode 100644 index 000000000..450f63486 --- /dev/null +++ b/src/modules/Elsa.JavaScript/Extensions/VariableNameExtensions.cs @@ -0,0 +1,21 @@ +using Elsa.JavaScript.Helpers; + +namespace Elsa.JavaScript.Extensions; + +public static class VariableNameExtensions +{ + public static bool IsValidVariableName(this string name) + { + return VariableNameValidator.IsValidVariableName(name); + } + + public static bool IsInvalidVariableName(this string name) + { + return !VariableNameValidator.IsValidVariableName(name); + } + + public static IEnumerable FilterInvalidVariableNames(this IEnumerable names) + { + return names.Where(IsValidVariableName); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs b/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs index a6a5cb6f0..ee04c38b4 100644 --- a/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs +++ b/src/modules/Elsa.JavaScript/Features/JavaScriptFeature.cs @@ -13,7 +13,6 @@ using Elsa.JavaScript.Options; using Elsa.JavaScript.Providers; using Elsa.JavaScript.Services; using Elsa.JavaScript.TypeDefinitions.Contracts; -using Elsa.JavaScript.TypeDefinitions.Providers; using Elsa.JavaScript.TypeDefinitions.Services; using Elsa.Workflows; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs index 9f134433f..ab4600e19 100644 --- a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs +++ b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs @@ -1,29 +1,38 @@ using System.Dynamic; using Elsa.Expressions.Models; using Elsa.Extensions; +using Elsa.JavaScript.Extensions; using Elsa.JavaScript.Helpers; using Elsa.JavaScript.Notifications; +using Elsa.JavaScript.Options; using Elsa.Mediator.Contracts; using Elsa.Workflows.Activities; using JetBrains.Annotations; using Jint; using Jint.Native; +using Microsoft.Extensions.Options; namespace Elsa.JavaScript.Handlers; /// A handler that configures the Jint engine with workflow variables. [UsedImplicitly] -public class ConfigureEngineWithVariables : INotificationHandler, INotificationHandler +public class ConfigureEngineWithVariables(IOptions options) : INotificationHandler, INotificationHandler { /// public Task HandleAsync(EvaluatingJavaScript notification, CancellationToken cancellationToken) { + if(options.Value.DisableWrappers) + return Task.CompletedTask; + CopyVariablesIntoEngine(notification); return Task.CompletedTask; } public Task HandleAsync(EvaluatedJavaScript notification, CancellationToken cancellationToken) { + if(options.Value.DisableWrappers) + return Task.CompletedTask; + CopyVariablesIntoWorkflowExecutionContext(notification); return Task.CompletedTask; } @@ -33,7 +42,7 @@ public class ConfigureEngineWithVariables : INotificationHandler)engine.GetValue("variables").ToObject()!; - var inputNames = GetInputNames(context).Distinct().ToList(); + var inputNames = GetInputNames(context).FilterInvalidVariableNames().Distinct().ToList(); foreach (var (variableName, variableValue) in variablesContainer) { @@ -67,7 +76,7 @@ public class ConfigureEngineWithVariables : INotificationHandler)new ExpandoObject(); foreach (var variableName in variableNames) diff --git a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariablesAndInputOutputAccessors.cs b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariablesAndInputOutputAccessors.cs index f7faa1913..1db64c9a0 100644 --- a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariablesAndInputOutputAccessors.cs +++ b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariablesAndInputOutputAccessors.cs @@ -1,24 +1,31 @@ using Elsa.Expressions.Models; using Elsa.Extensions; +using Elsa.JavaScript.Extensions; +using Elsa.JavaScript.Helpers; using Elsa.JavaScript.Notifications; +using Elsa.JavaScript.Options; using Elsa.Mediator.Contracts; using Humanizer; using JetBrains.Annotations; using Jint; +using Microsoft.Extensions.Options; namespace Elsa.JavaScript.Handlers; /// A handler that configures the Jint engine with workflow input and output accessors. [UsedImplicitly] -public class ConfigureEngineWithVariablesAndInputOutputAccessors : INotificationHandler +public class ConfigureEngineWithVariablesAndInputOutputAccessors(IOptions options) : INotificationHandler { /// public async Task HandleAsync(EvaluatingJavaScript notification, CancellationToken cancellationToken) { + if(options.Value.DisableWrappers) + return; + var engine = notification.Engine; var context = notification.Context; - // The order of the next 3 lines is important. + // The order of the next 3 lines is important. CreateVariableAccessors(engine, context); CreateWorkflowInputAccessors(engine, context); await CreateActivityOutputAccessorsAsync(engine, context); @@ -26,7 +33,7 @@ public class ConfigureEngineWithVariablesAndInputOutputAccessors : INotification private void CreateVariableAccessors(Engine engine, ExpressionExecutionContext context) { - var variableNames = context.GetVariableNamesInScope().ToList(); + var variableNames = context.GetVariableNamesInScope().FilterInvalidVariableNames().ToList(); foreach (var variableName in variableNames) { @@ -43,7 +50,7 @@ public class ConfigureEngineWithVariablesAndInputOutputAccessors : INotification if (context.IsContainedWithinCompositeActivity()) return; - var inputs = context.GetWorkflowInputs().ToDictionary(x => x.Name); + var inputs = context.GetWorkflowInputs().Where(x => x.Name.IsValidVariableName()).ToDictionary(x => x.Name); if (!context.TryGetWorkflowExecutionContext(out var workflowExecutionContext)) return; @@ -62,7 +69,7 @@ public class ConfigureEngineWithVariablesAndInputOutputAccessors : INotification var activityOutputs = context.GetActivityOutputs(); await foreach (var activityOutput in activityOutputs) - foreach (var outputName in activityOutput.OutputNames) + foreach (var outputName in activityOutput.OutputNames.FilterInvalidVariableNames()) engine.SetValue($"get{outputName}From{activityOutput.ActivityName}", (Func)(() => context.GetOutput(activityOutput.ActivityId, outputName))); } } \ No newline at end of file diff --git a/src/modules/Elsa.JavaScript/Helpers/VariableNameValidator.cs b/src/modules/Elsa.JavaScript/Helpers/VariableNameValidator.cs new file mode 100644 index 000000000..9553fc9df --- /dev/null +++ b/src/modules/Elsa.JavaScript/Helpers/VariableNameValidator.cs @@ -0,0 +1,9 @@ +namespace Elsa.JavaScript.Helpers; + +public static class VariableNameValidator +{ + public static bool IsValidVariableName(string name) + { + return !string.IsNullOrWhiteSpace(name) && name.All(char.IsLetterOrDigit); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.JavaScript/Options/JintOptions.cs b/src/modules/Elsa.JavaScript/Options/JintOptions.cs index f3a664a7a..1bcc08c61 100644 --- a/src/modules/Elsa.JavaScript/Options/JintOptions.cs +++ b/src/modules/Elsa.JavaScript/Options/JintOptions.cs @@ -40,6 +40,12 @@ public class JintOptions /// If the value of ScriptCacheTimeout is null, the scripts are cached indefinitely. If a time value is specified, the scripts will be recompiled after the specified duration has elapsed. /// public TimeSpan? ScriptCacheTimeout { get; set; } = TimeSpan.FromDays(1); + + /// + /// Disables the generation of variable wrappers. E.g. getMyVariable() will no longer be available for variables. Instead, you can only access variables using getVariable("MyVariable") function. + /// This is useful if your application requires the use of invalid JavaScript variable names. + /// + public bool DisableWrappers { get; set; } /// /// Configures the Jint engine options. diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/ActivityOutputFunctionsDefinitionProvider.cs similarity index 70% rename from src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs rename to src/modules/Elsa.JavaScript/Providers/ActivityOutputFunctionsDefinitionProvider.cs index 6ca1e34bb..1cc022542 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/ActivityOutputFunctionsDefinitionProvider.cs @@ -1,25 +1,31 @@ using Elsa.Extensions; +using Elsa.JavaScript.Extensions; +using Elsa.JavaScript.Options; using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Models; using Elsa.Workflows; using Humanizer; using JetBrains.Annotations; +using Microsoft.Extensions.Options; -namespace Elsa.JavaScript.TypeDefinitions.Providers; +namespace Elsa.JavaScript.Providers; /// Produces s for common functions. [UsedImplicitly] -internal class ActivityOutputFunctionsDefinitionProvider(IActivityRegistryLookupService activityRegistryLookup) : FunctionDefinitionProvider +internal class ActivityOutputFunctionsDefinitionProvider(IActivityRegistryLookupService activityRegistryLookup, IOptions options) : FunctionDefinitionProvider { protected override async ValueTask> GetFunctionDefinitionsAsync(TypeDefinitionContext context) { + if(options.Value.DisableWrappers) + return []; + var nodes = context.WorkflowGraph.Nodes; - var activitiesWithOutputs = nodes.GetActivitiesWithOutputs(activityRegistryLookup).Where(x => x.activity.Name != null); + var activitiesWithOutputs = nodes.GetActivitiesWithOutputs(activityRegistryLookup).Where(x => x.activity.Name != null && x.activity.Name.IsValidVariableName()); var definitions = new List(); await foreach (var (activity, activityDescriptor) in activitiesWithOutputs) { - definitions.AddRange(from output in activityDescriptor.Outputs + definitions.AddRange(from output in activityDescriptor.Outputs.Where(x => x.Name.IsValidVariableName()) select output.Name.Pascalize() into outputPascalName let activityNamePascalName = activity.Name.Pascalize() diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/CommonFunctionsDefinitionProvider.cs similarity index 81% rename from src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs rename to src/modules/Elsa.JavaScript/Providers/CommonFunctionsDefinitionProvider.cs index 76f9aaf03..5b389aa42 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonFunctionsDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/CommonFunctionsDefinitionProvider.cs @@ -1,15 +1,18 @@ using Elsa.Extensions; using Elsa.JavaScript.Contracts; +using Elsa.JavaScript.Extensions; +using Elsa.JavaScript.Options; using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Models; using Humanizer; using JetBrains.Annotations; +using Microsoft.Extensions.Options; -namespace Elsa.JavaScript.TypeDefinitions.Providers; +namespace Elsa.JavaScript.Providers; /// Produces s for common functions. [UsedImplicitly] -internal class CommonFunctionsDefinitionProvider(ITypeAliasRegistry typeAliasRegistry) : FunctionDefinitionProvider +internal class CommonFunctionsDefinitionProvider(ITypeAliasRegistry typeAliasRegistry, IOptions options) : FunctionDefinitionProvider { protected override IEnumerable GetFunctionDefinitions(TypeDefinitionContext context) { @@ -124,18 +127,21 @@ internal class CommonFunctionsDefinitionProvider(ITypeAliasRegistry typeAliasReg .Parameter("value", "string") .ReturnType("string")); - // Variable getter and setters. - foreach (var variable in context.WorkflowGraph.Workflow.Variables) + if (!options.Value.DisableWrappers) { - var pascalName = variable.Name.Pascalize(); - var variableType = variable.GetVariableType(); - var typeAlias = typeAliasRegistry.TryGetAlias(variableType, out var alias) ? alias : "any"; + // Variable getter and setters. + foreach (var variable in context.WorkflowGraph.Workflow.Variables.Where(x => x.Name.IsValidVariableName())) + { + var pascalName = variable.Name.Pascalize(); + var variableType = variable.GetVariableType(); + var typeAlias = typeAliasRegistry.TryGetAlias(variableType, out var alias) ? alias : "any"; - // get{Variable}. - yield return CreateFunctionDefinition(builder => builder.Name($"get{pascalName}").ReturnType(typeAlias)); + // get{Variable}. + yield return CreateFunctionDefinition(builder => builder.Name($"get{pascalName}").ReturnType(typeAlias)); - // set{Variable}. - yield return CreateFunctionDefinition(builder => builder.Name($"set{pascalName}").Parameter("value", typeAlias)); + // set{Variable}. + yield return CreateFunctionDefinition(builder => builder.Name($"set{pascalName}").Parameter("value", typeAlias)); + } } } } \ No newline at end of file diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonTypesDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/CommonTypesDefinitionProvider.cs similarity index 92% rename from src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonTypesDefinitionProvider.cs rename to src/modules/Elsa.JavaScript/Providers/CommonTypesDefinitionProvider.cs index 33df93bb5..9b457f7e9 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/CommonTypesDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/CommonTypesDefinitionProvider.cs @@ -3,7 +3,7 @@ using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Contracts; using Elsa.JavaScript.TypeDefinitions.Models; -namespace Elsa.JavaScript.TypeDefinitions.Providers; +namespace Elsa.JavaScript.Providers; /// /// Produces s for common functions. diff --git a/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs index 29d50ed1e..bb5a8aba9 100644 --- a/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs @@ -1,18 +1,24 @@ using Elsa.JavaScript.Contracts; +using Elsa.JavaScript.Helpers; +using Elsa.JavaScript.Options; using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Models; using Elsa.Workflows.Activities; using Humanizer; using JetBrains.Annotations; +using Microsoft.Extensions.Options; namespace Elsa.JavaScript.Providers; /// Produces s for common functions. [UsedImplicitly] -internal class InputFunctionsDefinitionProvider(ITypeAliasRegistry typeAliasRegistry) : FunctionDefinitionProvider +internal class InputFunctionsDefinitionProvider(ITypeAliasRegistry typeAliasRegistry, IOptions options) : FunctionDefinitionProvider { protected override ValueTask> GetFunctionDefinitionsAsync(TypeDefinitionContext context) { + if(options.Value.DisableWrappers) + return ValueTask.FromResult>([]); + var workflow = context.WorkflowGraph.Workflow; return ValueTask.FromResult(GetFunctionDefinitionsAsync(workflow)); } @@ -20,7 +26,7 @@ internal class InputFunctionsDefinitionProvider(ITypeAliasRegistry typeAliasRegi private IEnumerable GetFunctionDefinitionsAsync(Workflow workflow) { // Input argument getters. - foreach (var input in workflow.Inputs) + foreach (var input in workflow.Inputs.Where(x => VariableNameValidator.IsValidVariableName(x.Name))) { var pascalName = input.Name.Pascalize(); var variableType = input.Type; diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/VariableTypeDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/VariableTypeDefinitionProvider.cs similarity index 96% rename from src/modules/Elsa.JavaScript/TypeDefinitions/Providers/VariableTypeDefinitionProvider.cs rename to src/modules/Elsa.JavaScript/Providers/VariableTypeDefinitionProvider.cs index a14c633c2..d56e6c255 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/VariableTypeDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/VariableTypeDefinitionProvider.cs @@ -4,7 +4,7 @@ using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Contracts; using Elsa.JavaScript.TypeDefinitions.Models; -namespace Elsa.JavaScript.TypeDefinitions.Providers; +namespace Elsa.JavaScript.Providers; /// /// Produces s for variable types. diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/WorkflowVariablesTypeDefinitionProvider.cs similarity index 67% rename from src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs rename to src/modules/Elsa.JavaScript/Providers/WorkflowVariablesTypeDefinitionProvider.cs index 59e809cff..185b730ff 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/WorkflowVariablesTypeDefinitionProvider.cs @@ -1,15 +1,21 @@ using Elsa.Extensions; +using Elsa.JavaScript.Extensions; +using Elsa.JavaScript.Options; using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Models; using JetBrains.Annotations; +using Microsoft.Extensions.Options; -namespace Elsa.JavaScript.TypeDefinitions.Providers; +namespace Elsa.JavaScript.Providers; [UsedImplicitly] -internal class WorkflowVariablesTypeDefinitionProvider : TypeDefinitionProvider +internal class WorkflowVariablesTypeDefinitionProvider(IOptions options) : TypeDefinitionProvider { protected override IEnumerable GetTypeDefinitions(TypeDefinitionContext context) { + if(options.Value.DisableWrappers) + yield break; + var variables = context.WorkflowGraph.Workflow.Variables; var workflowTypeDefinition = new TypeDefinition @@ -18,7 +24,7 @@ internal class WorkflowVariablesTypeDefinitionProvider : TypeDefinitionProvider DeclarationKeyword = "class" }; - foreach (var variable in variables) + foreach (var variable in variables.Where(x => x.Name.IsValidVariableName())) { var variableType = variable.GetVariableType(); workflowTypeDefinition.Properties.Add(new PropertyDefinition diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesVariableProvider.cs b/src/modules/Elsa.JavaScript/Providers/WorkflowVariablesVariableProvider.cs similarity index 56% rename from src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesVariableProvider.cs rename to src/modules/Elsa.JavaScript/Providers/WorkflowVariablesVariableProvider.cs index 526075931..31a9757c1 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesVariableProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/WorkflowVariablesVariableProvider.cs @@ -1,14 +1,19 @@ +using Elsa.JavaScript.Options; using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Models; using JetBrains.Annotations; +using Microsoft.Extensions.Options; -namespace Elsa.JavaScript.TypeDefinitions.Providers; +namespace Elsa.JavaScript.Providers; [UsedImplicitly] -internal class WorkflowVariablesVariableProvider : VariableDefinitionProvider +internal class WorkflowVariablesVariableProvider(IOptions options) : VariableDefinitionProvider { protected override IEnumerable GetVariableDefinitions(TypeDefinitionContext context) { + if(options.Value.DisableWrappers) + yield break; + yield return CreateVariableDefinition(x => x.Name("variables").Type("WorkflowVariables")); } } \ No newline at end of file