Skip to content

Commit

Permalink
Fix type resolution by recursing prototypes
Browse files Browse the repository at this point in the history
This fixes an issue when you have types declared in a Prototype (such as
input_object input types for a directive). Previously type resolution
would look on the Schema, but not the Prototype for the type
definitions.

You _could_ workaround this by duplicating your type definition into
both the Schema and the Prototype. This makes me somewhat curious if
there is a better way to fix this, in that the code that was trying to
resolve the type here shouldn't be resolving it on the Schema, but
rather on the Prototype 🤷. This seems to work though.

Fixes absinthe-graphql#1279
  • Loading branch information
jeffutter committed Aug 2, 2024
1 parent f4a930c commit 27ffcb1
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 7 deletions.
19 changes: 12 additions & 7 deletions lib/absinthe/phase/schema/compile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ defmodule Absinthe.Phase.Schema.Compile do

%{schema_definitions: [schema]} = blueprint

type_ast = build_types(schema.type_artifacts)
prototype_schema = Keyword.fetch!(opts, :prototype_schema)

type_ast = build_types(schema.type_artifacts, prototype_schema)

directive_ast = build_directives(schema.directive_artifacts)

type_list =
Expand All @@ -27,8 +30,6 @@ defmodule Absinthe.Phase.Schema.Compile do
{type_def.identifier, type_def.name}
end)

prototype_schema = Keyword.fetch!(opts, :prototype_schema)

metadata = build_metadata(schema)

implementors = build_implementors(schema)
Expand Down Expand Up @@ -86,7 +87,7 @@ defmodule Absinthe.Phase.Schema.Compile do
end
end

def build_types(types) do
def build_types(types, prototype_schema) do
for type <- types do
if !type.definition,
do:
Expand All @@ -108,9 +109,13 @@ defmodule Absinthe.Phase.Schema.Compile do
end
end
|> Enum.concat([
quote do
def __absinthe_type__(_type) do
nil
if prototype_schema == Absinthe.Schema.Prototype do
quote do
def __absinthe_type__(_type), do: nil
end
else
quote do
def __absinthe_type__(type), do: unquote(prototype_schema).__absinthe_type__(type)
end
end
])
Expand Down
82 changes: 82 additions & 0 deletions test/absinthe/introspection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,88 @@ defmodule Absinthe.IntrospectionTest do
end
end

describe "introspection of complex directives" do
defmodule ComplexDirectiveSchema do
use Absinthe.Schema
use Absinthe.Fixture

defmodule ComplexDirectivePrototype do
use Absinthe.Schema.Prototype

input_object :complex do
field :str, :string
end

directive :complex_directive do
arg :complex, :complex

on [:field]
end
end

@prototype_schema ComplexDirectivePrototype

query do
field :foo,
type: :string,
args: [],
resolve: fn _, _ -> {:ok, "foo"} end
end
end

test "renders type for complex directives" do

Check failure on line 121 in test/absinthe/introspection_test.exs

View workflow job for this annotation

GitHub Actions / Elixir 1.15 / OTP 25

test introspection of complex directives renders type for complex directives (Absinthe.IntrospectionTest)

Check failure on line 121 in test/absinthe/introspection_test.exs

View workflow job for this annotation

GitHub Actions / Elixir 1.15 / OTP 26

test introspection of complex directives renders type for complex directives (Absinthe.IntrospectionTest)

Check failure on line 121 in test/absinthe/introspection_test.exs

View workflow job for this annotation

GitHub Actions / Elixir 1.16 / OTP 25

test introspection of complex directives renders type for complex directives (Absinthe.IntrospectionTest)

Check failure on line 121 in test/absinthe/introspection_test.exs

View workflow job for this annotation

GitHub Actions / Elixir 1.16 / OTP 26

test introspection of complex directives renders type for complex directives (Absinthe.IntrospectionTest)

Check failure on line 121 in test/absinthe/introspection_test.exs

View workflow job for this annotation

GitHub Actions / Elixir 1.17 / OTP 26

test introspection of complex directives renders type for complex directives (Absinthe.IntrospectionTest)

Check failure on line 121 in test/absinthe/introspection_test.exs

View workflow job for this annotation

GitHub Actions / Elixir 1.17 / OTP 27

test introspection of complex directives renders type for complex directives (Absinthe.IntrospectionTest)
result =
"""
query IntrospectionQuery {
__schema {
directives {
name
args {
name
description
type {
kind
name
}
defaultValue
}
}
}
}
"""
|> run(ComplexDirectiveSchema)

assert {:ok,
%{
data: %{
"__schema" => %{
"directives" => directives
}
}
}} = result

assert Enum.any?(directives, fn directive ->
match?(
directive,
%{
"name" => "complexDirective",
"args" => [
%{
"type" => %{
"kind" => "INPUT_OBJECT",
"name" => "Complex"
},
"defaultValue" => nil,
"description" => nil,
"name" => "complex"
}
]
}
)
end)
end
end

describe "introspection of an enum type" do
test "can use __type and value information with deprecations" do
result =
Expand Down

0 comments on commit 27ffcb1

Please sign in to comment.