View Source Absinthe.Adapter behaviour (absinthe v1.7.6)

Absinthe supports an adapter mechanism that allows developers to define their schema using one code convention (eg, snake_cased fields and arguments), but accept query documents and return results (including names in errors) in another (eg, camelCase).

Adapters aren't a part of GraphQL, but a utility that Absinthe adds so that both client and server can use use conventions most natural to them.

Absinthe ships with four adapters:

To set an adapter, you pass a configuration option at runtime:

For Absinthe.run/3:

Absinthe.run(
  query,
  MyApp.Schema,
  adapter: YourApp.Adapter.TheAdapterName
)

For Absinthe.Plug:

forward "/api",
  to: Absinthe.Plug,
  init_opts: [schema: MyAppWeb.Schema, adapter: YourApp.Adapter.TheAdapterName]

For GraphiQL:

forward "/graphiql",
  to: Absinthe.Plug.GraphiQL,
  init_opts: [schema: MyAppWeb.Schema, adapter: YourApp.Adapter.TheAdapterName]

Check Absinthe.Plug for full documentation on using the Plugs

Notably, this means you're able to switch adapters on case-by-case basis. In a Phoenix application, this means you could even support using different adapters for different clients.

A custom adapter module must merely implement the Absinthe.Adapter protocol, in many cases with use Absinthe.Adapter and only overriding the desired functions.

Writing Your Own

All you may need to implement in your adapter is to_internal_name/2 and to_external_name/2.

Check out Absinthe.Adapter.LanguageConventions for a good example.

Note that types that are defined external to your application (including the introspection types) may not be compatible if you're using a different adapter.

Summary

Types

The lexical role of a name within the document/schema.

t()

Callbacks

Convert a name from an internal name to an external name.

Convert a name from an external name to an internal name.

Types

@type role_t() :: :operation | :field | :argument | :result | :type | :directive

The lexical role of a name within the document/schema.

@type t() :: module()

Callbacks

Link to this callback

to_external_name(arg1, role_t)

View Source
@callback to_external_name(binary() | nil, role_t()) :: binary() | nil

Convert a name from an internal name to an external name.

Examples

Remove the role-prefix (the inverse of what we did in to_internal_name/2 above):

def to_external_name(internal_name, role) do
  internal_name
  |> String.replace(~r/^#{role}_/, "")
end
Link to this callback

to_internal_name(arg1, role_t)

View Source
@callback to_internal_name(binary() | nil, role_t()) :: binary() | nil

Convert a name from an external name to an internal name.

Examples

Prefix all names with their role, just for fun!

def to_internal_name(external_name, role) do
  role_name = role |> to_string
  role_name <> "_" <> external_name
end