populate_persistent_term.ex (2714B)
1 if Code.ensure_loaded?(:persistent_term) do 2 defmodule Absinthe.Phase.Schema.PopulatePersistentTerm do 3 @moduledoc false 4 5 alias Absinthe.Blueprint.Schema 6 7 def run(blueprint, opts) do 8 %{schema_definitions: [schema]} = blueprint 9 10 type_list = 11 for %{identifier: identifier} = type <- schema.type_definitions, 12 into: %{}, 13 do: {identifier, type.__reference__} 14 15 types_map = 16 schema.type_artifacts 17 |> Enum.flat_map(fn type -> [{type.identifier, type}, {type.name, type}] end) 18 |> Map.new() 19 20 referenced_types = 21 for type_def <- schema.type_definitions, 22 type_def.__private__[:__absinthe_referenced__], 23 into: %{}, 24 do: {type_def.identifier, type_def.name} 25 26 directive_list = 27 Map.new(schema.directive_definitions, fn type_def -> 28 {type_def.identifier, type_def.name} 29 end) 30 31 directives_map = 32 schema.directive_artifacts 33 |> Enum.flat_map(fn type -> [{type.identifier, type}, {type.name, type}] end) 34 |> Map.new() 35 36 prototype_schema = Keyword.fetch!(opts, :prototype_schema) 37 38 metadata = build_metadata(schema) 39 40 implementors = build_implementors(schema) 41 42 schema_content = %{ 43 __absinthe_types__: %{ 44 referenced: referenced_types, 45 all: type_list 46 }, 47 __absinthe_directives__: directive_list, 48 __absinthe_interface_implementors__: implementors, 49 __absinthe_prototype_schema__: prototype_schema, 50 __absinthe_type__: types_map, 51 __absinthe_directive__: directives_map, 52 __absinthe_reference__: metadata 53 } 54 55 schema_name = opts[:schema] || raise "no schema name provided" 56 57 put_schema(schema_name, schema_content) 58 59 {:ok, blueprint} 60 end 61 62 @dialyzer {:nowarn_function, [put_schema: 2]} 63 defp put_schema(schema_name, content) do 64 :persistent_term.put( 65 {Absinthe.Schema.PersistentTerm, schema_name}, 66 content 67 ) 68 end 69 70 def build_metadata(schema) do 71 for %{identifier: identifier} = type <- schema.type_definitions do 72 {identifier, type.__reference__} 73 end 74 end 75 76 defp build_implementors(schema) do 77 schema.type_definitions 78 |> Enum.filter(&match?(%Schema.InterfaceTypeDefinition{}, &1)) 79 |> Map.new(fn iface -> 80 implementors = 81 Schema.InterfaceTypeDefinition.find_implementors(iface, schema.type_definitions) 82 83 {iface.identifier, Enum.sort(implementors)} 84 end) 85 end 86 end 87 else 88 defmodule Absinthe.Phase.Schema.PopulatePersistentTerm do 89 def run(_, _) do 90 raise "This phase requires OTP >= 21.2" 91 end 92 end 93 end