defmodule Mix.Tasks.Oas.Gen.Plug do
@shortdoc "Generates Router and Plug modules from OpenAPI Specification"
@moduledoc """
Generates router and plug handlers for a proper OpenAPI Specification in YAML or JSON file.
mix oas.gen.plug --file path/to/openapi.yaml
mix oas.gen.plug --file path/to/openapi.yml
mix oas.gen.plug --file path/to/openapi.json
The arguments of `oas.gen.plug` mix task:
* `--file`, required, the completed path to the specification file in YAML or JSON format.
* `--router`, optional, the generated router's module alias, by default it is `Router` (the full module name is `Oasis.Gen.Router` by default), for example we set `--router Hello.MyRouter` meanwhile there is no other special name space defined, the final router module is `Oasis.Gen.Hello.MyRouter` in `/lib/oasis/gen/hello/my_router.ex` path.
* `--name-space`, optional, the generated all modules' name space, by default it is `Oasis.Gen`, this argument will always override the name space from the input `--file` if any `"x-oasis-name-space"` field(s) defined.
* `--force`, optional, forces creation without a shell prompt.
* `--quiet`, optional, does not log command output.
"""
use Mix.Task
@parse_opts [
switches: [
file: :string,
router: :string,
name_space: :string,
body_reader: :string,
force: :boolean,
quiet: :boolean
],
aliases: [f: :file, r: :router, n: :name_space, q: :quiet]
]
def run(args) do
if Mix.Project.umbrella?() do
Mix.raise("mix oas.gen.plug can only be run inside an application directory")
end
Mix.shell().info("Generates Router and Plug modules from OAS")
paths = Mix.Oasis.generator_paths()
opts = parse_opts(args)
files = build(opts)
Mix.Oasis.copy_from(paths, "priv/templates/oas.gen.plug", files, opts)
end
defp build(opts) do
%ExJsonSchema.Schema.Root{schema: schema} = Oasis.Spec.read(opts[:file])
opts = Keyword.take(opts, [:router, :name_space, :body_reader])
Mix.Oasis.new(schema, opts)
end
defp parse_opts(args) do
{opts, _, _} = OptionParser.parse(args, @parse_opts)
validate_opts!(opts)
end
defp validate_opts!(opts) do
oas_file_path = Keyword.get(opts, :file)
if oas_file_path == nil do
raise_with_help("Expected input `--file` option to be a valid path to a yaml/json file")
else
if File.exists?(oas_file_path) do
opts
else
raise_with_help("Could not find the file in `#{oas_file_path}` path")
end
end
end
defp raise_with_help(msg) do
Mix.raise("""
#{msg}
For example:
mix oas.gen.plug --file path/to/file.yaml
mix oas.gen.plug --file path/to/file.json
mix oas.gen.plug --file path/to/file.yml --name-space Test --router Router
By default the `--name-space` is "Oasis.Gen", and by default
the `--router` is "Router", these two options are optional.
""")
end
end