Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Swagger automatic docs generator #15

kazzkiq opened this issue Mar 25, 2019 · 2 comments


Copy link

commented Mar 25, 2019

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.

@kazzkiq kazzkiq changed the title Implement Swagger automatic API generator Implement Swagger automatic docs generator Mar 25, 2019

This comment has been minimized.

Copy link

commented Apr 2, 2019

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

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 ""

  license do
    name "MIT"

  authorizations do
    jwt do
      description "Auth via JWT"

    api_key do
      name "API key auth"
      location "header"

@[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!"

@[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

Onyx::HTTP.get "/swagger", Onyx::HTTP::Swagger::Web
Onyx::HTTP.get "/swagger/api", Onyx::HTTP::Swagger::API

  summary: "Create a user",
  description: "Creates a user from the request")]
  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

        description: "A user email",
        example: "")]
      type email : String

  errors do
    @[Onyx::HTTP::Swagger::Response(description: "Returned if e-mail is already registered")]
    type EmailAlreadyRegistered(422)

  summary: "Retrieve a user",
  description: "Fetches a user from database by its ID")]
  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

  errors do
    @[Onyx::HTTP::Swagger::Response(description: "Returned if user is not found")]
    type EmailAlreadyRegistered(404)

@[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

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


This comment has been minimized.

Copy link

commented May 24, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
3 participants
You can’t perform that action at this time.