Rolodex v0.4.0 Rolodex

Rolodex generates documentation for your Phoenix API.

Rolodex inspects a Phoenix Router and transforms the @doc annotations on your controller actions into documentation data in the format of your choosing.

Rolodex.run/1 encapsulates the full documentation generation process. When invoked, it will:

1) Traverse your Phoenix Router 2) Collect documentation data for the API endpoints exposed by your router 3) Serialize the data into a format of your choosing (e.g. Swagger JSON) 4) Write the serialized data out to a destination of your choosing.

Rolodex can be configured in the config/ files for your Phoenix project. See Rolodex.Config for more details on configuration options.

Features and resources

  • Reusable parameter schemas - See Rolodex.Schema for details on how to write reusable schemas for request and response parameters in your API.
  • Structured annotations - See Rolodex.Route for details on how to format annotations on your API route action functions for the Rolodex parser to handle
  • Generic serialization - The Rolodex.Processor behaviour encapsulates the basic steps needed to serialize API metadata into documentation. Rolodex ships with a valid Swagger JSON processor (see: Rolodex.Processors.Swagger)
  • Generic writing - The Rolodex.Writer behaviour encapsulates the basic steps needed to write out formatted docs. Rolodex ships with a file writer ( see: Rolodex.Writers.FileWriter)

High level example

# Your Phoenix router
defmodule MyRouter do
  pipeline :api do
    plug MyPlug
  end

  scope "/api" do
    pipe_through [:api]

    get "/test", MyController, :index
  end
end

# Your controller
defmodule MyController do
  @doc [
    headers: ["X-Request-ID": uuid],
    body: [id: :uuid],
    query_params: [include: :string],
    path_params: [user_id: :uuid],
    responses: %{200 => MyResponse},
    metadata: [public: true],
    tags: ["foo", "bar"]
  ]
  @doc "My index action"
  def index(conn, _), do: conn
end

# Your response schema
defmodule MyResponse do
  use Rolodex.Schema

  schema "MyResponse", desc: "A response" do
    field :id, :uuid
    field :name, :string, desc: "The response name"
  end
end

# In mix.exs
config :rolodex,
  title: "MyApp",
  description: "An example",
  version: "1.0.0",
  router: MyRouter,
  pipelines: [
    api: [
      headers: ["Include-Meta": :boolean]
    ]
  ]

# Then...
Application.get_all_env(:rolodex)
|> Rolodex.Config.new()
|> Rolodex.run()

# The JSON written out to file should look like
%{
  "openapi" => "3.0.0",
  "info" => %{
    "title" => "MyApp",
    "description" => "An example",
    "version" => "1.0.0"
  },
  "paths" => %{
    "/api/test" => %{
      "get" => %{
        "metadata" => %{"public" => true},
        "parameters" => [
          %{
            "in" => "header",
            "name" => "X-Request-ID",
            "schema" => %{
              "type" => "string",
              "format" => "uuid"
            }
          },
          %{
            "in" => "path",
            "name" => "user_id",
            "schema" => %{
              "type" => "string",
              "format" => "uuid"
            }
          },
          %{
            "in" => "query",
            "name" => "include",
            "schema" => %{
              "type" => "string"
            }
          }
        ],
        "responses" => %{
          "200" => %{
            "content" => %{
              "application/json" => %{
                "schema" => %{
                  "ref" => "#/components/schemas/MyResponse"
                }
              }
            }
          }
        },
        "requestBody" => %{
          "type" => "object",
          "properties" => %{
            "id" => %{"type" => "string", "format" => "uuid"}
          }
        },
        "tags" => ["foo", "bar"]
      }
    }
  },
  "components" => %{
    "schemas" => %{
      "MyResponse" => %{
        "type" => "object",
        "description" => "A response",
        "properties" => %{
          "id" => %{"type" => "string", "format" => "uuid"},
          "name" => %{"type" => "string", "description" => "The response name"}
        }
      }
    }
  }
}

Link to this section Summary

Functions

Generates a list of route docs and a map of response schemas. Passes both into the configured processor to generate the documentation JSON to be written to file

Inspects the Phoenix Router provided in your Rolodex.Config. Iterates through the list of routes to generate a Rolodex.Route for each. It will filter out any route(s) that match the filter(s) you provide in your config

Inspects the request and response parameter data for each Rolodex.Route. From these routes, it collects a unique list of Rolodex.Schema references, and serializes each via Rolodex.Schema.to_map/1. The serialized schemas will be passed along to a Rolodex.Processor behaviour

Runs Rolodex and writes out documentation to the specified destination

Link to this section Functions

Link to this function

generate_documentation(config)
generate_documentation(Rolodex.Config.t()) :: String.t()

Generates a list of route docs and a map of response schemas. Passes both into the configured processor to generate the documentation JSON to be written to file.

Link to this function

generate_routes(config)
generate_routes(Rolodex.Config.t()) :: [Rolodex.Route.t()]

Inspects the Phoenix Router provided in your Rolodex.Config. Iterates through the list of routes to generate a Rolodex.Route for each. It will filter out any route(s) that match the filter(s) you provide in your config.

Link to this function

generate_schemas(routes)
generate_schemas([Rolodex.Route.t()]) :: map()

Inspects the request and response parameter data for each Rolodex.Route. From these routes, it collects a unique list of Rolodex.Schema references, and serializes each via Rolodex.Schema.to_map/1. The serialized schemas will be passed along to a Rolodex.Processor behaviour.

Link to this function

run(config)
run(Rolodex.Config.t()) :: :ok | {:error, any()}

Runs Rolodex and writes out documentation to the specified destination