onyxframework / onyx

Powerful framework for modern applications 💪
https://api.onyxframework.com/onyx
MIT License
78 stars 5 forks source link

Implement Swagger automatic docs generator #15

Open kazzkiq opened 5 years ago

kazzkiq commented 5 years ago

First of all, thanks for this awesome and fully featured project.

Some frameworks I've worked with in other languages have an extremely useful feature that is generating Swagger docs automatically, just by "reading" the code you wrote.

Screen Shot 2019-03-25 at 12 29 35

Dynamic and interpreted languages have some trouble generating all the contracts (including param types, etc). But from the nature of Crystal (as a compiled, statically type checked language) it should be possible to create high fidelity contracts based on the project code.

The advantages of generating docs dynamically are as clear as it can get. It would be a great feature for Onyx Framework.

There is already a shard that let's you create such docs programmatically. Perhaps that could be used as a starting point.

vladfaust commented 5 years ago

Below goes an example of annotations-based syntax. RFC.

```crystal require "onyx/http" require "onyx/http/swagger" Onyx::HTTP::Swagger.configure do title "App API" version "1.0.0" contact do name "John Doe" email "john@doe.com" end license do name "MIT" end authorizations do jwt do description "Auth via JWT" end api_key do name "API key auth" location "header" end end end @[Onyx::HTTP::Swagger::Action(summary: %Q[Say "Hello World!"])] @[Onyx::HTTP::Swagger::Response(code: 200, description: "Always returns 200")] Onyx::HTTP.get "/" do |env| env.response << "Hello World!" end @[Onyx::HTTP::Swagger::Controller(name: "User", description: "User resources")] Onyx::HTTP.on "/users" do post "/", Endpoint::User::Create get "/:id", Endpoint::User::Get get "/", Endpoint::User::Index end Onyx::HTTP.get "/swagger", Onyx::HTTP::Swagger::Web Onyx::HTTP.get "/swagger/api", Onyx::HTTP::Swagger::API @[Onyx::HTTP::Swagger::Action( summary: "Create a user", description: "Creates a user from the request")] @[Onyx::HTTP::Swagger::Response( code: 201, description: "Returned when user is created", content_type: "application/json")] # Onyx has content-type depending on Accept header... struct Endpoint::User::Create include Onyx::HTTP::Endpoint params do # Generates a single Swagger::Request json require: true do @[Onyx::HTTP::Swagger::Property(description: "A user name", example: "Bob")] type name : String @[Onyx::HTTP::Swagger::Property( description: "A user email", example: "bob@example.com")] type email : String end end errors do @[Onyx::HTTP::Swagger::Response(description: "Returned if e-mail is already registered")] type EmailAlreadyRegistered(422) end end @[Onyx::HTTP::Swagger::Action( summary: "Retrieve a user", description: "Fetches a user from database by its ID")] @[Onyx::HTTP::Swagger::Response( code: 200, description: "Returned when user is found", content_type: "application/json")] struct Endpoint::User::Get include Onyx::HTTP::Endpoint params do # Generates Swagger::Parameter for every param path do @[Onyx::HTTP::Swagger::Parameter(description: "A user's ID")] type id : Int32 end end errors do @[Onyx::HTTP::Swagger::Response(description: "Returned if user is not found")] type EmailAlreadyRegistered(404) end end @[Onyx::HTTP::Swagger::Action(summary: "Get many users")] @[Onyx::HTTP::Swagger::Response(code: 200, content_type: "application/json")] struct Endpoint::User::Index include Onyx::HTTP::Endpoint params do # Generates Swagger::Parameter for every param query do type limit : Int32 = 10 type offset : Int32 = 0 end end end ```

It would also be possible to export Swagger JSON via Onyx CLI, I suppose.

aemadrid commented 5 years ago

I'd prefer being able to annotate endpoints with a DSL instead of annotations. They just look ugly to me: add a lot of noise that a clean DSL could clean up.