View Source Absinthe.Relay.Node.ParseIDs (absinthe_relay v1.5.2)
Parse node (global) ID arguments before they are passed to a resolver, checking the arguments against acceptable types.
For each argument:
- If a single node type is provided, the node ID in the argument map will be replaced by the ID specific to your application.
- If multiple node types are provided (as a list), the node ID in the
argument map will be replaced by a map with the node ID specific to your
application as
:id
and the parsed node type as:type
.
If a GraphQL null
value for an ID is found, it will be passed through as
nil
in either case, since no type can be associated with the value.
examples
Examples
Parse a node (global) ID argument :item_id
as an :item
type. This replaces
the node ID in the argument map (key :item_id
) with your
application-specific ID. For example, "123"
.
field :item, :item do
arg :item_id, non_null(:id)
middleware Absinthe.Relay.Node.ParseIDs, item_id: :item
resolve &item_resolver/3
end
Parse a node (global) ID argument :interface_id
into one of multiple node
types. This replaces the node ID in the argument map (key :interface_id
)
with map of the parsed node type and your application-specific ID. For
example, %{type: :thing, id: "123"}
.
field :foo, :foo do
arg :interface_id, non_null(:id)
middleware Absinthe.Relay.Node.ParseIDs, interface_id: [:item, :thing]
resolve &foo_resolver/3
end
Parse a nested structure of node (global) IDs. This behaves similarly to the examples above, but acts recursively when given a keyword list.
input_object :parent_input do
field :id, non_null(:id)
field :children, list_of(:child_input)
field :child, non_null(:child_input)
end
input_object :child_input do
field :id, non_null(:id)
end
mutation do
payload field :update_parent do
input do
field :parent, :parent_input
end
output do
field :parent, :parent
end
middleware Absinthe.Relay.Node.ParseIDs, parent: [
id: :parent,
children: [id: :child],
child: [id: :child]
]
resolve &resolve_parent/2
end
end
As with any piece of middleware, this can configured schema-wide using the
middleware/3
function in your schema. In this example all top level
query fields are made to support node IDs with the associated criteria in
@node_id_rules
:
defmodule MyApp.Schema do
# Schema ...
@node_id_rules [
item_id: :item,
interface_id: [:item, :thing],
]
def middleware(middleware, _, %Absinthe.Type.Object{identifier: :query}) do
[{Absinthe.Relay.Node.ParseIDs, @node_id_rules} | middleware]
end
def middleware(middleware, _, _) do
middleware
end
end
using-with-mutations
Using with Mutations
Important: Remember that middleware is applied in order. If you're
using middleware/3
to apply this middleware to a mutation field
(defined using the Absinthe.Relay.Mutation
macros) before the
Absinthe.Relay.Mutation
middleware, you need to include a wrapping
top-level :input
, since the argument won't be stripped out yet.
So, this configuration defined inside of a payload field
block:
mutation do
payload field :change_something do
# ...
middleware Absinthe.Relay.Node.ParseIDs, profile: [
user_id: :user
]
end
end
Needs to look like this if you put the ParseIDs
middleware first:
def middleware(middleware, %Absinthe.Type.Field{identifier: :change_something}, _) do
# Note the addition of the `input` level:
[{Absinthe.Relay.Node.ParseIDs, input: [profile: [user_id: :user]]} | middleware]
end
def middleware(middleware, _, _) do
middleware
end
If, however, you do a bit more advanced surgery to the middleware
list and insert Absinthe.Relay.Node.ParseIDs
after
Absinthe.Relay.Mutation
, you don't include the wrapping :input
.
compatibility-note-for-middleware-developers
Compatibility Note for Middleware Developers
If you're defining a piece of middleware that modifies field
arguments similar to Absinthe.Relay.Mutation
does (stripping the
outer input
argument), you need to set the private
:__parse_ids_root
so that this middleware can find the root schema
node used to apply its configuration. See Absinthe.Relay.Mutation
for an example of setting the value, and the find_schema_root!/2
function in this module for how it's used.
Link to this section Summary
Link to this section Types
Specs
full_result() :: %{type: atom(), id: simple_result()}
Specs
result() :: full_result() | simple_result()
Specs
The rules used to parse node ID arguments.
examples
Examples
Declare :item_id
as only valid with the :item
node type:
[
item_id: :item
]
Declare :item_id
be valid as either :foo
or :bar
types:
[
item_id: [:foo, :bar]
]
Note that using these two different forms will result in different argument
values being passed for :item_id
(the former, as a binary
, the latter
as a map
).
In the event that the ID is a null
, it will be passed-through as nil
.
See the module documentation for more details.
Specs
simple_result() :: nil | binary()
Link to this section Functions
Specs
find_schema_root!(Absinthe.Type.Field.t(), Absinthe.Resolution.t()) :: {{Absinthe.Type.Field.t() | Absinthe.Type.Argument.t(), String.t()}, (String.t() -> String.t())}