#nullable enable
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Svrnty.CQRS.Configuration;
using System;
using System.Linq;
using System.Reflection;
namespace Svrnty.CQRS.MinimalApi;
public static class WebApplicationExtensions
{
///
/// Maps Svrnty CQRS endpoints based on configuration (supports both gRPC and MinimalApi)
///
public static WebApplication UseSvrntyCqrs(this WebApplication app)
{
var config = app.Services.GetService();
// Handle gRPC configuration if available
// Note: GrpcCqrsOptions type is from Svrnty.CQRS.Grpc package
var grpcOptionsType = Type.GetType("Svrnty.CQRS.Grpc.GrpcCqrsOptions, Svrnty.CQRS.Grpc");
if (grpcOptionsType != null && config != null)
{
var getConfigMethod = typeof(CqrsConfiguration).GetMethod("GetConfiguration")!.MakeGenericMethod(grpcOptionsType);
var grpcOptions = getConfigMethod.Invoke(config, null);
if (grpcOptions != null)
{
// Try to find and call MapGrpcFromConfiguration extension method via reflection
// This is generated by the source generator in consumer projects
var grpcMethod = FindExtensionMethod("MapGrpcFromConfiguration");
if (grpcMethod != null)
{
grpcMethod.Invoke(null, new object[] { app });
}
else
{
Console.WriteLine("Warning: MapGrpcFromConfiguration not found. gRPC endpoints were not mapped.");
Console.WriteLine("Make sure your project references Svrnty.CQRS.Grpc and has source generators enabled.");
}
}
}
// Handle MinimalApi configuration if available
var minimalApiOptions = config?.GetConfiguration();
if (minimalApiOptions != null)
{
if (minimalApiOptions.MapCommands)
{
app.MapSvrntyCommands(minimalApiOptions.CommandRoutePrefix);
}
if (minimalApiOptions.MapQueries)
{
app.MapSvrntyQueries(minimalApiOptions.QueryRoutePrefix);
}
// TODO: Add dynamic query mapping when available
// if (minimalApiOptions.MapDynamicQueries)
// {
// app.MapSvrntyDynamicQueries(minimalApiOptions.DynamicQueryRoutePrefix);
// }
}
return app;
}
private static MethodInfo? FindExtensionMethod(string methodName)
{
// Search through all loaded assemblies for the extension method
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
var types = assembly.GetTypes()
.Where(t => t.IsClass && t.IsSealed && !t.IsGenericType && t.IsPublic);
foreach (var type in types)
{
var method = type.GetMethod(methodName,
BindingFlags.Static | BindingFlags.Public,
null,
new[] { typeof(IEndpointRouteBuilder) },
null);
if (method != null)
return method;
}
}
catch
{
// Skip assemblies that can't be inspected
}
}
return null;
}
}