Current section

Files

Jump to
xcribe lib config.ex
Raw

lib/config.ex

defmodule Xcribe.Config do
@moduledoc false
alias Xcribe.{MissingInformationSource, UnknownFormat}
@valid_formats [:api_blueprint, :swagger]
@doc """
Return true if serve mode is enabled.
If no config was given the default is false.
To configure server mode:
config :xcribe, [
serve: true
]
"""
def serving?, do: get_xcribe_config(:serve, false) == true
@doc """
Return the file name to output generated documentation.
If no config was given the default names are `api_doc.apib` for Blueprint
format and `openapi.json` for Swagger format.
To configure output name:
config :xcribe, [
output: "custom_name.json"
]
"""
def output_file, do: get_xcribe_config(:output, default_output_file())
@doc """
Return the format for documentation.
Default is `:api_blueprint`.
To configure the documentation format:
config :xcribe, [
format: :swagger
]
"""
def doc_format, do: get_xcribe_config(:format, :api_blueprint)
@doc """
Return the format for documentation.
Default is `:api_blueprint`. If an invalid format is given an `Xcribe.UnknownFormat`
exception will raise.
"""
def doc_format!, do: :format |> get_xcribe_config(:api_blueprint) |> validate_doc_format()
@doc """
Return if Xcribe should document the specs.
It's determined by an env var `XCRIBE_ENV`. Don't matter the var content if
it's defined Xcribe will generate documentation.
The env var name can changed by configuration:
config :xcribe, [
env_var: "CUSTOM_ENV_NAME"
]
"""
def active?, do: !is_nil(System.get_env(env_var_name()))
@doc """
Return the information module with API information
To configure the source:
config :xcribe, [
information_source: YourApp.YouModuleInformation
]
"""
def xcribe_information_source, do: get_xcribe_config(:information_source)
@doc """
Return the information module with API information
If information source is not given an `Xcribe.MissingInformationSource` exception will raise.
"""
def xcribe_information_source! do
case get_xcribe_config(:information_source) do
nil -> raise MissingInformationSource
information_source -> information_source
end
end
@doc """
Return configured json library.
If no custom lib was configured the `Phoenix` configuration will be used.
To configure:
config :xcribe, [
json_library: Jason
]
"""
def json_library, do: get_xcribe_config(:json_library, Phoenix.json_library())
@doc """
Return ok if given configurations are valid.
If same invalid config was set an tuple with a list of erros will be returned.
"""
def check_configurations(configs \\ [:format, :information_source, :json_library, :serve]),
do: Enum.reduce(configs, :ok, &validate_config/2)
@format_message "Xcribe doesn't support the configured documentation format"
@format_instructions "Xcribe supports Swagger and Blueprint, configure as: `config :xcribe, format: :swagger`"
defp validate_config(:format, results) do
format = doc_format()
if format in @valid_formats do
results
else
add_error(results, :format, format, @format_message, @format_instructions)
end
end
@info_source_message "The configured module as information source is not using Xcribe macros"
@info_source_instructions "Add `use Xcribe, :information` on top of your module"
defp validate_config(:information_source, results) do
module = xcribe_information_source()
if {:api_info, 0} in module_functions(module) do
results
else
add_error(
results,
:information_source,
module,
@info_source_message,
@info_source_instructions
)
end
end
@json_lib_message "The configured json library doesn't implement the needed functions"
@json_lib_instructions "Try configure Xcribe with Jason or Poison `config :xcribe, json_library: Jason`"
defp validate_config(:json_library, results) do
lib = json_library()
if function_exported?(lib, :decode!, 2) do
results
else
add_error(results, :json_library, lib, @json_lib_message, @json_lib_instructions)
end
end
defp validate_config(:serve, results) do
if serving?() do
results
|> validate_serve_format()
|> validate_serve_output()
else
results
end
end
@serve_format_message "When serve config is true you must use swagger format"
@serve_format_instructions "You must use Swagger format: `config :xcribe, format: :swagger`"
defp validate_serve_format(results) do
format = doc_format()
if format == :swagger do
results
else
add_error(
results,
:format,
format,
@serve_format_message,
@serve_format_instructions
)
end
end
@serve_output_message "When serve config is true you must confiture output to \"priv/static\" folder"
@serve_output_instructions "You must configure output as: `config :xcribe, output: \"priv/static/doc.json\"`"
defp validate_serve_output(results) do
output = output_file()
if Regex.match?(~r/^priv\/static\/.*/, output) do
results
else
add_error(
results,
:output,
output,
@serve_output_message,
@serve_output_instructions
)
end
end
defp module_functions(module) do
apply(module, :__info__, [:functions])
rescue
UndefinedFunctionError -> []
end
defp add_error(:ok, key, value, msg, info), do: {:error, [{key, value, msg, info}]}
defp add_error({:error, errs}, key, value, msg, info),
do: {:error, [{key, value, msg, info} | errs]}
defp env_var_name, do: get_xcribe_config(:env_var, "XCRIBE_ENV")
defp validate_doc_format(format) when format in @valid_formats, do: format
defp validate_doc_format(format), do: raise(UnknownFormat, format)
defp default_output_file do
case doc_format() do
:api_blueprint -> "api_doc.apib"
:swagger -> "openapi.json"
_ -> ""
end
end
defp get_xcribe_config(key, default \\ nil),
do: Application.get_env(:xcribe, key, default)
end