Skip to content

Commit

Permalink
Merge pull request #1189 from maartenvanvliet/expose-type-system-dire…
Browse files Browse the repository at this point in the history
…ctives-introspection

Expose type system directives in introspection
  • Loading branch information
benwilson512 authored Sep 6, 2022
2 parents 47ddd0a + 5eac6d5 commit 03be990
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Feature: [Support error tuples when scalar parsing fails](https://github.com/absinthe-graphql/absinthe/pull/1187)
- Feature: [Convert SDL Language.\* structs to SDL notation](https://github.com/absinthe-graphql/absinthe/pull/1160)
- Feature: [Add support for type extensions](https://github.com/absinthe-graphql/absinthe/pull/1157)
- Bug Fix: [Add type system directives to introspection results](https://github.com/absinthe-graphql/absinthe/pull/1189)
- Bug Fix: [Add `__private__` field to EnumValueDefinition](https://github.com/absinthe-graphql/absinthe/pull/1148)
- Bug Fix: [Fix bug in Schema.**absinthe_types**(:all) for Persistent Term](https://github.com/absinthe-graphql/absinthe/pull/1161)
- Feature: [Add `import_directives` macro](https://github.com/absinthe-graphql/absinthe/pull/1158)
Expand Down
8 changes: 6 additions & 2 deletions lib/absinthe/phase/schema/build.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ defmodule Absinthe.Phase.Schema.Build do
%{schema_definitions: [schema]} = blueprint

types = build_types(blueprint)
directives = build_directives(blueprint)
directive_artifacts = build_directives(blueprint)

schema = %{schema | type_artifacts: types, directive_artifacts: directives}
schema = %{
schema
| type_artifacts: types,
directive_artifacts: schema.directive_artifacts ++ directive_artifacts
}

blueprint = %{blueprint | schema_definitions: [schema]}

Expand Down
2 changes: 1 addition & 1 deletion lib/absinthe/phase/schema/compile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule Absinthe.Phase.Schema.Compile do
do: {type_def.identifier, type_def.name}

directive_list =
Map.new(schema.directive_definitions, fn type_def ->
Map.new(schema.directive_artifacts, fn type_def ->
{type_def.identifier, type_def.name}
end)

Expand Down
26 changes: 26 additions & 0 deletions lib/absinthe/phase/schema/import_prototype_directives.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule Absinthe.Phase.Schema.ImportPrototypeDirectives do
@moduledoc false

# Imports directives from the prototype schema into the current schema.
# This ensures the type system directives such as `deprecated` are available
# for introspection as per the spec.
#
# Note that this does import the (type system) directives themselves, this
# is already done in an earlier phase.

@behaviour Absinthe.Phase
alias Absinthe.Blueprint

@spec run(Blueprint.t(), Keyword.t()) :: {:ok, Blueprint.t()}
def run(blueprint, _options \\ []) do
prototype_directives = Absinthe.Schema.directives(blueprint.prototype_schema)

%{schema_definitions: [schema]} = blueprint

schema = %{schema | directive_artifacts: prototype_directives}

blueprint = %{blueprint | schema_definitions: [schema]}

{:ok, blueprint}
end
end
2 changes: 1 addition & 1 deletion lib/absinthe/phase/schema/populate_persistent_term.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if Code.ensure_loaded?(:persistent_term) do
do: {type_def.identifier, type_def.name}

directive_list =
Map.new(schema.directive_definitions, fn type_def ->
Map.new(schema.directive_artifacts, fn type_def ->
{type_def.identifier, type_def.name}
end)

Expand Down
1 change: 1 addition & 0 deletions lib/absinthe/pipeline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ defmodule Absinthe.Pipeline do
Phase.Schema.ReformatDescriptions,
# This phase is run again now after additional validations
{Phase.Schema.Validation.Result, pass: :final},
Phase.Schema.ImportPrototypeDirectives,
Phase.Schema.Build,
Phase.Schema.InlineFunctions,
{Phase.Schema.Compile, options}
Expand Down
2 changes: 2 additions & 0 deletions lib/absinthe/schema/prototype/notation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule Absinthe.Schema.Prototype.Notation do
@pipeline_modifier __MODULE__

directive :deprecated do
description "Marks an element of a GraphQL schema as no longer supported."
arg :reason, :string

on [
Expand All @@ -34,6 +35,7 @@ defmodule Absinthe.Schema.Prototype.Notation do
def pipeline(pipeline) do
pipeline
|> Absinthe.Pipeline.without(Absinthe.Phase.Schema.Validation.QueryTypeMustBeObject)
|> Absinthe.Pipeline.without(Absinthe.Phase.Schema.ImportPrototypeDirectives)
|> Absinthe.Pipeline.replace(
Absinthe.Phase.Schema.TypeExtensionImports,
{Absinthe.Phase.Schema.TypeExtensionImports, []}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ defmodule Elixir.Absinthe.Integration.Execution.Introspection.DirectivesTest do
data: %{
"__schema" => %{
"directives" => [
%{
"args" => [
%{"name" => "reason", "type" => %{"kind" => "SCALAR", "ofType" => nil}}
],
"isRepeatable" => false,
"locations" => [
"ARGUMENT_DEFINITION",
"ENUM_VALUE",
"FIELD_DEFINITION",
"INPUT_FIELD_DEFINITION"
],
"name" => "deprecated",
"onField" => false,
"onFragment" => false,
"onOperation" => false
},
%{
"args" => [
%{
Expand Down
24 changes: 24 additions & 0 deletions test/absinthe/introspection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ defmodule Absinthe.IntrospectionTest do
data: %{
"__schema" => %{
"directives" => [
%{
"description" =>
"Marks an element of a GraphQL schema as no longer supported.",
"isRepeatable" => false,
"locations" => [
"ARGUMENT_DEFINITION",
"ENUM_VALUE",
"FIELD_DEFINITION",
"INPUT_FIELD_DEFINITION"
],
"name" => "deprecated",
"onField" => false,
"onFragment" => false,
"onOperation" => false
},
%{
"description" => nil,
"isRepeatable" => false,
"locations" => ["FIELD_DEFINITION"],
"name" => "external",
"onField" => false,
"onFragment" => false,
"onOperation" => false
},
%{
"description" =>
"Directs the executor to include this field or fragment only when the `if` argument is true.",
Expand Down
10 changes: 10 additions & 0 deletions test/support/fixtures/color_schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ defmodule Absinthe.Fixtures.ColorSchema do
use Absinthe.Schema
use Absinthe.Fixture

defmodule WithTypeSystemDirective do
use Absinthe.Schema.Prototype

directive :external do
on [:field_definition]
end
end

@prototype_schema WithTypeSystemDirective

@names %{
r: "RED",
g: "GREEN",
Expand Down

0 comments on commit 03be990

Please sign in to comment.