Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix import_types/2 for A.{B, C} #1022

Merged
merged 2 commits into from
Jan 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 33 additions & 13 deletions lib/absinthe/phase/schema/type_imports.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ defmodule Absinthe.Phase.Schema.TypeImports do
{Absinthe.Type.BuiltIns.Introspection, []}
]
def handle_imports(%Schema.SchemaDefinition{} = schema) do
types = do_imports(@default_imports ++ schema.imports, schema.type_definitions)
{types, schema} =
do_imports(@default_imports ++ schema.imports, schema.type_definitions, schema)

# special casing the import of the built in directives
[builtins] = Absinthe.Type.BuiltIns.Directives.__absinthe_blueprint__().schema_definitions
directives = schema.directive_definitions ++ builtins.directive_definitions
Expand All @@ -26,25 +28,43 @@ defmodule Absinthe.Phase.Schema.TypeImports do

def handle_imports(node), do: node

defp do_imports([], types) do
types
defp do_imports([], types, schema) do
{types, schema}
end

defp do_imports([{module, opts} | rest], acc) do
[other_def] = module.__absinthe_blueprint__.schema_definitions
defp do_imports([{module, opts} | rest], acc, schema) do
case Code.ensure_compiled(module) do
{:module, module} ->
[other_def] = module.__absinthe_blueprint__.schema_definitions

rejections =
MapSet.new([:query, :mutation, :subscription] ++ Keyword.get(opts, :except, []))

rejections = MapSet.new([:query, :mutation, :subscription] ++ Keyword.get(opts, :except, []))
types = Enum.reject(other_def.type_definitions, &(&1.identifier in rejections))

types = Enum.reject(other_def.type_definitions, &(&1.identifier in rejections))
types =
case Keyword.fetch(opts, :only) do
{:ok, selections} ->
Enum.filter(types, &(&1.identifier in selections))

case Keyword.fetch(opts, :only) do
{:ok, selections} ->
Enum.filter(types, &(&1.identifier in selections))
_ ->
types
end

_ ->
types
do_imports(other_def.imports ++ rest, types ++ acc, schema)

{:error, reason} ->
do_imports(rest, acc, schema |> put_error(error(module, reason)))
end
end

do_imports(other_def.imports ++ rest, types ++ acc)
# Generate an error when loading module fails
@spec error(module :: module(), error :: :embedded | :badfile | :nofile | :on_load_failure) ::
Absinthe.Phase.Error.t()
defp error(module, reason) do
%Absinthe.Phase.Error{
message: "Could not load module `#{module}`. It returned reason: `#{reason}`.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you inspect(module) it'll get rid of the Elixir. prefix in the output...

phase: __MODULE__
}
end
end
6 changes: 1 addition & 5 deletions lib/absinthe/schema/notation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1680,11 +1680,7 @@ defmodule Absinthe.Schema.Notation do
for {_, _, leaf} <- modules_ast_list do
type_module = Module.concat([root_module_with_alias | leaf])

if Code.ensure_loaded?(type_module) do
do_import_types(type_module, env, opts)
else
raise ArgumentError, "module #{type_module} is not available"
end
do_import_types(type_module, env, opts)
end
end

Expand Down
11 changes: 11 additions & 0 deletions test/absinthe/schema/notation/import_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,17 @@ defmodule Absinthe.Schema.Notation.ImportTest do
end
end

describe "unknown imported modules" do
test "returns error" do
assert_schema_error("unknown_import_schema", [
%Absinthe.Phase.Error{
message: "Could not load module `Elixir.Test.Unknown`. It returned reason: `nofile`.",
phase: Absinthe.Phase.Schema.TypeImports
}
])
end
end

defp validate(schema) do
pipeline =
schema
Expand Down
8 changes: 8 additions & 0 deletions test/support/fixtures/dynamic/unknown_import_schema.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule Absinthe.TestSupport.Schema.UnknownImportSchema do
use Absinthe.Schema

import_types Test.Unknown

query do
end
end