From d033b56d29ad1fe5905bbf33f1f2e2d797da7111 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 29 May 2021 17:11:00 +0200 Subject: [PATCH] Increase javascript intellisense coverage --- .../Extensions/ServiceCollectionExtensions.cs | 1 + .../JavaScript/ConfigureJavaScriptEngine.cs | 14 +- .../JavaScript/HttpTypeDefinitionProvider.cs | 15 ++ .../Handlers/ConfigureCronProperty.cs | 2 +- .../WebhookActivityTypeProvider.cs | 6 +- .../Attributes/ActivityOutputAttribute.cs | 5 + .../Metadata/ActivityDescriptor.cs | 6 +- ...scriptor.cs => ActivityInputDescriptor.cs} | 6 +- .../Metadata/ActivityOutputDescriptor.cs | 25 ++++ .../Models/ActivityExecutionContext.cs | 17 +-- .../Models/WorkflowExecutionContext.cs | 15 ++ .../Metadata/TypedActivityTypeDescriber.cs | 31 ++++- .../Services/WorkflowBlueprintMaterializer.cs | 2 +- .../elsa-designer-tree/elsa-designer-tree.tsx | 2 +- .../elsa-workflow-blueprint-viewer-screen.tsx | 2 +- .../elsa-activity-editor-modal.tsx | 12 +- ...elsa-workflow-definition-editor-screen.tsx | 1 + .../elsa-workflow-instance-viewer-screen.tsx | 2 +- .../src/models/domain.ts | 2 +- .../CollectingTypeScriptDefinitionTypes.cs | 22 --- .../Extensions/JObjectExtensions.cs | 31 +++++ .../JavaScriptServiceCollectionExtensions.cs | 11 +- .../Handlers/ConfigureJavaScriptEngine.cs | 131 ++++++++++++++++-- .../IsExternalInit.cs | 17 +++ .../Services/ITypeDefinitionProvider.cs | 11 +- .../Services/TypeDefinitionProvider.cs | 16 +++ .../Services/TypeScriptDefinitionService.cs | 87 +++--------- .../CommonTypesTypeDefinitionProvider.cs | 28 ++++ .../Typings/EnumTypeDefinitionProvider.cs | 6 +- .../EnumerableTypeDefinitionProvider.cs | 10 +- .../PrimitiveTypeDefinitionProvider.cs | 6 +- .../WorkflowContextTypeDefinitionProvider.cs | 18 +++ ...WorkflowVariablesTypeDefinitionProvider.cs | 21 +++ 33 files changed, 423 insertions(+), 158 deletions(-) create mode 100644 src/activities/Elsa.Activities.Http/JavaScript/HttpTypeDefinitionProvider.cs rename src/core/Elsa.Abstractions/Metadata/{ActivityPropertyDescriptor.cs => ActivityInputDescriptor.cs} (91%) create mode 100644 src/core/Elsa.Abstractions/Metadata/ActivityOutputDescriptor.cs delete mode 100644 src/scripting/Elsa.Scripting.JavaScript/Events/CollectingTypeScriptDefinitionTypes.cs create mode 100644 src/scripting/Elsa.Scripting.JavaScript/Extensions/JObjectExtensions.cs create mode 100644 src/scripting/Elsa.Scripting.JavaScript/IsExternalInit.cs create mode 100644 src/scripting/Elsa.Scripting.JavaScript/Services/TypeDefinitionProvider.cs create mode 100644 src/scripting/Elsa.Scripting.JavaScript/Typings/CommonTypesTypeDefinitionProvider.cs create mode 100644 src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowContextTypeDefinitionProvider.cs create mode 100644 src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowVariablesTypeDefinitionProvider.cs diff --git a/src/activities/Elsa.Activities.Http/Extensions/ServiceCollectionExtensions.cs b/src/activities/Elsa.Activities.Http/Extensions/ServiceCollectionExtensions.cs index 03eed0545..e873f6deb 100644 --- a/src/activities/Elsa.Activities.Http/Extensions/ServiceCollectionExtensions.cs +++ b/src/activities/Elsa.Activities.Http/Extensions/ServiceCollectionExtensions.cs @@ -44,6 +44,7 @@ namespace Microsoft.Extensions.DependencyInjection .AddHttpContextAccessor() .AddNotificationHandlers(typeof(ConfigureJavaScriptEngine)) .AddLiquidFilter("signal_url") + .AddJavaScriptTypeDefinitionProvider() .AddDataProtection(); return services; diff --git a/src/activities/Elsa.Activities.Http/JavaScript/ConfigureJavaScriptEngine.cs b/src/activities/Elsa.Activities.Http/JavaScript/ConfigureJavaScriptEngine.cs index d27069dda..cd241266c 100644 --- a/src/activities/Elsa.Activities.Http/JavaScript/ConfigureJavaScriptEngine.cs +++ b/src/activities/Elsa.Activities.Http/JavaScript/ConfigureJavaScriptEngine.cs @@ -3,13 +3,14 @@ using System.Threading; using System.Threading.Tasks; using Elsa.Activities.Http.Extensions; using Elsa.Activities.Http.Services; +using Elsa.Scripting.JavaScript.Events; using Elsa.Scripting.JavaScript.Messages; using MediatR; using Microsoft.AspNetCore.Http; namespace Elsa.Activities.Http.JavaScript { - public class ConfigureJavaScriptEngine : INotificationHandler + public class ConfigureJavaScriptEngine : INotificationHandler, INotificationHandler { private readonly IAbsoluteUrlProvider _absoluteUrlProvider; private readonly IHttpContextAccessor _httpContextAccessor; @@ -42,5 +43,16 @@ namespace Elsa.Activities.Http.JavaScript return Task.CompletedTask; } + + public Task Handle(RenderingTypeScriptDefinitions notification, CancellationToken cancellationToken) + { + var output = notification.Output; + + output.AppendLine("declare function queryString(name: string): string;"); + output.AppendLine("declare function absoluteUrl(url: string): string;"); + output.AppendLine("declare function signalUrl(signal: string): string;"); + + return Task.CompletedTask; + } } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/JavaScript/HttpTypeDefinitionProvider.cs b/src/activities/Elsa.Activities.Http/JavaScript/HttpTypeDefinitionProvider.cs new file mode 100644 index 000000000..7a21c79c0 --- /dev/null +++ b/src/activities/Elsa.Activities.Http/JavaScript/HttpTypeDefinitionProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using Elsa.Activities.Http.Models; +using Elsa.Scripting.JavaScript.Services; + +namespace Elsa.Activities.Http.JavaScript +{ + public class HttpTypeDefinitionProvider : TypeDefinitionProvider + { + public override IEnumerable CollectTypes(TypeDefinitionContext context) + { + return new[] { typeof(HttpRequestModel) }; + } + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Temporal.Quartz/Handlers/ConfigureCronProperty.cs b/src/activities/Elsa.Activities.Temporal.Quartz/Handlers/ConfigureCronProperty.cs index 128644191..22eb32d65 100644 --- a/src/activities/Elsa.Activities.Temporal.Quartz/Handlers/ConfigureCronProperty.cs +++ b/src/activities/Elsa.Activities.Temporal.Quartz/Handlers/ConfigureCronProperty.cs @@ -15,7 +15,7 @@ namespace Elsa.Activities.Temporal.Quartz.Handlers if (activityType.Type != typeof(Cron)) return Task.CompletedTask; - var cronExpressionProperty = notification.ActivityDescriptor.Properties.First(x => x.Name == nameof(Cron.CronExpression)); + var cronExpressionProperty = notification.ActivityDescriptor.InputProperties.First(x => x.Name == nameof(Cron.CronExpression)); cronExpressionProperty.DefaultValue = "0 * 0 ? * * *"; cronExpressionProperty.Hint = "Specify a Quartz CRON expression. Go to https://www.freeformatter.com/cron-expression-generator-quartz.html to generate valid Quartz cron expressions."; diff --git a/src/activities/Elsa.Activities.Webhooks/ActivityTypes/WebhookActivityTypeProvider.cs b/src/activities/Elsa.Activities.Webhooks/ActivityTypes/WebhookActivityTypeProvider.cs index d24adb36a..d84fa533f 100644 --- a/src/activities/Elsa.Activities.Webhooks/ActivityTypes/WebhookActivityTypeProvider.cs +++ b/src/activities/Elsa.Activities.Webhooks/ActivityTypes/WebhookActivityTypeProvider.cs @@ -56,12 +56,12 @@ namespace Elsa.Activities.Webhooks.ActivityTypes Category = WebhookActivityCategory, Outcomes = new[] { OutcomeNames.Done }, Traits = ActivityTraits.Trigger, - Properties = new[] + InputProperties = new[] { - new ActivityPropertyDescriptor( + new ActivityInputDescriptor( nameof(HttpEndpoint.Methods), typeof(HashSet), - ActivityPropertyUIHints.Dropdown, + ActivityInputUIHints.Dropdown, "Request Method", "Specify what request method this webhook should handle. Leave empty to handle both GET and POST requests", new[] { "", "GET", "POST" }, diff --git a/src/core/Elsa.Abstractions/Attributes/ActivityOutputAttribute.cs b/src/core/Elsa.Abstractions/Attributes/ActivityOutputAttribute.cs index 13766257d..f3768af0e 100644 --- a/src/core/Elsa.Abstractions/Attributes/ActivityOutputAttribute.cs +++ b/src/core/Elsa.Abstractions/Attributes/ActivityOutputAttribute.cs @@ -5,6 +5,11 @@ namespace Elsa.Attributes [AttributeUsage(AttributeTargets.Property)] public class ActivityOutputAttribute : Attribute { + /// + /// The technical name of the activity property. + /// + public string? Name { get; set; } + /// /// A brief description about this property for workflow tooling to use when displaying activity editors. /// diff --git a/src/core/Elsa.Abstractions/Metadata/ActivityDescriptor.cs b/src/core/Elsa.Abstractions/Metadata/ActivityDescriptor.cs index 13f9b0b9e..0bfba28da 100644 --- a/src/core/Elsa.Abstractions/Metadata/ActivityDescriptor.cs +++ b/src/core/Elsa.Abstractions/Metadata/ActivityDescriptor.cs @@ -8,7 +8,8 @@ namespace Elsa.Metadata Category = "Miscellaneous"; Traits = ActivityTraits.Action; DisplayName = "Activity"; - Properties = new ActivityPropertyDescriptor[0]; + InputProperties = new ActivityInputDescriptor[0]; + OutputProperties = new ActivityOutputDescriptor[0]; Outcomes = new string[0]; } @@ -18,6 +19,7 @@ namespace Elsa.Metadata public string Category { get; set; } public ActivityTraits Traits { get; set; } public string[] Outcomes { get; set; } - public ActivityPropertyDescriptor[] Properties { get; set; } + public ActivityInputDescriptor[] InputProperties { get; set; } + public ActivityOutputDescriptor[] OutputProperties { get; set; } } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Metadata/ActivityPropertyDescriptor.cs b/src/core/Elsa.Abstractions/Metadata/ActivityInputDescriptor.cs similarity index 91% rename from src/core/Elsa.Abstractions/Metadata/ActivityPropertyDescriptor.cs rename to src/core/Elsa.Abstractions/Metadata/ActivityInputDescriptor.cs index f21809b2f..4deb10cc9 100644 --- a/src/core/Elsa.Abstractions/Metadata/ActivityPropertyDescriptor.cs +++ b/src/core/Elsa.Abstractions/Metadata/ActivityInputDescriptor.cs @@ -4,13 +4,13 @@ using System.Linq; namespace Elsa.Metadata { - public class ActivityPropertyDescriptor + public class ActivityInputDescriptor { - public ActivityPropertyDescriptor() + public ActivityInputDescriptor() { } - public ActivityPropertyDescriptor( + public ActivityInputDescriptor( string name, Type type, string uiHint, diff --git a/src/core/Elsa.Abstractions/Metadata/ActivityOutputDescriptor.cs b/src/core/Elsa.Abstractions/Metadata/ActivityOutputDescriptor.cs new file mode 100644 index 000000000..fa73272b1 --- /dev/null +++ b/src/core/Elsa.Abstractions/Metadata/ActivityOutputDescriptor.cs @@ -0,0 +1,25 @@ +using System; + +namespace Elsa.Metadata +{ + public class ActivityOutputDescriptor + { + public ActivityOutputDescriptor() + { + } + + public ActivityOutputDescriptor( + string name, + Type type, + string? hint = default) + { + Name = name; + Type = type; + Hint = hint; + } + + public string Name { get; set; } = default!; + public Type Type { get; set; } = default!; + public string? Hint { get; set; } + } +} \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Services/Models/ActivityExecutionContext.cs b/src/core/Elsa.Abstractions/Services/Models/ActivityExecutionContext.cs index 829e33002..987c9e90d 100644 --- a/src/core/Elsa.Abstractions/Services/Models/ActivityExecutionContext.cs +++ b/src/core/Elsa.Abstractions/Services/Models/ActivityExecutionContext.cs @@ -164,23 +164,8 @@ namespace Elsa.Services.Models public void SetWorkflowContext(object? value) => WorkflowExecutionContext.SetWorkflowContext(value); public object? GetWorkflowContext() => WorkflowExecutionContext.GetWorkflowContext(); public T GetWorkflowContext() => WorkflowExecutionContext.GetWorkflowContext(); - public JObject GetActivityData() => GetActivityData(ActivityId); - - public JObject GetActivityData(string activityId) - { - var activityData = WorkflowInstance.ActivityData; - var state = activityData.ContainsKey(activityId) ? activityData[activityId] : default; - - if (state != null) - return state; - - state = new JObject(); - activityData[activityId] = state; - - return state; - } - + public JObject GetActivityData(string activityId) => WorkflowExecutionContext.GetActivityData(activityId); public void Fault(Exception exception) => WorkflowExecutionContext.Fault(exception, ActivityId, Input, Resuming); } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs b/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs index dae078d7c..e585d8bec 100644 --- a/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs +++ b/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs @@ -8,6 +8,7 @@ using Elsa.Models; using MediatR; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using NodaTime; using Rebus.Extensions; @@ -205,6 +206,20 @@ namespace Elsa.Services.Models public void SetWorkflowContext(object? value) => WorkflowContext = value; public object? GetWorkflowContext() => WorkflowContext; public T GetWorkflowContext() => (T) WorkflowContext!; + + public JObject GetActivityData(string activityId) + { + var activityData = WorkflowInstance.ActivityData; + var state = activityData.ContainsKey(activityId) ? activityData[activityId] : default; + + if (state != null) + return state; + + state = new JObject(); + activityData[activityId] = state; + + return state; + } /// /// Remove empty activity data to save on document size. diff --git a/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs b/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs index abb65e655..efab72714 100644 --- a/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs +++ b/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs @@ -29,7 +29,9 @@ namespace Elsa.Metadata var category = activityAttribute?.Category ?? "Miscellaneous"; var traits = activityAttribute?.Traits ?? ActivityTraits.Action; var outcomes = activityAttribute?.Outcomes ?? new[] { OutcomeNames.Done }; - var properties = DescribeProperties(activityType); + var properties = activityType.GetProperties(); + var inputProperties = DescribeInputProperties(properties); + var outputProperties = DescribeOutputProperties(properties); return new ActivityDescriptor { @@ -38,15 +40,14 @@ namespace Elsa.Metadata Description = description, Category = category, Traits = traits, - Properties = properties.ToArray(), + InputProperties = inputProperties.ToArray(), + OutputProperties = outputProperties.ToArray(), Outcomes = outcomes, }; } - private IEnumerable DescribeProperties(Type activityType) + private IEnumerable DescribeInputProperties(IEnumerable properties) { - var properties = activityType.GetProperties(); - foreach (var propertyInfo in properties) { var activityPropertyAttribute = propertyInfo.GetCustomAttribute(); @@ -54,7 +55,7 @@ namespace Elsa.Metadata if (activityPropertyAttribute == null) continue; - yield return new ActivityPropertyDescriptor + yield return new ActivityInputDescriptor ( (activityPropertyAttribute.Name ?? propertyInfo.Name).Pascalize(), propertyInfo.PropertyType, @@ -69,5 +70,23 @@ namespace Elsa.Metadata ); } } + + private IEnumerable DescribeOutputProperties(IEnumerable properties) + { + foreach (var propertyInfo in properties) + { + var activityPropertyAttribute = propertyInfo.GetCustomAttribute(); + + if (activityPropertyAttribute == null) + continue; + + yield return new ActivityOutputDescriptor + ( + (activityPropertyAttribute.Name ?? propertyInfo.Name).Pascalize(), + propertyInfo.PropertyType, + activityPropertyAttribute.Hint + ); + } + } } } \ No newline at end of file diff --git a/src/core/Elsa.Core/Services/WorkflowBlueprintMaterializer.cs b/src/core/Elsa.Core/Services/WorkflowBlueprintMaterializer.cs index fa2333d68..c15b150f6 100644 --- a/src/core/Elsa.Core/Services/WorkflowBlueprintMaterializer.cs +++ b/src/core/Elsa.Core/Services/WorkflowBlueprintMaterializer.cs @@ -74,7 +74,7 @@ namespace Elsa.Services { var activityType = await _activityTypeService.GetActivityTypeAsync(activityDefinition.Type, cancellationToken); var activityDescriptor = activityType.Describe(); - var propertyDescriptors = activityDescriptor.Properties; + var propertyDescriptors = activityDescriptor.InputProperties; foreach (var property in activityDefinition.Properties) { diff --git a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx index 9070c5701..f988c238b 100644 --- a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx +++ b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx @@ -166,7 +166,7 @@ export class ElsaWorkflowDesigner { properties: [], }; - for (const property of activityDescriptor.properties) { + for (const property of activityDescriptor.inputProperties) { activity.properties[property.name] = { syntax: '', expression: '', diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-blueprint-viewer/elsa-workflow-blueprint-viewer-screen/elsa-workflow-blueprint-viewer-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-blueprint-viewer/elsa-workflow-blueprint-viewer-screen/elsa-workflow-blueprint-viewer-screen.tsx index a4ea8180b..e6c4878ec 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-blueprint-viewer/elsa-workflow-blueprint-viewer-screen/elsa-workflow-blueprint-viewer-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-blueprint-viewer/elsa-workflow-blueprint-viewer-screen/elsa-workflow-blueprint-viewer-screen.tsx @@ -111,7 +111,7 @@ export class ElsaWorkflowBlueprintViewerScreen { const activityDescriptors: Array = state.activityDescriptors; const activityDescriptor = activityDescriptors.find(x => x.type == source.type); const properties: Array = collection.map(source.properties.data, (value, key) => { - const propertyDescriptor = activityDescriptor.properties.find(x => x.name == key); + const propertyDescriptor = activityDescriptor.inputProperties.find(x => x.name == key); const defaultSyntax = propertyDescriptor.defaultSyntax || SyntaxNames.Literal; const expressions = {}; expressions[defaultSyntax] = value; diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx index 4c5a921f8..2d4fdd6db 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx @@ -37,7 +37,7 @@ export class ElsaActivityEditorModal { updateActivity(formData: FormData) { const activity = this.activityModel; const activityDescriptor = this.activityDescriptor; - const properties: Array = activityDescriptor.properties; + const properties: Array = activityDescriptor.inputProperties; for (const property of properties) propertyDisplayManager.update(activity, property, formData); @@ -62,9 +62,9 @@ export class ElsaActivityEditorModal { } componentWillRender(){ - const activityDescriptor = this.activityDescriptor || {displayName: '', type: '', outcomes: [], category: '', traits: 0, browsable: false, properties: [], description: ''}; - const propertyCategories = activityDescriptor.properties.filter(x => x.category).map(x => x.category).distinct(); - const defaultProperties = activityDescriptor.properties.filter(x => !x.category || x.category.length == 0); + const activityDescriptor: ActivityDescriptor = this.activityDescriptor || {displayName: '', type: '', outcomes: [], category: '', traits: 0, browsable: false, inputProperties: [], description: ''}; + const propertyCategories = activityDescriptor.inputProperties.filter(x => x.category).map(x => x.category).distinct(); + const defaultProperties = activityDescriptor.inputProperties.filter(x => !x.category || x.category.length == 0); let tabs: Array = []; if(defaultProperties.length > 0) { @@ -93,7 +93,7 @@ export class ElsaActivityEditorModal { render() { const renderProps = this.renderProps; - const activityDescriptor = renderProps.activityDescriptor; + const activityDescriptor: ActivityDescriptor = renderProps.activityDescriptor; const propertyCategories = renderProps.propertyCategories; const tabs = renderProps.tabs; const selectedTab = renderProps.selectedTab; @@ -211,7 +211,7 @@ export class ElsaActivityEditorModal { } renderCategoryTabs(activityModel: ActivityModel, activityDescriptor: ActivityDescriptor, categories: Array) { - const propertyDescriptors: Array = activityDescriptor.properties; + const propertyDescriptors: Array = activityDescriptor.inputProperties; return ( categories.map(category => { diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx index 37b91ac3e..3aba2d026 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx @@ -267,6 +267,7 @@ export class ElsaWorkflowDefinitionEditorScreen { const activityDescriptors: Array = state.activityDescriptors; const activityDescriptor = activityDescriptors.find(x => x.type == source.type); + debugger; return { activityId: source.activityId, description: source.description, diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-viewer/elsa-workflow-instance-viewer-screen/elsa-workflow-instance-viewer-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-viewer/elsa-workflow-instance-viewer-screen/elsa-workflow-instance-viewer-screen.tsx index cf7ee741d..4bc6f20fb 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-viewer/elsa-workflow-instance-viewer-screen/elsa-workflow-instance-viewer-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-instance-viewer/elsa-workflow-instance-viewer-screen/elsa-workflow-instance-viewer-screen.tsx @@ -148,7 +148,7 @@ export class ElsaWorkflowInstanceViewerScreen { const activityDescriptors: Array = state.activityDescriptors; const activityDescriptor = activityDescriptors.find(x => x.type == source.type); const properties: Array = collection.map(source.properties.data, (value, key) => { - const propertyDescriptor = activityDescriptor.properties.find(x => x.name == key); + const propertyDescriptor = activityDescriptor.inputProperties.find(x => x.name == key); const defaultSyntax = propertyDescriptor.defaultSyntax || SyntaxNames.Literal; const expressions = {}; expressions[defaultSyntax] = value; diff --git a/src/designer/elsa-workflows-studio/src/models/domain.ts b/src/designer/elsa-workflows-studio/src/models/domain.ts index d200edd8d..976b6644b 100644 --- a/src/designer/elsa-workflows-studio/src/models/domain.ts +++ b/src/designer/elsa-workflows-studio/src/models/domain.ts @@ -259,7 +259,7 @@ export interface ActivityDescriptor { traits: ActivityTraits; outcomes: Array; browsable: boolean; - properties: Array; + inputProperties: Array; } export interface ActivityPropertyDescriptor { diff --git a/src/scripting/Elsa.Scripting.JavaScript/Events/CollectingTypeScriptDefinitionTypes.cs b/src/scripting/Elsa.Scripting.JavaScript/Events/CollectingTypeScriptDefinitionTypes.cs deleted file mode 100644 index a3ca0fbc3..000000000 --- a/src/scripting/Elsa.Scripting.JavaScript/Events/CollectingTypeScriptDefinitionTypes.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using Elsa.Models; -using MediatR; - -namespace Elsa.Scripting.JavaScript.Events -{ - public class CollectingTypeScriptDefinitionTypes : INotification - { - internal CollectingTypeScriptDefinitionTypes(WorkflowDefinition? workflowDefinition, Action> collectTypes) - { - WorkflowDefinition = workflowDefinition; - CollectTypes = collectTypes; - } - - private Action> CollectTypes { get; } - public WorkflowDefinition? WorkflowDefinition { get; } - - public void CollectType() => CollectType(typeof(T)); - public void CollectType(Type type) => CollectTypes(new[] { type }); - } -} \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Extensions/JObjectExtensions.cs b/src/scripting/Elsa.Scripting.JavaScript/Extensions/JObjectExtensions.cs new file mode 100644 index 000000000..613e62739 --- /dev/null +++ b/src/scripting/Elsa.Scripting.JavaScript/Extensions/JObjectExtensions.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; + +namespace Elsa.Scripting.JavaScript.Extensions +{ + public static class JObjectExtensions + { + public static IDictionary ToDictionary(this JObject @object) + { + var result = @object.ToObject>()!; + + var jObjectKeys = (from r in result + let key = r.Key + let value = r.Value + where value != null && value.GetType() == typeof(JObject) + select key).ToList(); + + var jArrayKeys = (from r in result + let key = r.Key + let value = r.Value + where value != null && value.GetType() == typeof(JArray) + select key).ToList(); + + jArrayKeys.ForEach(key => result[key] = ((JArray) result[key]).Values().Select(x => ((JValue) x).Value).ToArray()); + jObjectKeys.ForEach(key => result[key] = ToDictionary((JObject) result[key])); + + return result; + } + } +} \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Extensions/JavaScriptServiceCollectionExtensions.cs b/src/scripting/Elsa.Scripting.JavaScript/Extensions/JavaScriptServiceCollectionExtensions.cs index 87fd4454a..092d57a70 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Extensions/JavaScriptServiceCollectionExtensions.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Extensions/JavaScriptServiceCollectionExtensions.cs @@ -15,16 +15,21 @@ namespace Microsoft.Extensions.DependencyInjection { return services .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() .AddScoped() .AddTransient(s => new JintEvaluationResultConverterFactory(s).GetConverter()) .AddTransient(s => new EnumerableResultConverter(default)) .TryAddProvider(ServiceLifetime.Scoped) + .AddJavaScriptTypeDefinitionProvider() + .AddJavaScriptTypeDefinitionProvider() + .AddJavaScriptTypeDefinitionProvider() + .AddJavaScriptTypeDefinitionProvider() + .AddJavaScriptTypeDefinitionProvider() + .AddJavaScriptTypeDefinitionProvider() .AddNotificationHandlers(typeof(JavaScriptServiceCollectionExtensions)); } + public static IServiceCollection AddJavaScriptTypeDefinitionProvider(this IServiceCollection services) where T: class, ITypeDefinitionProvider => services.AddScoped(); + public static IServiceCollection WithJavaScriptOptions(this IServiceCollection services, Action configureOptions) { services.Configure(configureOptions); diff --git a/src/scripting/Elsa.Scripting.JavaScript/Handlers/ConfigureJavaScriptEngine.cs b/src/scripting/Elsa.Scripting.JavaScript/Handlers/ConfigureJavaScriptEngine.cs index c91e268ce..eca03c8f2 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Handlers/ConfigureJavaScriptEngine.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Handlers/ConfigureJavaScriptEngine.cs @@ -1,8 +1,15 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Reflection; +using System.Text; using System.Threading; using System.Threading.Tasks; +using AutoMapper.Internal; +using Elsa.Attributes; +using Elsa.Scripting.JavaScript.Events; +using Elsa.Scripting.JavaScript.Extensions; using Elsa.Scripting.JavaScript.Messages; using Elsa.Services; using Elsa.Services.Models; @@ -10,20 +17,21 @@ using Jint; using Jint.Runtime.Interop; using MediatR; using Microsoft.Extensions.Configuration; -using Newtonsoft.Json.Linq; using NodaTime; namespace Elsa.Scripting.JavaScript.Handlers { - public class ConfigureJavaScriptEngine : INotificationHandler + public class ConfigureJavaScriptEngine : INotificationHandler, INotificationHandler { private readonly IConfiguration _configuration; + private readonly IActivityTypeService _activityTypeService; - public ConfigureJavaScriptEngine(IConfiguration configuration) + public ConfigureJavaScriptEngine(IConfiguration configuration, IActivityTypeService activityTypeService) { _configuration = configuration; + _activityTypeService = activityTypeService; } - + public Task Handle(EvaluatingJavaScriptExpression notification, CancellationToken cancellationToken) { var activityExecutionContext = notification.ActivityExecutionContext; @@ -57,48 +65,150 @@ namespace Elsa.Scripting.JavaScript.Handlers engine.SetValue("currentCulture", CultureInfo.InvariantCulture); engine.SetValue("workflowContext", activityExecutionContext.GetWorkflowContext()); - // NodaTime types. + // Types. RegisterType(engine); RegisterType(engine); RegisterType(engine); RegisterType(engine); RegisterType(engine); RegisterType(engine); + RegisterType(engine); + RegisterType(engine); + RegisterType(engine); + // Workflow variables. var variables = workflowExecutionContext.GetMergedVariables(); - // Add workflow variables. foreach (var variable in variables.Data) engine.SetValue(variable.Key, variable.Value); // TODO: Deprecated. Remove with next breaking version. - // Add activity outputs. + // Activity outputs. foreach (var activity in workflowBlueprint.Activities.Where(x => x.Name is not null and not "" && workflowInstance.ActivityOutput.ContainsKey(x.Id))) { var output = new { Output = workflowInstance.ActivityOutput[activity.Id!] }; engine.SetValue(activity.Name, output); } + // Named activities. + foreach (var activity in workflowBlueprint.Activities.Where(x => x.Name is not null)) + { + var state = activityExecutionContext.GetActivityData(activity.Id); + var dictionary = state.ToDictionary(); + + engine.SetValue(activity.Name, dictionary); + } + return Task.CompletedTask; } + public async Task Handle(RenderingTypeScriptDefinitions notification, CancellationToken cancellationToken) + { + var output = notification.Output; + + output.AppendLine("declare function guid(): string"); + output.AppendLine("declare function parseGuid(text: string): Guid"); + output.AppendLine("declare function setVariable(name: string, value?: any): void;"); + output.AppendLine("declare function getVariable(name: string): any;"); + output.AppendLine("declare function getConfig(section: string): any;"); + output.AppendLine("declare function isNullOrWhiteSpace(text: string): boolean;"); + output.AppendLine("declare function isNullOrEmpty(text: string): boolean;"); + output.AppendLine("declare function getWorkflowDefinitionIdByName(name: string): string;"); + output.AppendLine("declare function getWorkflowDefinitionIdByTag(tag: string): string;"); + output.AppendLine("declare function getActivity(idOrName: string): any;"); + output.AppendLine("declare function getInboundActivity(): any;"); + + output.AppendLine("declare const activityExecutionContext: ActivityExecutionContext;"); + output.AppendLine("declare const workflowExecutionContext: WorkflowExecutionContext;"); + output.AppendLine("declare const workflowInstance: WorkflowInstance;"); + output.AppendLine("declare const workflowInstanceId: string;"); + output.AppendLine("declare const workflowDefinitionId: string;"); + output.AppendLine("declare const workflowDefinitionVersion: number;"); + output.AppendLine("declare const correlationId: string;"); + output.AppendLine("declare const currentCulture: CultureInfo;"); + + var workflowDefinition = notification.WorkflowDefinition; + + if (workflowDefinition != null) + { + // Workflow Context + var contextType = workflowDefinition.ContextOptions?.ContextType; + + if (contextType == null) + return; + + var workflowContextTypeScriptType = notification.GetTypeScriptType(contextType); + output.AppendLine($"declare const workflowContext: {workflowContextTypeScriptType}"); + + // Workflow Variables. + foreach (var variable in workflowDefinition.Variables!.Data) + { + var variableType = variable.Value?.GetType() ?? typeof(object); + var typeScriptType = notification.GetTypeScriptType(variableType); + output.AppendLine($"declare const {variable.Key}: {typeScriptType}"); + } + + // Named Activities. + var namedActivities = workflowDefinition.Activities.Where(x => x.Name is not null).ToList(); + var activityTypeNames = namedActivities.Select(x => x.Type).Distinct().ToList(); + var activityTypes = await Task.WhenAll(activityTypeNames.Select(async activityTypeName => (activityTypeName, await _activityTypeService.GetActivityTypeAsync(activityTypeName, cancellationToken)))); + var activityTypeDictionary = activityTypes.ToDictionary(x => x.activityTypeName, x => x.Item2); + + foreach (var activityType in activityTypeDictionary.Values) + RenderActivityTypeDeclaration(activityType, output); + + foreach (var activity in namedActivities) + { + var activityType = activityTypeDictionary[activity.Type]; + var typeScriptType = activityType.TypeName; + output.AppendLine($"declare const {activity.Name}: {typeScriptType}"); + } + } + + void RenderActivityTypeDeclaration(ActivityType type, StringBuilder writer) + { + var typeName = type.TypeName; + var descriptor = type.Describe(); + var inputProperties = descriptor.InputProperties; + var outputProperties = descriptor.OutputProperties; + + writer.AppendLine($"declare interface {typeName} {{"); + + foreach (var property in inputProperties) + { + var typeScriptType = notification.GetTypeScriptType(property.Type); + var propertyName = property.Name; + writer.AppendLine($"{propertyName}: {typeScriptType};"); + } + + foreach (var property in outputProperties) + { + var typeScriptType = notification.GetTypeScriptType(property.Type); + var propertyName = property.Name; + writer.AppendLine($"{propertyName}: {typeScriptType};"); + } + + writer.AppendLine("}"); + } + } + private string? GetWorkflowDefinitionIdByTag(ActivityExecutionContext activityExecutionContext, string tag) => GetWorkflowDefinitionId(activityExecutionContext, x => string.Equals(x.Tag, tag, StringComparison.OrdinalIgnoreCase)); private string? GetWorkflowDefinitionIdByName(ActivityExecutionContext activityExecutionContext, string name) => GetWorkflowDefinitionId(activityExecutionContext, x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); - + private string? GetWorkflowDefinitionId(ActivityExecutionContext activityExecutionContext, Func filter) { var workflowRegistry = activityExecutionContext.GetService(); var workflowBlueprint = workflowRegistry.FindAsync(filter).Result; return workflowBlueprint?.Id; } - + private object? GetActivityModel(ActivityExecutionContext context, string idOrName) { var workflowExecutionContext = context.WorkflowExecutionContext; var activity = workflowExecutionContext.GetActivityBlueprintByName(idOrName) ?? workflowExecutionContext.GetActivityBlueprintById(idOrName); return activity == null ? null : workflowExecutionContext.WorkflowInstance.ActivityData[activity.Id]; } - + private object? GetInboundActivityModel(ActivityExecutionContext context) { var inboundActivityId = context.WorkflowExecutionContext.GetInboundActivityPath(context.ActivityId).FirstOrDefault(); @@ -106,5 +216,6 @@ namespace Elsa.Scripting.JavaScript.Handlers } private void RegisterType(Engine engine) => engine.SetValue(typeof(T).Name, TypeReference.CreateTypeReference(engine, typeof(T))); + private void RegisterType(Type type, Engine engine) => engine.SetValue(type.Name, TypeReference.CreateTypeReference(engine, type)); } } \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/IsExternalInit.cs b/src/scripting/Elsa.Scripting.JavaScript/IsExternalInit.cs new file mode 100644 index 000000000..475dd51b6 --- /dev/null +++ b/src/scripting/Elsa.Scripting.JavaScript/IsExternalInit.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; + +// ReSharper disable once CheckNamespace +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Services/ITypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Services/ITypeDefinitionProvider.cs index 7012949c8..a92ce9d58 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Services/ITypeDefinitionProvider.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Services/ITypeDefinitionProvider.cs @@ -1,10 +1,17 @@ using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; namespace Elsa.Scripting.JavaScript.Services { public interface ITypeDefinitionProvider { - bool SupportsType(Type type); - string GetTypeDefinition(Type type); + bool SupportsType(TypeDefinitionContext context, Type type); + string GetTypeDefinition(TypeDefinitionContext context, Type type); + ValueTask> CollectTypesAsync(TypeDefinitionContext context, CancellationToken cancellationToken = default); } + + public record TypeDefinitionContext(WorkflowDefinition? WorkflowDefinition, string? context); } \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Services/TypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Services/TypeDefinitionProvider.cs new file mode 100644 index 000000000..da87d9b5f --- /dev/null +++ b/src/scripting/Elsa.Scripting.JavaScript/Services/TypeDefinitionProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Elsa.Scripting.JavaScript.Services +{ + public abstract class TypeDefinitionProvider : ITypeDefinitionProvider + { + public virtual bool SupportsType(TypeDefinitionContext context, Type type) => false; + public virtual string GetTypeDefinition(TypeDefinitionContext context, Type type) => "any"; + public virtual ValueTask> CollectTypesAsync(TypeDefinitionContext context, CancellationToken cancellationToken = default) => new(CollectTypes(context)); + public virtual IEnumerable CollectTypes(TypeDefinitionContext context) => Enumerable.Empty(); + } +} \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Services/TypeScriptDefinitionService.cs b/src/scripting/Elsa.Scripting.JavaScript/Services/TypeScriptDefinitionService.cs index 9b0fa1651..09caecaba 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Services/TypeScriptDefinitionService.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Services/TypeScriptDefinitionService.cs @@ -9,7 +9,6 @@ using AutoMapper.Internal; using Elsa.Models; using Elsa.Scripting.JavaScript.Events; using MediatR; -using NodaTime; namespace Elsa.Scripting.JavaScript.Services { @@ -27,79 +26,40 @@ namespace Elsa.Scripting.JavaScript.Services public async Task GenerateTypeScriptDefinitionsAsync(WorkflowDefinition? workflowDefinition = default, string? context = default, CancellationToken cancellationToken = default) { var builder = new StringBuilder(); - var types = await CollectTypesAsync(workflowDefinition, cancellationToken); + var providerContext = new TypeDefinitionContext(workflowDefinition, context); + var types = await CollectTypesAsync(providerContext, cancellationToken); // Render type declarations for anything except those listed in TypeConverters. foreach (var type in types) { - var shouldRenderDeclaration = ShouldRenderTypeDeclaration(type); + var shouldRenderDeclaration = ShouldRenderTypeDeclaration(providerContext, type); if (shouldRenderDeclaration) - RenderTypeDeclaration(type, types, builder); + RenderTypeDeclaration(providerContext, type, types, builder); } - string GetTypeScriptTypeInternal(Type type) => GetTypeScriptType(type, types); - - if (workflowDefinition != null) - { - var contextType = workflowDefinition.ContextOptions?.ContextType; - - if (contextType != null) - { - var typeScriptType = GetTypeScriptTypeInternal(contextType); - builder.AppendLine($"declare const workflowContext: {typeScriptType}"); - } - - foreach (var variable in workflowDefinition.Variables!.Data) - { - var variableType = variable.Value?.GetType() ?? typeof(object); - var typeScriptType = GetTypeScriptTypeInternal(variableType); - builder.AppendLine($"declare const {variable.Key}: {typeScriptType}"); - } - } - + string GetTypeScriptTypeInternal(Type type) => GetTypeScriptType(providerContext, type, types); var renderingTypeScriptDefinitions = new RenderingTypeScriptDefinitions(workflowDefinition, GetTypeScriptTypeInternal, context, builder); await _mediator.Publish(renderingTypeScriptDefinitions, cancellationToken); return builder.ToString(); } - private async Task> CollectTypesAsync(WorkflowDefinition? workflowDefinition = default, CancellationToken cancellationToken = default) + private async Task> CollectTypesAsync(TypeDefinitionContext context, CancellationToken cancellationToken = default) { var collectedTypes = new HashSet(); - if (workflowDefinition != null) + foreach (var provider in _providers) { - var contextType = workflowDefinition.ContextOptions?.ContextType; + var providedTypes = await provider.CollectTypesAsync(context, cancellationToken); - if (contextType != null) - CollectType(contextType, collectedTypes); - - foreach (var variable in workflowDefinition.Variables!.Data.Values) - CollectType(variable!.GetType(), collectedTypes); + foreach (var providedType in providedTypes) + CollectType(providedType, collectedTypes); } - - CollectType(collectedTypes); - CollectType(collectedTypes); - CollectType(collectedTypes); - CollectType(collectedTypes); - CollectType(collectedTypes); - CollectType(collectedTypes); - - void CollectTypesInternal(IEnumerable types) - { - foreach (var type in types) - CollectType(type, collectedTypes); - } - - var collectTypesEvent = new CollectingTypeScriptDefinitionTypes(workflowDefinition, CollectTypesInternal); - await _mediator.Publish(collectTypesEvent, cancellationToken); - + return collectedTypes; } - private static void CollectType(ISet collectedTypes) => CollectType(typeof(T), collectedTypes); - private static void CollectType(Type type, ISet collectedTypes) { if (type.IsNullableType()) @@ -140,14 +100,11 @@ namespace Elsa.Scripting.JavaScript.Services } } - private void RenderTypeDeclaration(Type type, ISet collectedTypes, StringBuilder output) - { - RenderTypeDeclaration("class", type, collectedTypes, output); - } + private void RenderTypeDeclaration(TypeDefinitionContext context, Type type, ISet collectedTypes, StringBuilder output) => RenderTypeDeclaration(context, type.IsInterface ? "interface" : "class", type, collectedTypes, output); - private void RenderTypeDeclaration(string symbol, Type type, ISet collectedTypes, StringBuilder output) + private void RenderTypeDeclaration(TypeDefinitionContext context, string symbol, Type type, ISet collectedTypes, StringBuilder output) { - var typeName = type.Name; + var typeName = type.Name.Replace("`", ""); var properties = type.GetProperties(); var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static).Where(x => !x.IsSpecialName).ToList(); @@ -155,7 +112,7 @@ namespace Elsa.Scripting.JavaScript.Services foreach (var property in properties) { - var typeScriptType = GetTypeScriptType(property.PropertyType, collectedTypes); + var typeScriptType = GetTypeScriptType(context, property.PropertyType, collectedTypes); var propertyName = property.PropertyType.IsNullableType() ? $"{property.Name}?" : property.Name; output.AppendLine($"{propertyName}: {typeScriptType};"); } @@ -167,13 +124,13 @@ namespace Elsa.Scripting.JavaScript.Services output.Append($"{method.Name}("); - var arguments = method.GetParameters().Select(x => $"{x.Name}:{GetTypeScriptType(x.ParameterType, collectedTypes)}"); + var arguments = method.GetParameters().Select(x => $"{x.Name}:{GetTypeScriptType(context, x.ParameterType, collectedTypes)}"); output.Append(string.Join(", ", arguments)); output.Append(")"); var returnType = method.ReturnType; if (returnType != typeof(void)) - output.AppendFormat(":{0}", GetTypeScriptType(returnType, collectedTypes)); + output.AppendFormat(":{0}", GetTypeScriptType(context, returnType, collectedTypes)); output.AppendLine(";"); } @@ -181,18 +138,18 @@ namespace Elsa.Scripting.JavaScript.Services output.AppendLine("}"); } - private string GetTypeScriptType(Type type, ISet collectedTypes) + private string GetTypeScriptType(TypeDefinitionContext context, Type type, ISet collectedTypes) { if (type.IsNullableType()) type = type.GetTypeOfNullable(); - var provider = _providers.FirstOrDefault(x => x.SupportsType(type)); - return provider != null ? provider.GetTypeDefinition(type) : collectedTypes.Contains(type) ? type.Name : "any"; + var provider = _providers.FirstOrDefault(x => x.SupportsType(context, type)); + return provider != null ? provider.GetTypeDefinition(context, type) : collectedTypes.Contains(type) ? type.Name : "any"; } - private bool ShouldRenderTypeDeclaration(Type type) + private bool ShouldRenderTypeDeclaration(TypeDefinitionContext context, Type type) { - var provider = _providers.FirstOrDefault(x => x.SupportsType(type)); + var provider = _providers.FirstOrDefault(x => x.SupportsType(context, type)); return provider == null; } } diff --git a/src/scripting/Elsa.Scripting.JavaScript/Typings/CommonTypesTypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Typings/CommonTypesTypeDefinitionProvider.cs new file mode 100644 index 000000000..bd0520054 --- /dev/null +++ b/src/scripting/Elsa.Scripting.JavaScript/Typings/CommonTypesTypeDefinitionProvider.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using Elsa.Models; +using Elsa.Scripting.JavaScript.Services; +using Elsa.Services.Models; +using NodaTime; + +namespace Elsa.Scripting.JavaScript.Typings +{ + public class CommonTypesTypeDefinitionProvider : TypeDefinitionProvider + { + public override IEnumerable CollectTypes(TypeDefinitionContext context) => new[] + { + typeof(Instant), + typeof(Duration), + typeof(Period), + typeof(LocalDate), + typeof(LocalTime), + typeof(LocalDateTime), + typeof(Guid), + typeof(CultureInfo), + typeof(ActivityExecutionContext), + typeof(WorkflowExecutionContext), + typeof(WorkflowInstance), + }; + } +} \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumTypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumTypeDefinitionProvider.cs index 0775b4804..9fd614aa7 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumTypeDefinitionProvider.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumTypeDefinitionProvider.cs @@ -3,9 +3,9 @@ using Elsa.Scripting.JavaScript.Services; namespace Elsa.Scripting.JavaScript.Typings { - public class EnumTypeDefinitionProvider : ITypeDefinitionProvider + public class EnumTypeDefinitionProvider : TypeDefinitionProvider { - public bool SupportsType(Type type) => type.IsEnum; - public string GetTypeDefinition(Type type) => "number"; + public override bool SupportsType(TypeDefinitionContext context, Type type) => type.IsEnum; + public override string GetTypeDefinition(TypeDefinitionContext context, Type type) => "number"; } } \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumerableTypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumerableTypeDefinitionProvider.cs index fc21acd21..9f7d80673 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumerableTypeDefinitionProvider.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Typings/EnumerableTypeDefinitionProvider.cs @@ -4,13 +4,9 @@ using Elsa.Scripting.JavaScript.Services; namespace Elsa.Scripting.JavaScript.Typings { - public class EnumerableTypeDefinitionProvider : ITypeDefinitionProvider + public class EnumerableTypeDefinitionProvider : TypeDefinitionProvider { - public bool SupportsType(Type type) => typeof(IEnumerable).IsAssignableFrom(type); - - public string GetTypeDefinition(Type type) - { - return "[]"; - } + public override bool SupportsType(TypeDefinitionContext context, Type type) => typeof(IEnumerable).IsAssignableFrom(type); + public override string GetTypeDefinition(TypeDefinitionContext context, Type type) => "[]"; } } \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Typings/PrimitiveTypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Typings/PrimitiveTypeDefinitionProvider.cs index e0172e45b..35e37d107 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Typings/PrimitiveTypeDefinitionProvider.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Typings/PrimitiveTypeDefinitionProvider.cs @@ -4,7 +4,7 @@ using Elsa.Scripting.JavaScript.Services; namespace Elsa.Scripting.JavaScript.Typings { - public class PrimitiveTypeDefinitionProvider : ITypeDefinitionProvider + public class PrimitiveTypeDefinitionProvider : TypeDefinitionProvider { private static readonly IDictionary TypeMap = new Dictionary { @@ -25,7 +25,7 @@ namespace Elsa.Scripting.JavaScript.Typings [typeof(TimeSpan)] = "string", }; - public bool SupportsType(Type type) => TypeMap.ContainsKey(type); - public string GetTypeDefinition(Type type) => TypeMap[type]; + public override bool SupportsType(TypeDefinitionContext context, Type type) => TypeMap.ContainsKey(type); + public override string GetTypeDefinition(TypeDefinitionContext context, Type type) => TypeMap[type]; } } \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowContextTypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowContextTypeDefinitionProvider.cs new file mode 100644 index 000000000..c4855cc5d --- /dev/null +++ b/src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowContextTypeDefinitionProvider.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using Elsa.Scripting.JavaScript.Services; + +namespace Elsa.Scripting.JavaScript.Typings +{ + public class WorkflowContextTypeDefinitionProvider : TypeDefinitionProvider + { + public override IEnumerable CollectTypes(TypeDefinitionContext context) + { + var workflowDefinition = context.WorkflowDefinition; + var contextType = workflowDefinition?.ContextOptions?.ContextType; + + if (contextType != null) + yield return contextType; + } + } +} \ No newline at end of file diff --git a/src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowVariablesTypeDefinitionProvider.cs b/src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowVariablesTypeDefinitionProvider.cs new file mode 100644 index 000000000..c6557f772 --- /dev/null +++ b/src/scripting/Elsa.Scripting.JavaScript/Typings/WorkflowVariablesTypeDefinitionProvider.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Elsa.Scripting.JavaScript.Services; + +namespace Elsa.Scripting.JavaScript.Typings +{ + public class WorkflowVariablesTypeDefinitionProvider : TypeDefinitionProvider + { + public override IEnumerable CollectTypes(TypeDefinitionContext context) + { + var workflowDefinition = context.WorkflowDefinition; + + if (workflowDefinition == null) + yield break; + + foreach (var variable in workflowDefinition.Variables!.Data.Values) + yield return variable!.GetType(); + } + } +} \ No newline at end of file