Increase javascript intellisense coverage
This commit is contained in:
parent
7f420f4f42
commit
d033b56d29
|
|
@ -44,6 +44,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
.AddHttpContextAccessor()
|
||||
.AddNotificationHandlers(typeof(ConfigureJavaScriptEngine))
|
||||
.AddLiquidFilter<SignalUrlFilter>("signal_url")
|
||||
.AddJavaScriptTypeDefinitionProvider<HttpTypeDefinitionProvider>()
|
||||
.AddDataProtection();
|
||||
|
||||
return services;
|
||||
|
|
|
|||
|
|
@ -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<EvaluatingJavaScriptExpression>
|
||||
public class ConfigureJavaScriptEngine : INotificationHandler<EvaluatingJavaScriptExpression>, INotificationHandler<RenderingTypeScriptDefinitions>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Type> CollectTypes(TypeDefinitionContext context)
|
||||
{
|
||||
return new[] { typeof(HttpRequestModel) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.";
|
||||
|
||||
|
|
|
|||
|
|
@ -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<string>),
|
||||
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" },
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ namespace Elsa.Attributes
|
|||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class ActivityOutputAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The technical name of the activity property.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A brief description about this property for workflow tooling to use when displaying activity editors.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -164,23 +164,8 @@ namespace Elsa.Services.Models
|
|||
public void SetWorkflowContext(object? value) => WorkflowExecutionContext.SetWorkflowContext(value);
|
||||
public object? GetWorkflowContext() => WorkflowExecutionContext.GetWorkflowContext();
|
||||
public T GetWorkflowContext<T>() => WorkflowExecutionContext.GetWorkflowContext<T>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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>() => (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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove empty activity data to save on document size.
|
||||
|
|
|
|||
|
|
@ -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<ActivityPropertyDescriptor> DescribeProperties(Type activityType)
|
||||
private IEnumerable<ActivityInputDescriptor> DescribeInputProperties(IEnumerable<PropertyInfo> properties)
|
||||
{
|
||||
var properties = activityType.GetProperties();
|
||||
|
||||
foreach (var propertyInfo in properties)
|
||||
{
|
||||
var activityPropertyAttribute = propertyInfo.GetCustomAttribute<ActivityInputAttribute>();
|
||||
|
|
@ -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<ActivityOutputDescriptor> DescribeOutputProperties(IEnumerable<PropertyInfo> properties)
|
||||
{
|
||||
foreach (var propertyInfo in properties)
|
||||
{
|
||||
var activityPropertyAttribute = propertyInfo.GetCustomAttribute<ActivityOutputAttribute>();
|
||||
|
||||
if (activityPropertyAttribute == null)
|
||||
continue;
|
||||
|
||||
yield return new ActivityOutputDescriptor
|
||||
(
|
||||
(activityPropertyAttribute.Name ?? propertyInfo.Name).Pascalize(),
|
||||
propertyInfo.PropertyType,
|
||||
activityPropertyAttribute.Hint
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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: '',
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ export class ElsaWorkflowBlueprintViewerScreen {
|
|||
const activityDescriptors: Array<ActivityDescriptor> = state.activityDescriptors;
|
||||
const activityDescriptor = activityDescriptors.find(x => x.type == source.type);
|
||||
const properties: Array<ActivityDefinitionProperty> = 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;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export class ElsaActivityEditorModal {
|
|||
updateActivity(formData: FormData) {
|
||||
const activity = this.activityModel;
|
||||
const activityDescriptor = this.activityDescriptor;
|
||||
const properties: Array<ActivityPropertyDescriptor> = activityDescriptor.properties;
|
||||
const properties: Array<ActivityPropertyDescriptor> = 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<string> = [];
|
||||
|
||||
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<string>) {
|
||||
const propertyDescriptors: Array<ActivityPropertyDescriptor> = activityDescriptor.properties;
|
||||
const propertyDescriptors: Array<ActivityPropertyDescriptor> = activityDescriptor.inputProperties;
|
||||
|
||||
return (
|
||||
categories.map(category => {
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
const activityDescriptors: Array<ActivityDescriptor> = state.activityDescriptors;
|
||||
const activityDescriptor = activityDescriptors.find(x => x.type == source.type);
|
||||
|
||||
debugger;
|
||||
return {
|
||||
activityId: source.activityId,
|
||||
description: source.description,
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ export class ElsaWorkflowInstanceViewerScreen {
|
|||
const activityDescriptors: Array<ActivityDescriptor> = state.activityDescriptors;
|
||||
const activityDescriptor = activityDescriptors.find(x => x.type == source.type);
|
||||
const properties: Array<ActivityDefinitionProperty> = 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;
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ export interface ActivityDescriptor {
|
|||
traits: ActivityTraits;
|
||||
outcomes: Array<string>;
|
||||
browsable: boolean;
|
||||
properties: Array<ActivityPropertyDescriptor>;
|
||||
inputProperties: Array<ActivityPropertyDescriptor>;
|
||||
}
|
||||
|
||||
export interface ActivityPropertyDescriptor {
|
||||
|
|
|
|||
|
|
@ -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<IEnumerable<Type>> collectTypes)
|
||||
{
|
||||
WorkflowDefinition = workflowDefinition;
|
||||
CollectTypes = collectTypes;
|
||||
}
|
||||
|
||||
private Action<IEnumerable<Type>> CollectTypes { get; }
|
||||
public WorkflowDefinition? WorkflowDefinition { get; }
|
||||
|
||||
public void CollectType<T>() => CollectType(typeof(T));
|
||||
public void CollectType(Type type) => CollectTypes(new[] { type });
|
||||
}
|
||||
}
|
||||
|
|
@ -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<string, object> ToDictionary(this JObject @object)
|
||||
{
|
||||
var result = @object.ToObject<Dictionary<string, object>>()!;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,16 +15,21 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
return services
|
||||
.AddScoped<ITypeScriptDefinitionService, TypeScriptDefinitionService>()
|
||||
.AddScoped<ITypeDefinitionProvider, PrimitiveTypeDefinitionProvider>()
|
||||
.AddScoped<ITypeDefinitionProvider, EnumTypeDefinitionProvider>()
|
||||
.AddScoped<ITypeDefinitionProvider, EnumerableTypeDefinitionProvider>()
|
||||
.AddScoped<IJavaScriptService, JintJavaScriptEvaluator>()
|
||||
.AddTransient(s => new JintEvaluationResultConverterFactory(s).GetConverter())
|
||||
.AddTransient<IConvertsEnumerableToObject>(s => new EnumerableResultConverter(default))
|
||||
.TryAddProvider<IExpressionHandler, JavaScriptExpressionHandler>(ServiceLifetime.Scoped)
|
||||
.AddJavaScriptTypeDefinitionProvider<PrimitiveTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<EnumTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<EnumerableTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<WorkflowContextTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<WorkflowVariablesTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<CommonTypesTypeDefinitionProvider>()
|
||||
.AddNotificationHandlers(typeof(JavaScriptServiceCollectionExtensions));
|
||||
}
|
||||
|
||||
public static IServiceCollection AddJavaScriptTypeDefinitionProvider<T>(this IServiceCollection services) where T: class, ITypeDefinitionProvider => services.AddScoped<ITypeDefinitionProvider, T>();
|
||||
|
||||
public static IServiceCollection WithJavaScriptOptions(this IServiceCollection services, Action<ScriptOptions> configureOptions)
|
||||
{
|
||||
services.Configure(configureOptions);
|
||||
|
|
|
|||
|
|
@ -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<EvaluatingJavaScriptExpression>
|
||||
public class ConfigureJavaScriptEngine : INotificationHandler<EvaluatingJavaScriptExpression>, INotificationHandler<RenderingTypeScriptDefinitions>
|
||||
{
|
||||
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<Instant>(engine);
|
||||
RegisterType<Duration>(engine);
|
||||
RegisterType<Period>(engine);
|
||||
RegisterType<LocalDate>(engine);
|
||||
RegisterType<LocalTime>(engine);
|
||||
RegisterType<LocalDateTime>(engine);
|
||||
RegisterType<Guid>(engine);
|
||||
RegisterType<WorkflowExecutionContext>(engine);
|
||||
RegisterType<ActivityExecutionContext>(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<IWorkflowBlueprint, bool> filter)
|
||||
{
|
||||
var workflowRegistry = activityExecutionContext.GetService<IWorkflowRegistry>();
|
||||
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<T>(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));
|
||||
}
|
||||
}
|
||||
17
src/scripting/Elsa.Scripting.JavaScript/IsExternalInit.cs
Normal file
17
src/scripting/Elsa.Scripting.JavaScript/IsExternalInit.cs
Normal file
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved to be used by the compiler for tracking metadata.
|
||||
/// This class should not be used by developers in source code.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
internal static class IsExternalInit
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -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<IEnumerable<Type>> CollectTypesAsync(TypeDefinitionContext context, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public record TypeDefinitionContext(WorkflowDefinition? WorkflowDefinition, string? context);
|
||||
}
|
||||
|
|
@ -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<IEnumerable<Type>> CollectTypesAsync(TypeDefinitionContext context, CancellationToken cancellationToken = default) => new(CollectTypes(context));
|
||||
public virtual IEnumerable<Type> CollectTypes(TypeDefinitionContext context) => Enumerable.Empty<Type>();
|
||||
}
|
||||
}
|
||||
|
|
@ -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<string> 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<ISet<Type>> CollectTypesAsync(WorkflowDefinition? workflowDefinition = default, CancellationToken cancellationToken = default)
|
||||
private async Task<ISet<Type>> CollectTypesAsync(TypeDefinitionContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var collectedTypes = new HashSet<Type>();
|
||||
|
||||
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<Instant>(collectedTypes);
|
||||
CollectType<Duration>(collectedTypes);
|
||||
CollectType<Period>(collectedTypes);
|
||||
CollectType<LocalDate>(collectedTypes);
|
||||
CollectType<LocalTime>(collectedTypes);
|
||||
CollectType<LocalDateTime>(collectedTypes);
|
||||
|
||||
void CollectTypesInternal(IEnumerable<Type> 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<T>(ISet<Type> collectedTypes) => CollectType(typeof(T), collectedTypes);
|
||||
|
||||
private static void CollectType(Type type, ISet<Type> collectedTypes)
|
||||
{
|
||||
if (type.IsNullableType())
|
||||
|
|
@ -140,14 +100,11 @@ namespace Elsa.Scripting.JavaScript.Services
|
|||
}
|
||||
}
|
||||
|
||||
private void RenderTypeDeclaration(Type type, ISet<Type> collectedTypes, StringBuilder output)
|
||||
{
|
||||
RenderTypeDeclaration("class", type, collectedTypes, output);
|
||||
}
|
||||
private void RenderTypeDeclaration(TypeDefinitionContext context, Type type, ISet<Type> collectedTypes, StringBuilder output) => RenderTypeDeclaration(context, type.IsInterface ? "interface" : "class", type, collectedTypes, output);
|
||||
|
||||
private void RenderTypeDeclaration(string symbol, Type type, ISet<Type> collectedTypes, StringBuilder output)
|
||||
private void RenderTypeDeclaration(TypeDefinitionContext context, string symbol, Type type, ISet<Type> 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<Type> collectedTypes)
|
||||
private string GetTypeScriptType(TypeDefinitionContext context, Type type, ISet<Type> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Type> 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),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
@ -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) => "[]";
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Type, string> TypeMap = new Dictionary<Type, string>
|
||||
{
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Type> CollectTypes(TypeDefinitionContext context)
|
||||
{
|
||||
var workflowDefinition = context.WorkflowDefinition;
|
||||
var contextType = workflowDefinition?.ContextOptions?.ContextType;
|
||||
|
||||
if (contextType != null)
|
||||
yield return contextType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Type> CollectTypes(TypeDefinitionContext context)
|
||||
{
|
||||
var workflowDefinition = context.WorkflowDefinition;
|
||||
|
||||
if (workflowDefinition == null)
|
||||
yield break;
|
||||
|
||||
foreach (var variable in workflowDefinition.Variables!.Data.Values)
|
||||
yield return variable!.GetType();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue