compile.ex (3468B)
1 defmodule Absinthe.Phase.Schema.Compile do 2 @moduledoc false 3 4 alias Absinthe.Blueprint.Schema 5 6 def run(blueprint, opts) do 7 module_name = Module.concat(opts[:schema], Compiled) 8 9 %{schema_definitions: [schema]} = blueprint 10 11 type_ast = build_types(schema.type_artifacts) 12 directive_ast = build_directives(schema.directive_artifacts) 13 14 type_list = 15 Map.new(schema.type_definitions, fn type_def -> 16 {type_def.identifier, type_def.name} 17 end) 18 19 referenced_types = 20 for type_def <- schema.type_definitions, 21 type_def.__private__[:__absinthe_referenced__], 22 into: %{}, 23 do: {type_def.identifier, type_def.name} 24 25 directive_list = 26 Map.new(schema.directive_definitions, fn type_def -> 27 {type_def.identifier, type_def.name} 28 end) 29 30 prototype_schema = Keyword.fetch!(opts, :prototype_schema) 31 32 metadata = build_metadata(schema) 33 34 implementors = build_implementors(schema) 35 36 body = 37 quote do 38 @moduledoc false 39 40 unquote_splicing(type_ast) 41 unquote_splicing(directive_ast) 42 43 def __absinthe_types__() do 44 __absinthe_types__(:referenced) 45 end 46 47 def __absinthe_types__(:referenced) do 48 unquote(Macro.escape(referenced_types)) 49 end 50 51 def __absinthe_types__(:all) do 52 unquote(Macro.escape(type_list)) 53 end 54 55 def __absinthe_directives__() do 56 unquote(Macro.escape(directive_list)) 57 end 58 59 def __absinthe_interface_implementors__() do 60 unquote(Macro.escape(implementors)) 61 end 62 63 def __absinthe_prototype_schema__() do 64 unquote(Macro.escape(prototype_schema)) 65 end 66 67 unquote_splicing(metadata) 68 end 69 70 Module.create(module_name, body, Macro.Env.location(__ENV__)) 71 72 {:ok, blueprint} 73 end 74 75 def build_metadata(schema) do 76 for type <- schema.type_definitions do 77 quote do 78 def __absinthe_reference__(unquote(type.identifier)) do 79 unquote(Macro.escape(type.__reference__)) 80 end 81 end 82 end 83 end 84 85 def build_types(types) do 86 for type <- types do 87 if !type.definition, 88 do: 89 raise(""" 90 No definition set! 91 #{inspect(type)} 92 """) 93 94 ast = Macro.escape(type, unquote: true) 95 96 quote do 97 def __absinthe_type__(unquote(type.identifier)) do 98 unquote(ast) 99 end 100 101 def __absinthe_type__(unquote(type.name)) do 102 unquote(ast) 103 end 104 end 105 end 106 |> Enum.concat([ 107 quote do 108 def __absinthe_type__(_type) do 109 nil 110 end 111 end 112 ]) 113 end 114 115 def build_directives(directives) do 116 for type <- directives do 117 ast = Macro.escape(type) 118 119 quote do 120 def __absinthe_directive__(unquote(type.identifier)) do 121 unquote(ast) 122 end 123 124 def __absinthe_directive__(unquote(type.name)) do 125 unquote(ast) 126 end 127 end 128 end 129 |> Enum.concat([ 130 quote do 131 def __absinthe_directive__(_type) do 132 nil 133 end 134 end 135 ]) 136 end 137 138 defp build_implementors(schema) do 139 schema.type_definitions 140 |> Enum.filter(&match?(%Schema.InterfaceTypeDefinition{}, &1)) 141 |> Map.new(fn iface -> 142 implementors = 143 Schema.InterfaceTypeDefinition.find_implementors(iface, schema.type_definitions) 144 145 {iface.identifier, Enum.sort(implementors)} 146 end) 147 end 148 end