Coder Social home page Coder Social logo

asyncapi / saunter Goto Github PK

View Code? Open in Web Editor NEW
182.0 11.0 54.0 741 KB

Saunter is a code-first AsyncAPI documentation generator for dotnet.

Home Page: https://www.asyncapi.com/

License: MIT License

C# 99.35% HTML 0.47% Dockerfile 0.18%
asyncapi dotnet aspnetcore openapi documentation amqp hacktoberfest

saunter's Introduction

AsyncAPI Logo

Read the specification

The latest draft specification can be found at spec/asyncapi.md which tracks the latest commit to the master branch in this repository.

The human-readable markdown file is the source of truth for the specification.

Click to see reference links to older versions of the specification.

Looking for the JSON Schema files? Check out our spec-json-schemas repo.

Feel like contributing? Check out our contributor's guide.

Examples

Check out the examples directory for examples.

Case Studies and Adopters

Check out the AsyncAPI website to see the list of AsyncAPI adopters and their use cases.

Our Sponsors

Want to become a sponsor? Learn what we do with sponsors' money and join the club.

Platinum

IBM logo      Solace logo

Gold

Postman logo

Silver

Bump.sh logo      svix logo
hivemq logo      aklivity logo

Bronze

RedHat logo

Contributors

Thanks goes to these wonderful people (emoji key):

Fran Méndez
Fran Méndez

💬 🐛 📝 📖 🤔 🚇 🚧 👀 📢
Lukasz Gornicki
Lukasz Gornicki

📖 🤔 👀 💬 📝 📢 🚧 🚇
Mike Ralphson
Mike Ralphson

💬 📖 🤔 🚇 👀 🚧
raisel melian
raisel melian

💬 🐛 📖 🤔 🚧 👀
Chris Wood
Chris Wood

🤔 📖
Jonathan Schabowsky
Jonathan Schabowsky

📖 🤔
Victor Romero
Victor Romero

🤔 👀
Antonio Garrote
Antonio Garrote

🤔 👀 📖
Jonathan Stoikovitch
Jonathan Stoikovitch

💡 🤔 👀
Jonas Lagoni
Jonas Lagoni

🐛 📖 🤔 💬 👀 💡
Waleed Ashraf
Waleed Ashraf

📢 🤔 📖 💡
Andrzej Jarzyna
Andrzej Jarzyna

📢
Emmelyn Wang
Emmelyn Wang

📝 🤔 📖 📢
Marc DiPasquale
Marc DiPasquale

📝 📢 👀 🐛 🤔 📹
Gerald Loeffler
Gerald Loeffler

📖 🐛 🤔
Dale Lane
Dale Lane

📝 🤔 📹 📢 📖
Maciej Urbańczyk
Maciej Urbańczyk

👀 🤔 💬 🐛 📖 💡 🚧
Vladimir Gorej
Vladimir Gorej

📖 🐛 💡 🤔 👀
Lorna Jane Mitchell
Lorna Jane Mitchell

📢 🤔
Laurent Broudoux
Laurent Broudoux

📖 📝 📢 💡 🤔 👀
Jesse Menning
Jesse Menning

📝 📢 👀 🤔
Sergio Moya
Sergio Moya

👀 🤔 💬 📝 🐛 📖 💡 🚧
Alexander Balogh
Alexander Balogh

📖 🐛
Khuda Dad Nomani
Khuda Dad Nomani

💡 🐛
Aaron Korver
Aaron Korver

📖
Orlov Valentine
Orlov Valentine

📖
Moez Bouhlel
Moez Bouhlel

📖
Muhammad Rafly Andrianza
Muhammad Rafly Andrianza

📖
Daniel Kocot
Daniel Kocot

📖 💡 🤔
sekharbans-ebay
sekharbans-ebay

📖 💡 🤔
Michael Davis
Michael Davis

🐛 📖 💡 🤔
Heiko Henning
Heiko Henning

🐛 💻 🖋 📖 💡 🤔 🚧 👀
Quetzalli
Quetzalli

🖋 📖 💡 🤔 👀
Akshit Gupta
Akshit Gupta

🖋 📖
samz
samz

🐛 🖋 📖 💡 📆
Rishi
Rishi

🚧 🚇
nickshoe
nickshoe

🐛 📖
Ace
Ace

📋 🤔 🚧 📢
Animesh Kumar
Animesh Kumar

🖋 📖 🚧
Fabrizio Lazzaretti
Fabrizio Lazzaretti

📖
Pavel Bodiachevskii
Pavel Bodiachevskii

📖 🐛 🤔 💬

This project follows the all-contributors specification. Contributions of any kind welcome!

saunter's People

Contributors

brechtvhb avatar devlux avatar filipedguy avatar gomete avatar henryprutsman-situsamc avatar janeggers avatar jellevandendriessche avatar jgpayvision avatar m-wild avatar meunierfrederic avatar ricosuter avatar sunnjek avatar tscrypter avatar wallyuva avatar zarusz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

saunter's Issues

requiredmembers not properly setup

the requiredmembers set is not properly assembled: currently any name overrides (jsonpropertyname, datamember) and the propertyselector are not applied on the requiredmembers entries.

Message could be a $ref in Operation.

Check this asyncapi documentation.

channels:
  Envios/Traza/Admision:
    publish:
      operationId: Admision
      message:
        $ref: '#/components/messages/Admision'  

I think is no way to do that with the current classes. The Message should implement an Interface like Schema to have the possibility of add a Reference.

Best Regards,
Facundo

Channel Operation should support multiple messages

Currently, Channel is an attribute for a method and the Operation must be an attribute in the same method and only a message type can be provided.

If I repeat the Channel with the same name, on another method, it generates an error indicating the Channel is already added as a key in a Dictionary.

So it's only possible to describe a single Message to one Channel within one Operation.

For example, in my case, I have a Kafka topic that aggregates multiple messages.

In the specification, it describes that in an Operation, a Message Object can be declared as a set of possible message types (using oneOf):
https://www.asyncapi.com/docs/specifications/2.0.0/#operationObject

A possible solution, that is more flexible, is to allow for Channels/Operations and Messages to be declared as independent attributes in multiple classes or methods. In this case, each Message Attribute would specify the Operation it belongs to, and when generating the document, it would update/add the message (stored as a collection) in the specified Operation object.

Thank you for your project and for your help!

RabbitMQ.Client.Core.DependencyInjection Support

I am currently using RabbitMQ.Client.Core.DependencyInjection so I have all the information in the di container and I dont want to add attributes to all the implementations that contain redundant information.

so what i would like to see is:

public interface IOperationProvider
{
       IEnumerable<(string channelname, Type payloadtype ,OperationType)> ProvideOperations()
}

this lib could provide the default implementation with the code in DocumentGenerator but I would be able to tap into the di container and use the information that is present there.

Add Kafka bindings

Kafka is a popular message broker.
We should provide

  • classes for Kafka bindings,
  • documentation on how to use Kafka bindings

https://github.com/asyncapi/bindings/tree/master/kafka

Bindings are currently usable by creating a filter which adds the binding.
e.g.

services.AddAsyncApiSchemaGeneration(options =>
{
    options.ChannelItemFilters.Add(new MyAmqpChannelFilter());
}

class MyAmqpChannelFilter : IChannelItemFilter
{
    public void Apply(ChannelItem channelItem, ChannelItemFilterContext context)
    {
        channelItem.Bindings.Amqp = new AmqpChannelBinding
        {
            Is = AmqpChannelBindingIs.RoutingKey,
            Exchange = new AmqpChannelBindingExchange
            {
                Name = "streetlights",
                Type = "topic",
            }
        };
    }
}

Missing character in "ValidRegex" pattern of ComponentFieldName

In my class properties I have some nullable components. In AsyncApiSchema/v2/ComponentFieldName.cs there is a validation of the component field name which does not include the character "`" of my type "nullable`1", which breaks the process.

Just adding the character to ValidRegex fixes the problem:

private const string ValidRegex = @"^[a-zA-Z0-9\.\-_`]+$";

Any collateral damage you could think of after adding this?

Thank you for your work!

"examples"field is not an Array of Maps

In reference documentation, one can see that Message.examples field is a [Map[string,any]].

However, in Message Class, Examples member is a IDictionary<string,object>.
Generated documentation validation fails (online editor here).

With the following in Message.cs line 42

        [JsonProperty("examples")]
        public IList<IDictionary<string, object>> Examples { get; set; } = new List<IDictionary<string, object>>();

generated documents are valid.

Missing default property in Schema class.

Another topic. I was using the classes to generate yaml documentation, that is why a found some missing properties.
It will be good to have yaml generation also, What do you think?

Facundo

Herency

Is possible use classes that using herency? I use it to have a basic structure for every event and I add the necessary fields.

public class SyncDocumentIntegrationEvent : IntEvent
{
public int DocumentId { get; }
public int UserId { get; }

    public SyncDocumentIntegrationEvent(int documentId, int userId) : base()
    {
        DocumentId = documentId;
        UserId = userId;
    }
}

The document generated by asyncAPI is enormous and breaks the structure:

I'm doing something wrong?

Thanks for the help.

the requiredmembers are not properly filled

the requiredmembers set is not properly assembled: currently any name overrides (jsonpropertyname, datamember) and the propertyselector are not applied on the requiredmembers entries.

Add a list of most common server protocols

In order to create the Server object instead of passing a string to the constructor, the list of the most common protocols could be provided to reduce errors and to normalize the casing.

The list is provided in the specs: REQUIRED. The protocol this URL supports for connection. Supported protocol include, but are not limited to: amqp, amqps, http, https, jms, kafka, kafka-secure, mqtt, secure-mqtt, stomp, stomps, ws, wss. (https://www.asyncapi.com/docs/specifications/2.0.0#serversObject).

It is not a limited list.

Is it possible to add automatically request examples for testing asyncAPI?

Hi evryone,
I wonder, if there is any option to add examples to autogenerated AsyncAPI document. It would be very useful to be able to add them using decorators (swagger-like) to have more complete APIs definitions when importing them into other tools such as Microcks (API listing, mocking and testing tool).
Thanks.

Add HTTP Bindings

HTTP is a popular format for async messaging (webooks).
We should provide

  • classes for HTTP bindings,
  • documentation on how to use HTTP bindings

https://github.com/asyncapi/bindings/tree/master/http

Bindings are currently usable by creating a filter which adds the binding.
e.g.

services.AddAsyncApiSchemaGeneration(options =>
{
    options.ChannelItemFilters.Add(new MyAmqpChannelFilter());
}

class MyAmqpChannelFilter : IChannelItemFilter
{
    public void Apply(ChannelItem channelItem, ChannelItemFilterContext context)
    {
        channelItem.Bindings.Amqp = new AmqpChannelBinding
        {
            Is = AmqpChannelBindingIs.RoutingKey,
            Exchange = new AmqpChannelBindingExchange
            {
                Name = "streetlights",
                Type = "topic",
            }
        };
    }
}

Add code-first discriminator support

Add discriminator support. It is in the specification and currently, there is no way to mark the polymorphism and inheritance using discriminators.

image

"oneOf" is not part of the schema but it is supported in the AsyncAPI playground:

image

{
  "asyncapi": "2.0.0",
  "info": {
    "title": "Example AsyncAPI",
    "version": "v1"
  },
  "defaultContentType": "application/json",
  "channels": {
    "MessagePublished": {
      "publish": {
        "operationId": "events",
        "message": {
          "payload": { "$ref": "#/components/schemas/event" },
          "name": "event"
        }
      }
    }
  },
  "components": {
    "schemas": {
      "event": {
        "required": ["provider"],
        "discriminator": "provider",
        "oneOf": [
          { "$ref": "#/components/schemas/aEventSubType" },
          { "$ref": "#/components/schemas/otherEventSubType" }
        ]
      },
      "aEventSubType": {
        "required": ["provider", "name"],
        "properties": {
          "provider": {
            "type": "string",
            "description": "aEventSubType."
          },
          "name": {
            "type": "string",
            "description": "aEventSubType name."
          }
        }
      },
      "otherEventSubType": {
        "required": ["provider", "name"],
        "properties": {
          "provider": {
            "type": "string",
            "description": "otherEventSubType."
          },
          "name": {
            "type": "string",
            "description": "otherEventSubType name."
          },
          "additionalProperty": {
            "type": "string",
            "description": "otherEventSubType additionalProperty."
          }
        }
      }
    }
  }
}

Extract serialization from Middleware into Serializer object

Currently the building of the document model is separated from the middleware, and rightfully so. In this way, a third-party application (not necessarily an ASP.NET application) can build the document model independently, either by creating items or by scanning assemblies.

However, the serialization parameters are still in-coded inside the Middleware, meaning that the only way to get a valid JSON output with Saunter is either inside an ASP.NET application using this middleware, or re-implementing the same lines of code elsewhere in a custom tooling.

Extracting the following lines of code into its own AsyncApiDocumentSerializer enables developers that do not wish to use the Middleware on a particular workflow (or cannot because their application is not based on ASP.NET's pipeline) to still generate documentation and serialize it in a pre-configured validatable form. Moreover it enables the ability to plug in multiple different serialization methods (e.g. YamlAsyncApiDocumentSerializer or TextJsonAsyncApiDocumentSerializer).

https://github.com/tehmantra/saunter/blob/07f310f43caba862ad638b09fc071198186bcd77/src/Saunter/AsyncApiMiddleware.cs#L38-L50

Allow setting description for attributes/parameters

Hi there!

An idea that I think it's not available right now (please correct me if it is). It would be very useful to be able to define the "description" field of the properties of a class via summary or metadata.

Example:

public sealed class MyClass
   {
       /// <summary>
       /// Att1 description.
       /// </summary>
       public double Att1 { get; set; }

       [Saunter.Attributes.ParameterDefinition(Description = "Att2 description.")]
       public double Att2 { get; set; }
   }

Resulting in:

"myClass":{"properties":{
       "Att1":{"type":"number", "description":"Att1 description."},
       "Att2":{"type":"number", "description":"Att2 description."}
}}

align the enum name handling with the behavior of system.text.json

align the enum handling with the behavior of System.Text.Json:

  • use the enum value (int) by default
  • use the case-sensitive name of the enum member if JsonStringEnumConverter is specified

other than that, use the EnumMemberAttribute if the internal EnumMemberConverter is specified

as this behavior is subject to be changed in .NET5 (dotnet/runtime#31081) I would propose to add support for the JsonStringEnumMemberConverter (part of Macross.Json.Extensions) by applying the same logic as with the internal EnumMemberConverter.

SignalR Integration

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

Add UI to view documentation

Similar to Swachbuckle.AspNetCore which provides app.UseSwaggerUI() it would be nice to have an app.UseAsyncApiUI()

Allow oneOf messages

Regarding the AsyncApi specification, the operation field message could be a oneOf with an array of possible message objects.

A definition of the message that will be published or received on this channel. oneOf is allowed here to specify multiple messages, however, a message MUST be valid only against one of the referenced message objects.

The AsyncApi playground supports this case too:
image

System.Guid apparently not supported

In my many of my classes I have properties of type "System.Guid". This type has itself an Empty property of type "System.Guid". Hence, the component generated by Saunter is:

      "guid":{
            "properties":{
               "Empty":{
                  "$ref":"#/components/schemas/guid"
               }
            }
         }

When I try to render the resulting json file in the AsynApi editor it throws the error "undefined". This could be an infinite loop. Simply setting guid to type string solves the problem, but it is not the desired behaviour.

Maybe I'm doing something wrong?

MapAsyncApiDocuments not found

Documentation says that I should add this

app.UseEndpoints(endpoints =>
{
endpoints.MapAsyncApiDocuments();
});

But there is no MapAsyncApiDocuments extension method on v0.2.0 package. I am running .Net 5.

Use NJsonSchema for the JSON Schema implementation

Hi Everyone

I'm the maintainer of NSwag (https://github.com/RicoSuter/NSwag) and I have a proposal.

NSwag is built on top of NJsonSchema (https://github.com/RicoSuter/NJsonSchema) which contains the model, schema generator and code generators for JSON Schema.

Would you be open to use NJsonSchema as the base of Saunter? This way you could leverage all the features of NJS and we could bundle our efforts in building great dev tools...

This would probably solve the following issues:

  • #48 NJS supports both Newtonsoft.Json (uses the contract resolver and not reflection for maximum compatibility) and the new System.Text.Json
  • #20 #22 NJS already supports NRT out-of-the-box via https://github.com/RicoSuter/Namotion.Reflection
  • #8 $refs are correctly resolved (document wide) and can be defined in the model (ActualSchema, Reference properties)

What do you think?

A simple spec implementation (simpler than NSwag) based on NJS can be checked out here, eg the spec model just uses the JsonSchema class:
https://github.com/RicoSuter/SigSpec/blob/master/src/SigSpec.Core/SigSpecOperation.cs

/cc @devlux @tehmantra

Create a changelog

  • Create a changelog so that users know what is changing when new versions are published.
  • Follow the keep a changelog format.
  • Add all current versions to the log (currently v0.1.0 and v0.2.0)

datetimeoffset creates recursive schema

"dateTimeOffset":{
"properties":{
"Now":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"UtcNow":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"DateTime":{
"type":"string",
"format":"date-time"
},
"UtcDateTime":{
"type":"string",
"format":"date-time"
},
"LocalDateTime":{
"type":"string",
"format":"date-time"
},
"Date":{
"type":"string",
"format":"date-time"
},
"Day":{
"type":"integer"
},
"DayOfWeek":{
"type":"string",
"enum":[
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
]
},
"DayOfYear":{
"type":"integer"
},
"Hour":{
"type":"integer"
},
"Millisecond":{
"type":"integer"
},
"Minute":{
"type":"integer"
},
"Month":{
"type":"integer"
},
"Offset":{
"type":"string",
"format":"time-span"
},
"Second":{
"type":"integer"
},
"Ticks":{
"type":"integer"
},
"UtcTicks":{
"type":"integer"
},
"TimeOfDay":{
"type":"string",
"format":"time-span"
},
"Year":{
"type":"integer"
},
"MinValue":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"MaxValue":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"UnixEpoch":{
"$ref":"#/components/schemas/dateTimeOffset"
}
}
},

Add channel parameters

Channel parameters field in the specification is an array of parameter objects https://www.asyncapi.com/docs/specifications/2.0.0#parametersObject. In the current implementation, channel parameters field is a string.

There is no way of setting parameters in the ChannelAttibute as Parameters property is a string too.

Could we modify the schema (it is a breaking change) and add a new ChannelParameterAttribute to add one or several parameters to the channel indicated with ChannelAttribute?

Use Endpoint routing

Currently, the middleware needs to run in the app pipeline before the terminal Endpoints middleware.

app.UseRouting();

app.UseMiddleware<AsyncApiMiddleware>();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

It would be nice to register this as an endpoint:

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapAsyncApiDocuments();
});

Nuget Build

I notice #61 was fixed, are you planning a new nuget build with that in?

✨ Feature - MQTTnet.AspNetCore.AttributeRouting Support

I've been struggling to get Saunter v0.3.1 to work in combination with:

My project has these 2 MQTTnet libraries implemented successfully in ASP.NET 5 now.
I tried to follow Saunters documentation to the letter too. However with MQTTnet there was no need for me to implement MessageBus(Interface)s or Event (model-like) classes.

I can send/receive payloads from the MQTTnet.App client test application, however Saunter AsyncAPI Documentation generation keeps failing, the only thing I see hosted under /asyncapi/ui/index.html is the info defined in new AsyncApiDocument() of Startup.cs.

Which lead me to wondering:

  • Are these packages are actually compatible with each other or not?
  • Are any example projects that combine these packages available somewhere? (Looked but couldn't find any)
  • Does Saunter provide a MQTT Broker? (I assume it doesn't, because I saw the mosquitto references, MQTTnet is my Broker that is embedded in the source of my project in this case, thus I have no need for a stand alone broker like mosquitto)

Any help would be truly welcome!

add ability to expose multiple async apis

buhu we have a monolith :)

can you please expose any method to split / filter the api.

for my monster monolith it would be nice to split by first segment of channel name.

right now we write the aync api spec by hand and have:

AcountApi.*
ProductApi.*
.....

but as this is all hosted in one app i now only get a giant doc and i am not able to recreate what we had created manually

Add supported exchange types to the specification

In order to reduce typos, a list of exchange types could be provided as it is a short limited list: The type of the exchange. Can be either topic, direct, fanout, default or headers. (https://github.com/asyncapi/bindings/blob/master/amqp/README.md#channel).

The is property is an enum and this exchange.type seems to be the same case but:

  • I don't know if it could grow or vary more often than is.
  • It will be a breaking change.

So my proposal is to provide a static class with a list of constants just to have the supported options.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.