variables.ex (2430B)
1 defmodule Absinthe.Phase.Document.Variables do 2 @moduledoc false 3 4 # Provided a set of variable values: 5 # 6 # - Set the `variables` field on the `Blueprint.Document.Operation.t` to the reconciled 7 # mapping of variable values, supporting defined default values. 8 # 9 # ## Examples 10 # 11 # Given a GraphQL document that looks like: 12 # 13 # ```graphql 14 # query Item($id: ID!, $text = String = "Another") { 15 # item(id: $id, category: "Things") { 16 # name 17 # } 18 # } 19 # ``` 20 # 21 # And this phase configuration: 22 # 23 # ``` 24 # run(blueprint, %{"id" => "1234"}) 25 # `` 26 # 27 # - The operation's `variables` field would have an `"id"` value set to 28 # `%Blueprint.Input.String{value: "1234"}` 29 # - The operation's `variables` field would have an `"text"` value set to 30 # `%Blueprint.Input.String{value: "Another"}` 31 # 32 # ``` 33 # run(blueprint, %{}) 34 # ``` 35 # 36 # - The operation's `variables` field would have an `"id"` value set to 37 # `nil` 38 # - The operation's `variables` field would have an `"text"` value set to 39 # `%Blueprint.Input.String{value: "Another"}` 40 # 41 # Note that no validation occurs in this phase. 42 43 use Absinthe.Phase 44 alias Absinthe.Blueprint 45 46 @spec run(Blueprint.t(), Keyword.t()) :: {:ok, Blueprint.t()} 47 def run(input, options \\ []) do 48 variables = options[:variables] || %{} 49 {:ok, update_operations(input, variables)} 50 end 51 52 def update_operations(input, variables) do 53 operations = 54 for op <- input.operations do 55 update_operation(op, variables) 56 end 57 58 %{input | operations: operations} 59 end 60 61 def update_operation(%{variable_definitions: variable_definitions} = operation, variables) do 62 {variable_definitions, provided_values} = 63 Enum.map_reduce(variable_definitions, %{}, fn node, acc -> 64 provided_value = calculate_value(node, variables) 65 66 { 67 %{node | provided_value: provided_value}, 68 Map.put(acc, node.name, provided_value) 69 } 70 end) 71 72 %{operation | variable_definitions: variable_definitions, provided_values: provided_values} 73 end 74 75 defp calculate_value(node, variables) do 76 case Map.fetch(variables, node.name) do 77 :error -> 78 node.default_value 79 80 {:ok, value} -> 81 value 82 |> preparse_nil 83 |> Blueprint.Input.parse() 84 end 85 end 86 87 defp preparse_nil(nil), do: %Blueprint.Input.Null{} 88 defp preparse_nil(other), do: other 89 end