AbsintheUtils.Middleware.ArgLoader (absinthe_utils v0.0.1-main-b324c3236f3971cfc05577e796dca31477a46391)

View Source

Absinthe middleware for loading entities in field arguments.

This middleware should be defined before resolve. It will manipulate the arguments before they are passed to the resolver function.

As configuration it accepts a map of original argument names (or path) to a keyword list, containing:

  • new_name: the new key to push the loaded entity into, can be a list of atoms to push the entity into a nested map. (optional, defaults to the argument name - the key of the map configuration).
  • load_function: the function used to load the argument into an entity. As an input accepts two arguments:
    • context: the context of the current resolution (prior to any modifications of the current middleware).
    • input_value: the value received in the value of argument_name. The function should return the entity or a list of entities. nil or an empty list when not found .
  • nil_is_not_found: whether to consider nil as a not found value. (optional, defaults to true).

Examples

query do
  field :user, :user do
    arg(:id, :id)

    # Add the middleware before your resolver
    middleware(
      ArgLoader,
      %{
        id: [
          new_name: :user,
          load_function: fn _context, id ->
            get_user_by_id(id)
          end,
          nil_is_not_found: false
        ]
      }
    )

    resolve(fn _, arguments, _ ->
      {:ok, Map.get(arguments, :user)}
    end)
  end

This will define a user query that accepts an id input. Before calling the resolver,

List of entities

ArgLoader can also be used to load a list_of arguments:

query do
  field :users, non_null(list_of(:user)) do
    arg(:ids, non_null(list_of(:id)))

    middleware(
      ArgLoader,
      %{
        ids: [
          new_name: :users,
          load_function: fn _context, ids ->
            ids
            |> get_users_by_id()
            |> AbsintheUtils.Helpers.Sorting.sort_alike(ids, & &1.id)
          end
        ]
      }
    )

    resolve(fn _, params, _ ->
      {:ok, Map.get(params, :users)}
    end)
  end
end

Deep nested arguments

Using ArgLoader to load and rename deep nested arguments:

input_object :complex_input_object do
  field(:user_id, :id)
end

query do
  field :users, :boolean do
    arg(:input, :complex_input_object)

    middleware(
      ArgLoader,
      %{
        [:input, :user_id] => [
          new_name: [:loaded_entities, :user],
          load_function: fn _context, user_id ->
            get_user_by_id(user_id)
          end
        ]
      }
    )

    resolve(fn _, params, _ ->
      # params.loaded_entities.user will contain the loaded user
      {:ok, true}
    end)
  end
end

Note the use of AbsintheUtils.Helpers.Sorting.sort_alike/2 to ensure the returned list of entities from the repository is sorted according to the user's input.