field.ex (6664B)
1 defmodule Absinthe.Type.Field do 2 alias Absinthe.Type 3 4 @moduledoc """ 5 Used to define a field. 6 7 Usually these are defined using `Absinthe.Schema.Notation.field/4` 8 9 See the `t` type below for details and examples of how to define a field. 10 """ 11 12 alias Absinthe.Type 13 alias Absinthe.Type.Deprecation 14 15 use Type.Fetch 16 17 @typedoc """ 18 A resolver function. 19 20 See the `Absinthe.Type.Field.t` explanation of `:resolve` for more information. 21 """ 22 @type resolver_t :: (%{atom => any}, Absinthe.Resolution.t() -> result) 23 24 @typedoc """ 25 The result of a resolver. 26 """ 27 @type result :: ok_result | error_result | middleware_result 28 29 @typedoc """ 30 A complexity function. 31 32 See the `Absinthe.Type.Field/t` explanation of `:complexity` for more 33 information. 34 """ 35 @type complexity_t :: 36 (%{atom => any}, non_neg_integer -> non_neg_integer) 37 | (%{atom => any}, non_neg_integer, Absinthe.Complexity.t() -> non_neg_integer) 38 | {module, atom} 39 | non_neg_integer 40 41 @type ok_result :: {:ok, any} 42 @type error_result :: {:error, error_value} 43 @type middleware_result :: {:middleware, Absinthe.Middleware.spec(), term} 44 45 @typedoc """ 46 An error message is a human-readable string describing the error that occurred. 47 """ 48 @type error_message :: String.t() 49 50 @typedoc """ 51 Any serializable value. 52 """ 53 @type serializable :: any 54 55 @typedoc """ 56 A custom error may be a `map` or a `Keyword.t`, but must contain a `:message` key. 57 58 Note that the values that make up a custom error must be serializable. 59 """ 60 @type custom_error :: 61 %{required(:message) => error_message, optional(atom) => serializable} | Keyword.t() 62 63 @typedoc """ 64 An error value is a simple error message, a custom error, or a list of either/both of them. 65 """ 66 @type error_value :: 67 error_message | custom_error | [error_message | custom_error] | serializable 68 69 @typedoc """ 70 The configuration for a field. 71 72 * `:name` - The name of the field, usually assigned automatically by 73 the `Absinthe.Schema.Notation.field/4`. Including this option will bypass the snake_case to camelCase conversion. 74 * `:description` - Description of a field, useful for introspection. 75 * `:deprecation` - Deprecation information for a field, usually 76 set-up using `Absinthe.Schema.Notation.deprecate/1`. 77 * `:type` - The type the value of the field should resolve to 78 * `:args` - The arguments of the field, usually created by using `Absinthe.Schema.Notation.arg/2`. 79 * `:resolve` - The resolution function. See below for more information. 80 * `:complexity` - The complexity function. See below for more information. 81 * `:default_value` - The default value of a field. Note this is not used during resolution; only fields that are part of an `Absinthe.Type.InputObject` should set this value. 82 83 ## Resolution Functions 84 85 ### Default 86 87 If no resolution function is given, the default resolution function is used, 88 which is roughly equivalent to this: 89 90 {:ok, Map.get(parent_object, field_name)} 91 92 This is commonly use when listing the available fields on a 93 `Absinthe.Type.Object` that models a data record. For instance: 94 95 ``` 96 object :person do 97 description "A person" 98 99 field :first_name, :string 100 field :last_name, :string 101 end 102 ``` 103 ### Custom Resolution 104 105 When accepting arguments, however, you probably need to use them for 106 something. Here's an example of defining a field that looks up a list of 107 users for a given `location_id`: 108 ``` 109 query do 110 field :users, :person do 111 arg :location_id, non_null(:id) 112 113 resolve fn %{location_id: id}, _ -> 114 {:ok, MyApp.users_for_location_id(id)} 115 end 116 end 117 end 118 ``` 119 120 Custom resolution functions are passed two arguments: 121 122 1. A map of the arguments for the field, filled in with values from the 123 provided query document/variables. 124 2. An `Absinthe.Resolution` struct, containing the execution environment 125 for the field (and useful for complex resolutions using the resolved source 126 object, etc) 127 128 ## Complexity function 129 130 ### Default 131 132 If no complexity function is given, the default complexity function is used, 133 which is equivalent to: 134 135 fn(_, child_complexity) -> 1 + child_complexity end 136 137 ### Custom Complexity 138 139 When accepting arguments, however, you probably need to use them for 140 something. Here's an example of defining a field that looks up at most 141 `limit` users: 142 ``` 143 query do 144 field :users, :person do 145 arg :limit, :integer 146 147 complexity fn %{limit: limit}, child_complexity -> 148 10 + limit * child_complexity 149 end 150 end 151 end 152 ``` 153 154 An optional third argument, `Absinthe.Complexity` struct, provides extra 155 information. Here's an example of changing the complexity using the context: 156 ``` 157 query do 158 field :users, :person do 159 arg :limit, :integer 160 161 complexity fn _, child_complexity, %{context: %{admin: admin?}} -> 162 if admin?, do: 0, else: 10 + limit * child_complexity 163 end 164 end 165 end 166 ``` 167 168 Custom complexity functions are passed two or three arguments: 169 170 1. A map of the arguments for the field, filled in with values from the 171 provided query document/variables. 172 2. A non negative integer, which is total complexity of the child fields. 173 3. An `Absinthe.Complexity` struct with information about the context of the 174 field. This argument is optional when using an anonymous function. 175 176 Alternatively complexity can be an integer greater than or equal to 0: 177 ``` 178 query do 179 field :users, :person do 180 complexity 10 181 end 182 end 183 ``` 184 185 """ 186 @type t :: %__MODULE__{ 187 identifier: atom, 188 name: binary, 189 description: binary | nil, 190 type: Type.identifier_t(), 191 deprecation: Deprecation.t() | nil, 192 default_value: any, 193 args: %{(binary | atom) => Absinthe.Type.Argument.t()} | nil, 194 middleware: [], 195 complexity: complexity_t | nil, 196 __private__: Keyword.t(), 197 definition: module, 198 __reference__: Type.Reference.t() 199 } 200 201 defstruct identifier: nil, 202 name: nil, 203 description: nil, 204 type: nil, 205 deprecation: nil, 206 args: %{}, 207 # used by subscription fields 208 config: nil, 209 # used by mutation fields 210 triggers: [], 211 middleware: [], 212 complexity: nil, 213 default_value: nil, 214 __private__: [], 215 definition: nil, 216 __reference__: nil 217 218 @doc false 219 defdelegate functions, to: Absinthe.Blueprint.Schema.FieldDefinition 220 end