defmodule Mix.Tasks.Absinthe.Gen.Query do
@shortdoc "Generates an absinthe query schema and inserts the record in the base schema.ex"
@moduledoc """
Generates an Absinthe Query
### Options
#{NimbleOptions.docs(AbsintheGenerator.Query.definitions())}
### Specifying Queries
The following format can be used to specify queries
```bash
query_name:return_type:arg_name:arg_type:arg_name:arg_type:ResolverModule.resolver_function
```
you can also specify middleware before or after the resolver
### Example
```bash
mix absinthe.gen.query
summoners:list_of(return_type):arg_a:string:arg_b:non_null(:integer):Resolvers.Summoner.list_all
summoner:return_type:id:id:Resolvers.Summoner.find
summoner:return_type:middleware:IDToIntegerMiddlewareid:id:middleware:AuthMiddleware:Resolvers.Summoner.find:middleware:ChangesetErrorFormatter
--app-name MyApp
--query-name students
--moduledoc "this is the test"
```
"""
use Mix.Task
alias Mix.AbsintheGeneratorUtils
alias Mix.AbsintheGeneratorUtils.SchemaFieldParser
@query_regex ~r/^([a-z]+|list_of\([^\(\)]+\))+[A-Za-z\.]+(:middleware:[A-Za-z]+)?+$/
def run(args) do
AbsintheGeneratorUtils.ensure_not_in_umbrella!("absinthe.gen.query")
{args, extra_args} = AbsintheGeneratorUtils.parse_path_opts(args, [
path: :string,
app_name: :string,
moduledoc: :string,
query_name: :string
])
parsed_query_functions = extra_args
|> validate_query_string
|> SchemaFieldParser.parse_fields
args
|> Map.new
|> Map.put(:queries, parsed_query_functions)
|> serialize_to_query_struct
|> IO.inspect
|> AbsintheGenerator.Query.run
|> AbsintheGeneratorUtils.write_template(path_from_args(args))
end
defp path_from_args(args) do
Keyword.get(
args,
:path,
"./lib/#{Macro.underscore(args[:app_name])}_web/queries/#{Macro.underscore(args[:query_name])}.ex"
)
end
defp validate_query_string(query_parts) do
if query_parts === [] or Enum.all?(query_parts, &Regex.match?(@query_regex, &1)) do
query_parts
else
Mix.raise("""
\n
Query format isn't setup properly and must match the following regex
#{inspect @query_regex}
Example:
summoners:list_of(return_type):arg_a:string:arg_b:non_null(:integer):Resolvers.Summoner.list_all
summoner:return_type:id:id:Resolvers.Summoner.find
summoner:return_type:middleware:IDToIntegerMiddlewareid:id:middleware:AuthMiddleware:Resolvers.Summoner.find:middleware:ChangesetErrorFormatter
""")
end
end
defp serialize_to_query_struct(params) do
%AbsintheGenerator.Query{
app_name: params[:app_name],
moduledoc: params[:moduledoc],
query_name: params[:query_name],
queries: params[:queries]
}
end
end