parent
62aa989a9e
commit
b6a7a38b21
|
|
@ -41,7 +41,7 @@ namespace Elsa.Activities.Http
|
|||
DefaultSyntax = SyntaxNames.Json,
|
||||
SupportedSyntaxes = new[] { SyntaxNames.Json, SyntaxNames.JavaScript, SyntaxNames.Liquid })]
|
||||
|
||||
public HashSet<string> Methods { get; set; } = new HashSet<string> { "GET" };
|
||||
public HashSet<string> Methods { get; set; } = new() { "GET" };
|
||||
|
||||
/// <summary>
|
||||
/// A value indicating whether the HTTP request content body should be read and stored as part of the HTTP request model.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Elsa.Activities.Http.Parsers.Request;
|
|||
using Elsa.Activities.Http.Parsers.Response;
|
||||
using Elsa.Activities.Http.Services;
|
||||
using Elsa.Options;
|
||||
using Elsa.Scripting.JavaScript.Providers;
|
||||
using Elsa.Scripting.Liquid.Extensions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
|
|
@ -58,6 +59,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
.AddNotificationHandlers(typeof(ConfigureJavaScriptEngine))
|
||||
.AddLiquidFilter<SignalUrlFilter>("signal_url")
|
||||
.AddJavaScriptTypeDefinitionProvider<HttpTypeDefinitionProvider>()
|
||||
.AddSingleton<IActivityTypeDefinitionRenderer, HttpEndpointTypeDefinitionRenderer>()
|
||||
.AddDataProtection();
|
||||
|
||||
return services;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Metadata;
|
||||
using Elsa.Models;
|
||||
using Elsa.Scripting.JavaScript.Events;
|
||||
using Elsa.Scripting.JavaScript.Providers;
|
||||
using Elsa.Services.Models;
|
||||
using NJsonSchema;
|
||||
using NJsonSchema.CodeGeneration.TypeScript;
|
||||
|
||||
namespace Elsa.Activities.Http.JavaScript
|
||||
{
|
||||
public class HttpEndpointTypeDefinitionRenderer : DefaultActivityTypeDefinitionRenderer
|
||||
{
|
||||
public class CustomTypeNameGenerator : DefaultTypeNameGenerator
|
||||
{
|
||||
public string Prefix { get; }
|
||||
|
||||
public CustomTypeNameGenerator(string prefix)
|
||||
{
|
||||
Prefix = prefix;
|
||||
}
|
||||
|
||||
protected override string Generate(JsonSchema schema, string typeNameHint)
|
||||
{
|
||||
var result = base.Generate(schema, typeNameHint);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public override async ValueTask RenderTypeDeclarationAsync(
|
||||
RenderingTypeScriptDefinitions notification,
|
||||
ActivityType activityType,
|
||||
ActivityDescriptor activityDescriptor,
|
||||
ActivityDefinition activityDefinition,
|
||||
StringBuilder writer,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var targetTypeSchema = activityDefinition.Properties.First(x => x.Name == nameof(HttpEndpoint.Schema)).Expressions.Values.First();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(targetTypeSchema))
|
||||
{
|
||||
var jsonSchema = await JsonSchema.FromJsonAsync(targetTypeSchema, cancellationToken);
|
||||
var generator = new TypeScriptGenerator(jsonSchema, new TypeScriptGeneratorSettings
|
||||
{
|
||||
TypeStyle = TypeScriptTypeStyle.Interface,
|
||||
TypeScriptVersion = 4,
|
||||
TypeNameGenerator = new CustomTypeNameGenerator(activityDefinition.Name!)
|
||||
});
|
||||
|
||||
var typeScriptType = $"{activityDefinition.Name}Output";
|
||||
|
||||
var jsonSchemaTypes = generator.GenerateFile(typeScriptType)
|
||||
.Replace("\r\n", "\n")
|
||||
.Replace("export interface", "declare class");
|
||||
|
||||
writer.AppendLine(jsonSchemaTypes);
|
||||
}
|
||||
|
||||
await base.RenderTypeDeclarationAsync(notification, activityType, activityDescriptor, activityDefinition, writer, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async ValueTask RenderActivityPropertyAsync(
|
||||
RenderingTypeScriptDefinitions notification,
|
||||
StringBuilder writer,
|
||||
string propertyName,
|
||||
Type propertyType,
|
||||
ActivityType activityType,
|
||||
ActivityDescriptor activityDescriptor,
|
||||
ActivityDefinition activityDefinition,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (propertyName != nameof(HttpEndpoint.Output))
|
||||
{
|
||||
await base.RenderActivityPropertyAsync(notification, writer, propertyName, propertyType, activityType, activityDescriptor, activityDefinition, cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetTypeName = activityDefinition.Properties.First(x => x.Name == nameof(HttpEndpoint.TargetType)).Expressions.Values.First();
|
||||
var targetTypeSchema = activityDefinition.Properties.First(x => x.Name == nameof(HttpEndpoint.Schema)).Expressions.Values.First();
|
||||
var typeScriptType = notification.GetTypeScriptType(propertyType);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(targetTypeName))
|
||||
{
|
||||
var type = Type.GetType(targetTypeName);
|
||||
|
||||
if (type != null)
|
||||
typeScriptType = notification.GetTypeScriptType(type);
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(targetTypeSchema))
|
||||
{
|
||||
typeScriptType = $"{activityDefinition.Name}Output";
|
||||
}
|
||||
|
||||
writer.AppendLine($"{propertyName}(): {typeScriptType}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Elsa.Activities.Http.Models;
|
||||
using Elsa.Scripting.JavaScript.Services;
|
||||
|
||||
|
|
@ -9,7 +10,29 @@ namespace Elsa.Activities.Http.JavaScript
|
|||
{
|
||||
public override IEnumerable<Type> CollectTypes(TypeDefinitionContext context)
|
||||
{
|
||||
return new[] { typeof(HttpRequestModel), typeof(HttpResponseHeaders), typeof(HttpResponseModel) };
|
||||
var workflowDefinition = context.WorkflowDefinition;
|
||||
|
||||
if (workflowDefinition != null)
|
||||
{
|
||||
var httpEndpointActivities = workflowDefinition.Activities.Where(x => x.Type == nameof(HttpEndpoint)).ToList();
|
||||
|
||||
foreach (var type in
|
||||
from activityDefinition in httpEndpointActivities
|
||||
select activityDefinition.Properties.First(x => x.Name == nameof(HttpEndpoint.TargetType)).Expressions.Values.First()
|
||||
into targetTypeName
|
||||
where !string.IsNullOrWhiteSpace(targetTypeName)
|
||||
select Type.GetType(targetTypeName)
|
||||
into type
|
||||
where type != null
|
||||
select type)
|
||||
{
|
||||
yield return type;
|
||||
}
|
||||
}
|
||||
|
||||
yield return typeof(HttpRequestModel);
|
||||
yield return typeof(HttpResponseHeaders);
|
||||
yield return typeof(HttpResponseModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,12 +27,25 @@ namespace Elsa.Metadata
|
|||
return null;
|
||||
|
||||
if (activityPropertyAttribute.OptionsProvider == null)
|
||||
return activityPropertyAttribute.Options ?? (TryGetEnumOptions(activityPropertyInfo, out var items) ? items : null);
|
||||
{
|
||||
var options = activityPropertyAttribute.Options;
|
||||
|
||||
if (options is IEnumerable<string> enumerable)
|
||||
return new SelectList
|
||||
{
|
||||
Items = enumerable.Select(x => new SelectListItem(x)).ToList()
|
||||
};
|
||||
|
||||
if (TryGetEnumOptions(activityPropertyInfo, out var items))
|
||||
return items;
|
||||
|
||||
return activityPropertyAttribute.Options;
|
||||
}
|
||||
|
||||
var providerType = activityPropertyAttribute.OptionsProvider;
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var provider = (IActivityPropertyOptionsProvider) ActivatorUtilities.GetServiceOrCreateInstance(scope.ServiceProvider, providerType);
|
||||
var provider = (IActivityPropertyOptionsProvider)ActivatorUtilities.GetServiceOrCreateInstance(scope.ServiceProvider, providerType);
|
||||
return provider.GetOptions(activityPropertyInfo);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,16 @@ async function fetchRuntimeItems(serverUrl: string, options: RuntimeSelectListPr
|
|||
}
|
||||
|
||||
export async function getSelectListItems(serverUrl: string, propertyDescriptor: ActivityPropertyDescriptor): Promise<SelectList> {
|
||||
const options = propertyDescriptor.options;
|
||||
const options: any = propertyDescriptor.options;
|
||||
let selectList: SelectList;
|
||||
|
||||
if (!!options && options.runtimeSelectListProviderType)
|
||||
selectList = await fetchRuntimeItems(serverUrl, options);
|
||||
else if (Array.isArray(options))
|
||||
selectList = {
|
||||
items: options,
|
||||
isFlagsEnum: false
|
||||
};
|
||||
else
|
||||
selectList = options as SelectList;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
.AddJavaScriptTypeDefinitionProvider<WorkflowContextTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<WorkflowVariablesTypeDefinitionProvider>()
|
||||
.AddJavaScriptTypeDefinitionProvider<BlacklistedTypeDefinitionProvider>()
|
||||
.AddSingleton<IActivityTypeDefinitionRenderer, DefaultActivityTypeDefinitionRenderer>()
|
||||
.AddNotificationHandlers(typeof(JavaScriptServiceCollectionExtensions));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Models;
|
||||
using Elsa.Scripting.JavaScript.Events;
|
||||
using Elsa.Scripting.JavaScript.Providers;
|
||||
using Elsa.Services;
|
||||
using Elsa.Services.Models;
|
||||
using MediatR;
|
||||
|
|
@ -13,10 +15,12 @@ namespace Elsa.Scripting.JavaScript.Handlers
|
|||
public class RenderJavaScriptTypeDefinitions : INotificationHandler<RenderingTypeScriptDefinitions>
|
||||
{
|
||||
private readonly IActivityTypeService _activityTypeService;
|
||||
private readonly IEnumerable<IActivityTypeDefinitionRenderer> _activityTypeDefinitionRenderers;
|
||||
|
||||
public RenderJavaScriptTypeDefinitions(IActivityTypeService activityTypeService)
|
||||
public RenderJavaScriptTypeDefinitions(IActivityTypeService activityTypeService, IEnumerable<IActivityTypeDefinitionRenderer> activityTypeDefinitionRenderers)
|
||||
{
|
||||
_activityTypeService = activityTypeService;
|
||||
_activityTypeDefinitionRenderers = activityTypeDefinitionRenderers.OrderByDescending(x => x.Priority).ToList();
|
||||
}
|
||||
|
||||
public async Task Handle(RenderingTypeScriptDefinitions notification, CancellationToken cancellationToken)
|
||||
|
|
@ -72,17 +76,20 @@ namespace Elsa.Scripting.JavaScript.Handlers
|
|||
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)
|
||||
await RenderActivityTypeDeclarationAsync(activityType, output);
|
||||
foreach (var namedActivity in namedActivities)
|
||||
{
|
||||
var activityType = activityTypeDictionary[namedActivity.Type];
|
||||
await RenderActivityTypeDeclarationAsync(namedActivity, activityType, output);
|
||||
}
|
||||
|
||||
output.AppendLine("declare interface Activities {");
|
||||
|
||||
foreach (var activity in namedActivities)
|
||||
{
|
||||
var activityType = activityTypeDictionary[activity.Type];
|
||||
var typeScriptType = activityType.TypeName;
|
||||
var query = $"{activity.Name}: {typeScriptType}";
|
||||
var interfaceActivity = FindInterface(notification, query);
|
||||
//var activityType = activityTypeDictionary[activity.Type];
|
||||
//var typeScriptType = activityType.TypeName;
|
||||
var typeScriptType = activity.Name;
|
||||
var interfaceActivity = $"{activity.Name}: {typeScriptType}";
|
||||
output.AppendLine($"{interfaceActivity};");
|
||||
}
|
||||
|
||||
|
|
@ -90,39 +97,11 @@ namespace Elsa.Scripting.JavaScript.Handlers
|
|||
output.AppendLine("declare const activities: Activities");
|
||||
}
|
||||
|
||||
async Task RenderActivityTypeDeclarationAsync(ActivityType type, StringBuilder writer)
|
||||
async Task RenderActivityTypeDeclarationAsync(ActivityDefinition activityDefinition, ActivityType type, StringBuilder writer)
|
||||
{
|
||||
var typeName = type.TypeName;
|
||||
var descriptor = await type.DescribeAsync();
|
||||
var inputProperties = descriptor.InputProperties;
|
||||
var outputProperties = descriptor.OutputProperties;
|
||||
|
||||
var query = $"declare interface {typeName}";
|
||||
var interfaceDeclaration = FindInterface(notification, query);
|
||||
writer.AppendLine($"{interfaceDeclaration} {{");
|
||||
|
||||
foreach (var property in inputProperties)
|
||||
RenderActivityProperty(writer, typeName, property.Name, property.Type);
|
||||
|
||||
foreach (var property in outputProperties)
|
||||
RenderActivityProperty(writer, typeName, property.Name, property.Type);
|
||||
|
||||
writer.AppendLine("}");
|
||||
}
|
||||
|
||||
void RenderActivityProperty(StringBuilder writer, string typeName, string propertyName, Type propertyType)
|
||||
{
|
||||
var typeScriptType = notification.GetTypeScriptType(propertyType);
|
||||
|
||||
var query = $"{propertyName}(): {typeScriptType}";
|
||||
var interfaceDeclaration = FindInterface(notification, query);
|
||||
writer.AppendLine($"{interfaceDeclaration};");
|
||||
}
|
||||
|
||||
string FindInterface(RenderingTypeScriptDefinitions notification, string query)
|
||||
{
|
||||
var result = notification.DeclaredTypes.FirstOrDefault(x => x.Contains(query));
|
||||
return result ?? query;
|
||||
var renderer = _activityTypeDefinitionRenderers.First(x => x.GetCanRenderType(type));
|
||||
await renderer.RenderTypeDeclarationAsync(notification, type, descriptor, activityDefinition, writer, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Metadata;
|
||||
using Elsa.Models;
|
||||
using Elsa.Scripting.JavaScript.Events;
|
||||
using Elsa.Services.Models;
|
||||
|
||||
namespace Elsa.Scripting.JavaScript.Providers
|
||||
{
|
||||
public class DefaultActivityTypeDefinitionRenderer : IActivityTypeDefinitionRenderer
|
||||
{
|
||||
public int Priority => -1;
|
||||
public bool GetCanRenderType(ActivityType activityType) => true;
|
||||
|
||||
public virtual async ValueTask RenderTypeDeclarationAsync(
|
||||
RenderingTypeScriptDefinitions notification,
|
||||
ActivityType activityType,
|
||||
ActivityDescriptor activityDescriptor,
|
||||
ActivityDefinition activityDefinition,
|
||||
StringBuilder writer,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var typeName = activityDefinition.Name;
|
||||
var inputProperties = activityDescriptor.InputProperties;
|
||||
var outputProperties = activityDescriptor.OutputProperties;
|
||||
var interfaceDeclaration = $"declare interface {typeName}";
|
||||
writer.AppendLine($"{interfaceDeclaration} {{");
|
||||
|
||||
foreach (var property in inputProperties)
|
||||
await RenderActivityPropertyAsync(notification, writer, property.Name, property.Type, activityType, activityDescriptor, activityDefinition, cancellationToken);
|
||||
|
||||
foreach (var property in outputProperties)
|
||||
await RenderActivityPropertyAsync(notification, writer, property.Name, property.Type, activityType, activityDescriptor, activityDefinition, cancellationToken);
|
||||
|
||||
writer.AppendLine("}");
|
||||
}
|
||||
|
||||
protected virtual ValueTask RenderActivityPropertyAsync(
|
||||
RenderingTypeScriptDefinitions notification,
|
||||
StringBuilder writer,
|
||||
string propertyName,
|
||||
Type propertyType,
|
||||
ActivityType activityType,
|
||||
ActivityDescriptor activityDescriptor,
|
||||
ActivityDefinition activityDefinition,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var typeScriptType = notification.GetTypeScriptType(propertyType);
|
||||
writer.AppendLine($"{propertyName}(): {typeScriptType}");
|
||||
return new ValueTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Metadata;
|
||||
using Elsa.Models;
|
||||
using Elsa.Scripting.JavaScript.Events;
|
||||
using Elsa.Services.Models;
|
||||
|
||||
namespace Elsa.Scripting.JavaScript.Providers
|
||||
{
|
||||
public interface IActivityTypeDefinitionRenderer
|
||||
{
|
||||
int Priority { get; }
|
||||
bool GetCanRenderType(ActivityType activityType);
|
||||
ValueTask RenderTypeDeclarationAsync(
|
||||
RenderingTypeScriptDefinitions notification,
|
||||
ActivityType activityType,
|
||||
ActivityDescriptor activityDescriptor,
|
||||
ActivityDefinition activityDefinition,
|
||||
StringBuilder writer,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue