Packages
open_api_spex
3.5.1
3.22.3
3.22.2
3.22.1
3.22.0
3.21.5
3.21.4
3.21.3
3.21.2
3.21.1
3.21.0
3.20.1
3.20.0
3.19.1
3.19.0
3.18.3
3.18.2
3.18.1
3.18.0
3.17.3
3.17.2
3.17.1
3.17.0
3.16.4
3.16.3
3.16.2
3.16.1
3.16.0
3.15.0
3.14.0
3.13.0
3.12.0
3.11.0
3.10.0
3.9.0
3.8.0
3.7.0
3.6.0
3.5.2
3.5.1
3.5.0
3.4.0
3.3.0
3.2.1
3.2.0
3.1.0
3.0.0
2.3.1
2.3.0
2.2.0
2.1.1
2.1.0
2.0.0
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
Leverage Open Api Specification 3 (swagger) to document, test, validate and explore your Plug and Phoenix APIs.
Current section
Files
Jump to
Current section
Files
lib/open_api_spex/open_api.ex
defmodule OpenApiSpex.OpenApi do
@moduledoc """
Defines the `OpenApiSpex.OpenApi.t` type and the behaviour for application modules that
construct an `OpenApiSpex.OpenApi.t` at runtime.
"""
alias OpenApiSpex.{
Extendable,
Info,
Server,
Paths,
Components,
SecurityRequirement,
Tag,
ExternalDocumentation,
OpenApi,
MediaType,
Schema,
Example
}
@enforce_keys [:info, :paths]
defstruct openapi: "3.0.0",
info: nil,
servers: [],
paths: nil,
components: nil,
security: [],
tags: [],
externalDocs: nil,
extensions: nil
@typedoc """
[OpenAPI Object](https://swagger.io/specification/#oasObject)
This is the root document object of the OpenAPI document.
"""
@type t :: %OpenApi{
openapi: String.t(),
info: Info.t(),
servers: [Server.t()] | nil,
paths: Paths.t(),
components: Components.t() | nil,
security: [SecurityRequirement.t()] | nil,
tags: [Tag.t()] | nil,
externalDocs: ExternalDocumentation.t() | nil,
extensions: %{String.t() => any()} | nil
}
@doc """
A spec/0 callback function is required for use with the `OpenApiSpex.Plug.PutApiSpec` plug.
## Example
@impl OpenApiSpex.OpenApi
def spec do
%OpenApi{
servers: [
# Populate the Server info from a phoenix endpoint
Server.from_endpoint(MyAppWeb.Endpoint)
],
info: %Info{
title: "My App",
version: "1.0"
},
# populate the paths from a phoenix router
paths: Paths.from_router(MyAppWeb.Router)
}
|> OpenApiSpex.resolve_schema_modules() # discover request/response schemas from path specs
end
"""
@callback spec() :: t
@json_encoder Enum.find([Jason, Poison], &Code.ensure_loaded?/1)
def json_encoder, do: @json_encoder
for encoder <- [Poison.Encoder, Jason.Encoder] do
if Code.ensure_loaded?(encoder) do
defimpl encoder do
def encode(api_spec = %OpenApi{}, options) do
api_spec
|> to_json()
|> unquote(encoder).encode(options)
end
defp to_json(%Regex{source: source}), do: source
defp to_json(%object{} = value) when object in [MediaType, Schema, Example] do
value
|> Extendable.to_map()
|> Stream.map(fn
{:value, v} when object == Example -> {"value", to_json_example(v)}
{:example, v} -> {"example", to_json_example(v)}
{k, v} -> {to_string(k), to_json(v)}
end)
|> Stream.filter(fn
{_, nil} -> false
_ -> true
end)
|> Enum.into(%{})
end
defp to_json(value = %{__struct__: _}) do
value
|> Extendable.to_map()
|> to_json()
end
defp to_json(value) when is_map(value) do
value
|> Stream.map(fn {k, v} -> {to_string(k), to_json(v)} end)
|> Stream.filter(fn
{_, nil} -> false
_ -> true
end)
|> Enum.into(%{})
end
defp to_json(value) when is_list(value) do
Enum.map(value, &to_json/1)
end
defp to_json(nil), do: nil
defp to_json(true), do: true
defp to_json(false), do: false
defp to_json(value) when is_atom(value), do: to_string(value)
defp to_json(value), do: value
defp to_json_example(value = %{__struct__: _}) do
value
|> Extendable.to_map()
|> to_json_example()
end
defp to_json_example(value) when is_map(value) do
value
|> Stream.map(fn {k, v} -> {to_string(k), to_json_example(v)} end)
|> Enum.into(%{})
end
defp to_json_example(value) when is_list(value) do
Enum.map(value, &to_json_example/1)
end
defp to_json_example(value), do: to_json(value)
end
end
end
def from_map(map) do
OpenApi.Decode.decode(map)
end
end