asyncapi / saunter

Saunter is a code-first AsyncAPI documentation generator for dotnet.
https://www.asyncapi.com/
MIT License
205 stars 57 forks source link

SignalR Integration #92

Open mhmd-azeez opened 3 years ago

mhmd-azeez commented 3 years ago

Hi, from what I can see Saunter doesn't support generating AsyncAPI spec from SignalR hubs out of the box. Do you have any plans to add that? I am willing to give it a try if it's something that you want to add

m-wild commented 3 years ago

Hi, I don't have any experience using SignalR personally. But it's definitely something that I want Saunter to support.

If you are happy to work on it I would accept a PR.

Thanks

mhmd-azeez commented 3 years ago

Cool, can you give me an overview of what needs to be done? I'd really appreciate it :)

m-wild commented 3 years ago

I think you'd have to implement a new IDocumentGenerator. The current implementation is focused on scanning assemblies to find classes & methods with the Saunter-specific attributes, I don't think it makes sense to mix the SignalR stuff in with that. There's currently no extension point below that level which is perhaps unfortunate.

A starting point might look something like this

public class SignalRDocumentGenerator : IDocumentGenerator
{
    private readonly AsyncApiOptions _options;

    public SignalRDocumentGenerator(IOptions<AsyncApiOptions> options)
    {
        _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
    }

    public AsyncApiDocument GenerateDocument(TypeInfo[] _)
    {
       // could either ignore the TypeInfo[] here... they are the ones with [AsyncApi] attribute
       // or require SignalR hubs to have the [AsyncApi] attribute?

        var schemaRepository = new SchemaRepository();

        var asyncApiSchema = _options.AsyncApi;

        asyncApiSchema.Channels = GenerateChannels(schemaRepository);
        asyncApiSchema.Components.Schemas = schemaRepository.Schemas;

        return asyncApiSchema;
    }

    private Channels GenerateChannels(ISchemaRepository schemaRepository)
    {
        // scan assemblies to find SignalR types?
        // maybe Microsoft provides a class to help find these types like the IApiExplorer in MVC?
    }
}

This would likely need to be in a separate project (which we can build to a separate NuGet package) to avoid the core lib taking a dependency on SignalR.

mhmd-azeez commented 3 years ago

Looks good. I haven't looked into it too deep so will have to sit down and do some proper experimentations. But my idea right now is to only support strongly typed Hubs for now.

Once I start working on it I'll have a better idea of what needs to be done. Your overview is very helpful though, thank you :)

mhmd-azeez commented 3 years ago

Hi, unfortunately I don't think I understand AsyncAPI spec or SignalR enough to contribute a good integration for this library. I am sorry.

Serg046 commented 2 years ago

Hello @tehmantra, I don't think this issue should be closed. Someone might want to finish it. That IDocumentGenerator doesn't look too difficult to implement. I will try to find some time to do it. But what else should be done in order to have UI support? A new binding? How easy is to implement it?

m-wild commented 2 years ago

Hi @Serg046, that's for offering to help. I think we would just need a class like the example filter above.

As for bindings, SignalR should probably use websockets bindings https://github.com/asyncapi/bindings/blob/master/websockets/README.md

The bindings are super easy to add, just some POCOs.

Let me know if you need any help, I'm also available on the AsyncAPI slack if you prefer to chat there.

Serg046 commented 2 years ago

I've ended up with this approach https://github.com/neuroglia-io/AsyncApi/issues/3#issuecomment-882043073. So we can do the same trick here to discribe the hubs. I see just two topics to discuss:

  1. Seems Saunter doesn't support two channels with the same name, however you need two here for publish and subscribe.
  2. SignalR supports multiple arguments. Finally it converts them to an array [typeOfArg1, typeOfArg2, ...] which is not valid in C# and cannot be described using existing operation attributes. We can extend attributes so that they support multiple args too.