Current section
Files
Jump to
Current section
Files
lib/maru_swagger.ex
defmodule MaruSwagger do
use Maru.Middleware
def init(opts) do
at = Keyword.fetch!(opts, :at)
Plug.Router.Utils.split(at)
end
def call(%Plug.Conn{path_info: path}=conn, path) do
header "access-control-allow-origin", "*"
generate |> json
end
def call(conn, _) do
conn
end
def generate do
for {mod, _} <- Maru.Config.servers do
generate_module(mod, [], nil)
end
|> List.flatten
|> Enum.sort(&(&1[:path] > &2[:path]))
|> to_swagger
end
defp generate_module(mod, path, version) do
version = version || mod.__version__
for ep <- mod.__endpoints__ do
params = extract_params({ep.method, ep.path, ep.param_context})
%{desc: ep.desc, method: ep.method, path: ep.path, params: params}
end
++
for {_, [router: m, resource: resource], _} <- mod.__routers__ do
generate_module(m, path ++ resource.path, version)
end
end
defp extract_params({"GET", _, []}), do: []
defp extract_params({"GET", path, params_list}) do
for param <- params_list do
if param.attr_name in path do
%{ in: "path" }
else
%{ in: "query" }
end
|> Map.merge %{
name: param.attr_name,
description: param.desc || "",
required: param.required,
type: decode_parser(param.parser)
}
end
end
defp extract_params({_, _, []}), do: []
defp extract_params({_, path, params_list}) do
{file_list, param_list} = Enum.split_while(
params_list,
fn(param) ->
decode_parser(param.parser) == "file"
end
)
p = for param <- param_list do
{param.attr_name, %{type: decode_parser(param.parser)}}
end |> Enum.into %{}
f = for param <- file_list do
%{ name: param.attr_name,
in: "formData",
description: "file",
required: true,
type: "file"
}
end
%{ name: "body",
in: "body",
description: "desc",
required: false,
}
|> fn r ->
if p == %{} do r else
r
|> put_in([:schema], %{})
|> put_in([:schema, :properties], p)
end
end.()
|> fn r ->
if f == [] do [r] else f end
end.()
|> fn r ->
if Enum.any? path, &is_atom/1 do
r ++ path |> Enum.filter(&is_atom/1) |> Enum.map &(%{name: &1, in: "path", required: true, type: "string"})
else r end
end.()
end
defp decode_parser(parser) do
parser |> to_string |> String.split(".") |> List.last |> String.downcase
end
defp to_swagger(list) do
paths = list |> List.foldr%{}, fn (%{desc: desc, method: method, path: url_list, params: params}, result) ->
url = join_path(url_list)
if Map.has_key? result, url do
result
else
result |> put_in([url], %{})
end
|> put_in([url, String.downcase(method)], %{
description: desc || "",
parameters: params,
})
end
[{mod, _}] = Maru.Config.servers
version = mod.__version__ || "0.0.1"
%{ swagger: "2.0",
info: %{ version: version,
title: mod,
},
paths: paths
}
end
defp join_path(path) do
[ "/" | for i <- path do
cond do
is_atom(i) -> "{#{i}}"
is_binary(i) -> i
true -> raise "unknow path type"
end
end ] |> Path.join
end
end