aboutsummaryrefslogtreecommitdiffstats
path: root/code/api/src/Utilities/SwaggerGenOptionsExtensions.cs
blob: a3d90366398cabdcf0bd9872944c2b11017481a0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#nullable enable
using IOL.GreatOffice.Api.Endpoints;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Controllers;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace IOL.GreatOffice.Api.Utilities;

public static class SwaggerGenOptionsExtensions
{
    /// <summary>
    /// Updates Swagger document to support ApiEndpoints.<br/><br/>
    /// For controllers inherited from <see cref="EndpointBase"/>:<br/>
    /// - Replaces action Tag with <c>[namespace]</c><br/>
    /// </summary>
    public static void UseApiEndpoints(this SwaggerGenOptions options) {
        options.TagActionsBy(EndpointNamespaceOrDefault);
    }

    private static IList<string?> EndpointNamespaceOrDefault(ApiDescription api) {
        if (api.ActionDescriptor is not ControllerActionDescriptor actionDescriptor) {
            throw new InvalidOperationException($"Unable to determine tag for endpoint: {api.ActionDescriptor.DisplayName}");
        }

        if (actionDescriptor.ControllerTypeInfo.GetBaseTypesAndThis().Any(t => t == typeof(EndpointBase))) {
            return new[] {
                actionDescriptor.ControllerTypeInfo.Namespace?.Split('.').Last()
            };
        }

        return new[] {
            actionDescriptor.ControllerName
        };
    }

    private static IEnumerable<Type> GetBaseTypesAndThis(this Type type) {
        var current = type;
        while (current != null) {
            yield return current;
            current = current.BaseType;
        }
    }
}