Current section

Files

Jump to
graphql lib mix tasks compile.graphql.ex
Raw

lib/mix/tasks/compile.graphql.ex

defmodule Mix.Tasks.Compile.Graphql do
use Mix.Task
@recursive true
@manifest ".compile.graphql"
@moduledoc """
Compiles `.graphql` files which have changed since the last generation.
Currently only handles schema files, but will support queries in future.
To use this you need to add the `:graphql` compiler to the front ofyour compiler chain.
This just needs to be anywhere before the Elixir compiler because we are
generating Elixir code.
In your `mix.exs` project in a Phoenix project for example:
compilers: [:phoenix, :graphql] ++ Mix.compilers
You also need to tell the GraphQL compiler which files to pick up.
In `config/config.exs`
config :graphql, source_path: "web/graphql/**/*_schema.graphql"
## Command line options
* `--force` - forces compilation regardless of modification times
"""
@spec run(OptionParser.argv) :: :ok | :noop
def run(args) do
{opts, _, _} = OptionParser.parse(args, switches: [force: :boolean])
graphql_schema_glob = Application.get_env(:graphql, :source_path)
changed =
graphql_schema_glob
|> Path.wildcard
|> compile_all(opts)
if Enum.any?(changed, &(&1 == :ok)) do
:ok
else
:noop
end
end
@doc """
Returns GraphQL manifests.
"""
def manifests, do: [manifest]
defp manifest, do: Path.join(Mix.Project.manifest_path, @manifest)
def compile_all(schema_paths, opts) do
Enum.map schema_paths, &(compile(&1, opts))
end
def compile(schema_path, opts) do
base_filename = extract_file_prefix(schema_path)
target = base_filename <> ".ex"
if opts[:force] || Mix.Utils.stale?([schema_path], [target]) do
Mix.shell.info "Compiling `#{schema_path}` to `#{target}`"
with target,
{:ok, source_schema} <- File.read(schema_path),
{:ok, generated_schema} <- GraphQL.Schema.Generator.generate(base_filename, source_schema),
do: File.write!(target, generated_schema)
else
Mix.shell.info "Skipping `#{schema_path}`"
end
end
def extract_file_prefix(path) do
Path.join(Path.dirname(path), Path.basename(path, ".graphql"))
end
end