Packages

Something to help you consume that sweet, sweet absinthe.

Current section

Files

Jump to
goblet lib goblet.ex
Raw

lib/goblet.ex

defmodule Goblet do
@moduledoc """
Documentation for Goblet.
"""
defmacro __using__(from: path) do
# support module attributes as path? https://stackoverflow.com/questions/54000082/pass-module-attribute-as-an-argument-to-macros
schema = path |> File.read!() |> Jason.decode!() |> Map.get("__schema") |> Macro.escape()
quote bind_quoted: [path: path, schema: schema] do
@external_resource path
defmacro query(name, do: expr) do
schema = unquote(schema |> Macro.escape())
fn_name = name |> Macro.underscore() |> String.to_atom()
body = Goblet.build(:query, name, expr, schema, fn_name, __CALLER__)
if body == :error do
reraise "There are errors in your query", Macro.Env.stacktrace(__CALLER__)
end
# TODO:: determine types of pinned variables and create a typespec here
quote do
def unquote(fn_name)(variables \\ %{}) do
%{
"operationName" => unquote(name),
"query" => unquote(body),
"variables" => variables
}
end
if function_exported?(unquote(__MODULE__), :process, 2) do
def unquote(fn_name)(variables, ctx) do
apply(__MODULE__, unquote(fn_name), [variables])
|> unquote(__MODULE__).process(ctx)
end
end
end
end
defmacro mutation(name, do: expr) do
schema = unquote(schema |> Macro.escape())
fn_name = name |> Macro.underscore() |> String.to_atom()
body = Goblet.build(:mutation, name, expr, schema, fn_name, __CALLER__)
if body == :error do
reraise "There are errors in your mutation", Macro.Env.stacktrace(__CALLER__)
end
# TODO:: determine types of pinned variables and create a typespec here
quote do
def unquote(fn_name)(variables \\ %{}) do
%{
"operationName" => unquote(name),
"query" => unquote(body),
"variables" => variables
}
end
if function_exported?(unquote(__MODULE__), :process, 2) do
def unquote(fn_name)(variables, ctx) do
apply(__MODULE__, unquote(fn_name), [variables])
|> unquote(__MODULE__).process(ctx)
end
end
end
end
defmacro __using__(_) do
quote do
import unquote(__MODULE__), only: [query: 2, mutation: 2]
end
end
end
end
def build(type, name, expr, schema, fn_name, caller) do
Goblet.Parser.parse(expr, type, schema)
|> Goblet.Validator.validate({fn_name, caller})
|> Goblet.Printer.print(type, name)
end
end