Reusing Imported GraphQL Type Definitions in Absinthe

I’m trying to break apart my schema types into reusable definitions. I’d like to define, say, an Office in one place and use that in a UserTypes definition and CreatedThingsTypes definition i.e:

defmodule DerpWeb.Schema do
  use Absinthe.Schema

  import_types DerpWeb.Schema.UserTypes
  import_types DerpWeb.Schema.OfficeTypes
  import_types DerpWeb.Schema.CreatedThingTypes
  ...
end

and

defmodule DerpWeb.Schema.CreatedThingTypes do
  use Absinthe.Schema.Notation

  import DerpWeb.Schema.UserTypes
  import DerpWeb.Schema.OfficeTypes
  ...
  object :created_thing do
    @desc "The user associated with the created thing"
    field :user, :user, resolve: assoc(:user)
    @desc "The office associated with the created thing"
    field :office, :office, resolve: assoc(:office)
    ...
  end
end

When I try to compile this, I get stuff like:

/Users/tres/derp/lib/derp_web/schema.ex:5: Absinthe type identifier :office is not unique.

  References to types must be unique.

  > All types within a GraphQL schema must have unique names. No two provided
  > types may have the same name. No provided type may have a name which
  > conflicts with any built in types (including Scalar and Introspection
  > types).

  Reference: https://github.com/facebook/graphql/blob/master/spec/Section%203%20--%20Type%20System.md#type-system
 

If I don’t import_types from the types definition file, then I get an undefined type reference error:

  Office :office is not defined in your schema.

Am I missing something here, or is it just expected that we’ll be defining the entirety of the imported object in a single file, no matter whether that’s the top-level schema or an imported type definition file?

Thanks so much for your time and any help you can give!

Hey @tres. import_types should generally only be used from the root level Schema. The Schema is ultimately a single namespace, and no checking of types is done until the schema itself is built. In other words just do:

defmodule DerpWeb.Schema do
  use Absinthe.Schema

  import_types DerpWeb.Schema.UserTypes
  import_types DerpWeb.Schema.OfficeTypes
  import_types DerpWeb.Schema.CreatedThingTypes
  ...
end
defmodule DerpWeb.Schema.CreatedThingTypes do
  use Absinthe.Schema.Notation
  ...
  object :created_thing do
    @desc "The user associated with the created thing"
    field :user, :user, resolve: assoc(:user)
    @desc "The office associated with the created thing"
    field :office, :office, resolve: assoc(:office)
    ...
  end
end

And it’ll all just work.

5 Likes

Awesome.

Thanks, Ben!

1 Like