Rolodex v0.10.1 Rolodex.Field

Shared logic for parsing parameter fields.

Rolodex.RequestBody, Rolodex.Response, and Rolodex.Schema each use this module to parse parameter metadata. new/1 transforms a bare map into a standardized parameter definition format. get_refs/1 takes a parameter map returned by `new/1 and traverses it, searching for any refs to a RequestBody, Response, or Schema.

Link to this section Summary

Functions

Takes a module and determines if it is a known shared module ref type: Headers, RequestBody, Response, or Schema

Traverses a formatted map returned by new/1 and returns a unique list of all refs to Rolodex.Response and Rolodex.Schema modules within

Parses parameter data into maps with a standardized shape

Link to this section Types

Link to this type

ref_type()
ref_type() :: :headers | :request_body | :response | :schema

Link to this section Functions

Link to this function

get_ref_type(mod)
get_ref_type(module()) :: ref_type() | :error

Takes a module and determines if it is a known shared module ref type: Headers, RequestBody, Response, or Schema.

Link to this function

get_refs(field)
get_refs(module() | map()) :: [module()]

Traverses a formatted map returned by new/1 and returns a unique list of all refs to Rolodex.Response and Rolodex.Schema modules within.

Examples

iex> defmodule NestedSchema do
...>   use Rolodex.Schema
...>
...>   schema "NestedSchema" do
...>     field :id, :uuid
...>   end
...> end
iex>
iex> defmodule TopSchema do
...>   use Rolodex.Schema
...>
...>   schema "TopSchema", desc: "An example" do
...>     # Atomic field with no description
...>     field :id, :uuid
...>
...>     # Atomic field with a description
...>     field :name, :string, desc: "The schema's name"
...>
...>     # A field that refers to another, nested object
...>     field :other, NestedSchema
...>
...>     # A field that is an array of items of one-or-more types
...>     field :multi, :list, of: [:string, NestedSchema]
...>
...>     # A field that is one of the possible provided types
...>     field :any, :one_of, of: [:string, NestedSchema]
...>   end
...> end
iex>
iex> # Searching for refs in a formatted map
iex> Rolodex.Field.new(type: :list, of: [TopSchema, NestedSchema])
...> |> Rolodex.Field.get_refs()
[Rolodex.FieldTest.NestedSchema, Rolodex.FieldTest.TopSchema]
Link to this function

new(opts)
new(atom() | module() | list() | map()) :: map()

Parses parameter data into maps with a standardized shape.

Every field within the map returned will have a type. Some fields, like lists and objects, have other data nested within. Other fields hold references (called refs) to Rolodex.RequestBody, Rolodex.Response or Rolodex.Schema modules.

You can think of the output as an AST of parameter data that a Rolodex.Processor behaviour can serialize into documentation output.

Examples

Parsing primitive data types (e.g. integer)

Valid options for a primitive are:

  • enum - a list of possible values
  • desc
  • default
  • format
  • maximum
  • minimum
  • required

    Creating a simple field with a primitive type

    iex> Rolodex.Field.new(:integer) %{type: :integer}

    With additional options

    iex> Rolodex.Field.new(type: :integer, desc: "My count", enum: [1, 2]) %{type: :integer, desc: "My count", enum: [1, 2]}

OpenAPI string formats

When serializing docs for OpenAPI (i.e. Swagger), the following primitive field types will be converted into string formats:

  • date
  • datetime
  • date-time
  • password
  • byte
  • binary
  • uuid
  • email
  • uri

For example:

# The following field
iex> Rolodex.Field.new(:date)
%{type: :date}

# Will be serialized like the following for OpenAPI docs
%{type: :string, format: :date}

Parsing collections: objects and lists

# Create an object
iex> Rolodex.Field.new(type: :object, properties: %{id: :uuid, name: :string})
%{
  type: :object,
  properties: %{
    id: %{type: :uuid},
    name: %{type: :string}
  }
}

# Shorthand for creating an object: a top-level map or keyword list
iex> Rolodex.Field.new(%{id: :uuid, name: :string})
%{
  type: :object,
  properties: %{
    id: %{type: :uuid},
    name: %{type: :string}
  }
}

# Create a list
iex> Rolodex.Field.new(type: :list, of: [:string, :uuid])
%{
  type: :list,
  of: [
    %{type: :string},
    %{type: :uuid}
  ]
}

# Shorthand for creating a list: a list of types
iex> Rolodex.Field.new([:string, :uuid])
%{
  type: :list,
  of: [
    %{type: :string},
    %{type: :uuid}
  ]
}

Arbitrary collections

Use the one_of type to describe a field that can be one of the provided types

iex> Rolodex.Field.new(type: :one_of, of: [:string, :uuid])
%{
  type: :one_of,
  of: [
    %{type: :string},
    %{type: :uuid}
  ]
}

Working with refs

iex> defmodule DemoSchema do
...>   use Rolodex.Schema
...>
...>   schema "DemoSchema" do
...>     field :id, :uuid
...>   end
...> end
iex>
iex> # Creating a field with a [`Rolodex.Schema`](Rolodex.Schema.html) as the top-level type
iex> Rolodex.Field.new(DemoSchema)
%{type: :ref, ref: Rolodex.FieldTest.DemoSchema}
iex>
iex> # Creating a collection field with various members, including a nested schema
iex> Rolodex.Field.new(type: :list, of: [:string, DemoSchema])
%{
  type: :list,
  of: [
    %{type: :string},
    %{type: :ref, ref: Rolodex.FieldTest.DemoSchema}
  ]
}