Packages
absinthe
1.2.4
1.11.0
1.10.2
1.10.1
1.10.0
1.9.1
1.9.0
1.8.0
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.8
1.6.7
retired
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.5
1.5.0-rc.4
1.5.0-rc.3
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.5.0-beta.2
1.5.0-beta.1
1.5.0-beta.0
1.5.0-alpha.4
1.5.0-alpha.3
1.5.0-alpha.2
1.5.0-alpha.1
1.5.0-alpha.0
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
retired
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.4.0-beta.5
1.4.0-beta.4
1.4.0-beta.3
1.4.0-beta.2
1.4.0-beta.1
1.3.2
1.3.1
1.3.0
1.3.0-rc.0
1.3.0-beta.2
1.3.0-beta.1
1.3.0-beta.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.0
1.2.0-beta.0
1.2.0-alpha0
1.2.0-alpha.2
1.2.0-alpha.1
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
0.5.2
0.5.1
0.5.0
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.2.3
0.2.2
0.2.1
0.1.0
GraphQL for Elixir
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/absinthe/schema/notation/writer.ex
defmodule Absinthe.Schema.Notation.Writer do
@moduledoc false
defstruct [
:env,
type_map: %{},
directive_map: %{},
errors: [],
type_functions: [],
directive_functions: [],
exports: [],
implementors: %{},
]
defmacro __before_compile__(env) do
info = build_info(env)
errors = Macro.escape info.errors
exports = Macro.escape info.exports
type_map = Macro.escape info.type_map
implementors = Macro.escape info.implementors
directive_map = Macro.escape info.directive_map
default_resolve_func = Module.get_attribute(env.module, :absinthe_custom_default_resolve)
[
quote do
def __absinthe_types__, do: unquote(type_map)
end,
info.type_functions,
quote do
def __absinthe_type__(_), do: nil
end,
quote do
def __absinthe_directives__, do: unquote(directive_map)
end,
info.directive_functions,
quote do
def __absinthe_directive__(_), do: nil
end,
quote do
def __absinthe_errors__, do: unquote(errors)
def __absinthe_interface_implementors__, do: unquote(implementors)
def __absinthe_exports__, do: unquote(exports)
end,
custom_default_resolve(default_resolve_func),
quote do
def resolution_plugins do
unquote(Absinthe.Resolution.Plugin.defaults())
end
defoverridable(resolution_plugins: 0)
end ]
end
def build_info(env) do
descriptions =
env.module
|> Module.get_attribute(:absinthe_descriptions)
|> Map.new
definitions =
env.module
|> Module.get_attribute(:absinthe_definitions)
|> Enum.map(&update_description(&1, descriptions))
{definitions, errors} =
{definitions, []}
|> Absinthe.Schema.Rule.FieldImportsExist.check
|> Absinthe.Schema.Rule.NoCircularFieldImports.check
info = %__MODULE__{env: env, errors: errors}
Enum.reduce(definitions, info, &do_build_info/2)
end
defp custom_default_resolve(nil) do
quote do
def __absinthe_custom_default_resolve__, do: nil
end
end
defp custom_default_resolve(func) do
quote do
def __absinthe_custom_default_resolve__, do: unquote(func)
end
end
defp type_functions(definition) do
ast = build(:type, definition)
identifier = definition.identifier
name = definition.attrs[:name]
quote do
def __absinthe_type__(unquote(identifier)), do: unquote(ast)
def __absinthe_type__(unquote(name)), do: __absinthe_type__(unquote(identifier))
end
end
defp directive_functions(definition) do
ast = build(:directive, definition)
identifier = definition.identifier
name = definition.attrs[:name]
quote do
def __absinthe_directive__(unquote(identifier)), do: unquote(ast)
def __absinthe_directive__(unquote(name)), do: __absinthe_directive__(unquote(identifier))
end
end
# Type import reference
defp build(:type, %{source: source, builder: nil} = definition) do
quote bind_quoted: [source: source, identifier: definition.identifier] do
source.__absinthe_type__(identifier)
end
end
# Directive import reference
defp build(:directive, %{source: source, builder: nil} = definition) do
quote bind_quoted: [source: source, identifier: definition.identifier] do
source.__absinthe_directive__(identifier)
end
end
# Type/Directive definition
defp build(_, %{source: nil, builder: builder} = definition) do
builder.build(definition)
end
defp directive_name_error(definition) do
%{
rule: Absinthe.Schema.Rule.TypeNamesAreUnique,
location: %{file: definition.file, line: definition.line},
data: %{artifact: "Absinthe directive identifier", value: definition.identifier}
}
end
defp type_name_error(artifact, value, definition) do
%{
rule: Absinthe.Schema.Rule.TypeNamesAreUnique,
location: %{file: definition.file, line: definition.line},
data: %{artifact: artifact, value: value}
}
end
defp directive_errors(definition, state) do
case Map.has_key?(state.directive_map, definition.identifier) do
true ->
[directive_name_error(definition)]
false ->
[]
end
end
defp type_errors(definition, state) do
[
if Map.has_key?(state.type_map, definition.identifier) do
type_name_error("Absinthe type identifier", definition.identifier, definition)
end,
if Enum.member?(Map.values(state.type_map), definition.attrs[:name]) do
type_name_error("Type name", definition.attrs[:name], definition)
end,
]
|> Enum.reject(&is_nil/1)
end
defp update_description(definition, descriptions) do
case Map.get(descriptions, definition.identifier) do
nil -> definition
desc -> Map.update!(definition, :attrs, &Keyword.put(&1, :description, desc))
end
end
defp do_build_info(%{category: :directive} = definition, info) do
errors = directive_errors(definition, info)
info
|> update_directive_map(definition)
|> update_directive_functions(definition, errors)
|> update_exports(definition)
|> update_errors(errors)
end
defp do_build_info(%{category: :type} = definition, info) do
errors = type_errors(definition, info)
info
|> update_type_map(definition)
|> update_type_functions(definition, errors)
|> update_implementors(definition)
|> update_exports(definition)
|> update_errors(errors)
end
defp update_directive_map(info, definition) do
Map.update!(info, :directive_map, &Map.put(&1, definition.identifier, definition.attrs[:name]))
end
defp update_directive_functions(info, definition, []) do
Map.update!(info, :directive_functions, &[directive_functions(definition) | &1])
end
defp update_type_map(info, definition) do
Map.update!(info, :type_map, &Map.put(&1, definition.identifier, definition.attrs[:name]))
end
defp update_type_functions(info, definition, []) do
Map.update!(info, :type_functions, &[type_functions(definition) | &1])
end
defp update_type_functions(info, _definition, _errors), do: info
defp update_implementors(info, definition) do
implementors = definition.attrs[:interfaces]
|> List.wrap
|> Enum.reduce(info.implementors, fn
iface, implementors ->
Map.update(implementors, iface, [definition.identifier], &[definition.identifier | &1])
end)
%{info | implementors: implementors}
end
defp update_exports(info, definition) do
exports = (if Keyword.get(definition.opts, :export, definition.source != Absinthe.Type.BuiltIns) do
[definition.identifier | info.exports]
else
info.exports
end)
%{info | exports: exports}
end
defp update_errors(info, errors) do
%{info | errors: errors ++ info.errors}
end
end