Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit c99d710

Browse files
author
Josh Price
committed
Support directives in introspection query
Closes #88
1 parent c253b86 commit c99d710

6 files changed

Lines changed: 101 additions & 30 deletions

File tree

lib/graphql/execution/executor.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,14 @@ defmodule GraphQL.Execution.Executor do
9898
!resolve_directive(context, directives, :skip)
9999
end
100100

101-
defp resolve_directive(context, directives, dir_type) do
102-
ast = Enum.find(directives, fn(d) -> d.name.value == Atom.to_string(dir_type) end)
103-
directive = apply(GraphQL.Type.Directives, dir_type, [])
101+
defp resolve_directive(context, directives, directive_name) do
102+
ast = Enum.find(directives, fn(d) -> d.name.value == Atom.to_string(directive_name) end)
103+
directive = apply(GraphQL.Type.Directives, directive_name, [])
104104
if ast do
105105
%{if: val} = argument_values(directive.args, ast.arguments, context.variable_values)
106106
val
107107
else
108-
directive.args.if.defaultValue
108+
directive_name == :include
109109
end
110110
end
111111

lib/graphql/type/directive.ex

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,34 @@ defmodule GraphQL.Type.Directive do
22
@moduledoc """
33
Directives currently supported are @skip and @include
44
"""
5-
defstruct name: "Directive", description: nil, locations: [], args: %{}
5+
defstruct name: "Directive",
6+
description: nil,
7+
locations: [],
8+
args: %{},
9+
onOperation: false,
10+
onFragment: true,
11+
onField: true
612
end
713

814
defmodule GraphQL.Type.Directives do
915
alias GraphQL.Type.{Directive, Boolean, NonNull, String}
16+
alias GraphQL.Util.Text
1017

1118
def include do
1219
%Directive{
1320
name: "include",
14-
description: """
15-
Directs the executor to include this field or fragment
16-
only when the `if` argument is true.
17-
""",
21+
description:
22+
"""
23+
Directs the executor to include this field or fragment
24+
only when the `if` argument is true.
25+
""" |> Text.normalize,
1826
locations: [:Field, :FragmentSpread, :InlineFragment],
1927
args: %{
2028
if: %{
2129
type: %NonNull{ofType: %Boolean{}},
30+
name: "if",
2231
description: "Included when true.",
23-
defaultValue: true
32+
defaultValue: nil
2433
}
2534
}
2635
}
@@ -29,16 +38,18 @@ defmodule GraphQL.Type.Directives do
2938
def skip do
3039
%Directive{
3140
name: "skip",
32-
description: """
33-
Directs the executor to skip this field or fragment
34-
only when the `if` argument is true.
35-
""",
41+
description:
42+
"""
43+
Directs the executor to skip this field or fragment
44+
when the `if` argument is true.
45+
""" |> Text.normalize,
3646
locations: [:Field, :FragmentSpread, :InlineFragment],
3747
args: %{
3848
if: %{
3949
type: %NonNull{ofType: %Boolean{}},
50+
name: "if",
4051
description: "Skipped when true.",
41-
defaultValue: false
52+
defaultValue: nil
4253
}
4354
}
4455
}
@@ -47,9 +58,10 @@ defmodule GraphQL.Type.Directives do
4758
def deprecated do
4859
%Directive{
4960
name: "deprecated",
50-
description: """
51-
Marks an element of a GraphQL schema as no longer supported.
52-
""",
61+
description:
62+
"""
63+
Marks an element of a GraphQL schema as no longer supported.
64+
""",
5365
locations: [:FieldDefinition, :EnumValue],
5466
args: %{
5567
reason: %{

lib/graphql/type/introspection.ex

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ defmodule GraphQL.Type.Introspection do
5757
directives: %{
5858
description: "A list of all directives supported by this server.",
5959
type: %NonNull{ofType: %List{ofType: %NonNull{ofType: Directive}}},
60-
resolve: nil #schema => schema.getDirectives(),
60+
resolve: fn(schema, _, _) ->
61+
schema.directives
62+
end
6163
}
6264
}
6365
}
@@ -83,7 +85,11 @@ defmodule GraphQL.Type.Introspection do
8385
description: %{type: %String{}},
8486
args: %{
8587
type: %NonNull{ofType: %List{ofType: %NonNull{ofType: InputValue}}},
86-
resolve: nil #directive => directive.args || []
88+
resolve: fn
89+
%{args: args}, _, _ ->
90+
Enum.map(args, fn {name, v} -> Map.put(v, :name, name) end)
91+
_, _, _ -> []
92+
end
8793
},
8894
onOperation: %{type: %NonNull{ofType: %Boolean{}}},
8995
onFragment: %{type: %NonNull{ofType: %Boolean{}}},
@@ -251,9 +257,9 @@ defmodule GraphQL.Type.Introspection do
251257
args: %{
252258
type: %NonNull{ofType: %List{ofType: %NonNull{ofType: InputValue}}},
253259
resolve: fn
254-
(%{args: _args} = schema) ->
255-
Enum.map(schema.args, fn({name, v}) -> Map.put(v, :name, name) end)
256-
(_) -> []
260+
%{args: args} ->
261+
Enum.map(args, fn {name, v} -> Map.put(v, :name, name) end)
262+
_ -> []
257263
end
258264
},
259265
type: %{type: %NonNull{ofType: Type}},

lib/graphql/type/schema.ex

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ defmodule GraphQL.Schema do
22

33
@type t :: %GraphQL.Schema{
44
query: Map,
5-
mutation: Map
5+
mutation: Map,
6+
type_cache: Map,
7+
directives: [GraphQL.Type.Directive.t]
68
}
79

810
alias GraphQL.Type.Interface
@@ -12,7 +14,13 @@ defmodule GraphQL.Schema do
1214
alias GraphQL.Type.CompositeType
1315
alias GraphQL.Lang.AST.Nodes
1416

15-
defstruct query: nil, mutation: nil, type_cache: nil
17+
defstruct query: nil,
18+
mutation: nil,
19+
type_cache: nil,
20+
directives: [
21+
GraphQL.Type.Directives.include,
22+
GraphQL.Type.Directives.skip
23+
]
1624

1725
def with_type_cache(schema = %{type_cache: nil}), do: new(schema)
1826
def with_type_cache(schema), do: schema

test/star_wars/introspection_query_test.exs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,55 @@ defmodule GraphQL.StarWars.IntrospectionTest do
219219
test "Can run the full introspection query" do
220220
{:ok, result} = execute(StarWars.Schema.schema, GraphQL.Type.Introspection.query)
221221
assert_data(result, %{
222-
"__schema" => %{"directives" => nil, "mutationType" => nil, "queryType" => %{"name" => "Query"}, "subscriptionType" => nil,
222+
"__schema" => %{"directives" => [
223+
%{
224+
"name" => "include",
225+
"description" => "Directs the executor to include this field or fragment only when the `if` argument is true.",
226+
"args" => [
227+
%{
228+
"name" => "if",
229+
"description" => "Included when true.",
230+
"type" => %{
231+
"kind" => "NON_NULL",
232+
"name" => nil,
233+
"ofType" => %{
234+
"kind" => "SCALAR",
235+
"name" => "Boolean",
236+
"ofType" => nil
237+
}
238+
},
239+
"defaultValue" => nil
240+
}
241+
],
242+
"onOperation" => false,
243+
"onFragment" => true,
244+
"onField" => true
245+
},
246+
%{
247+
"name" => "skip",
248+
"description" => "Directs the executor to skip this field or fragment when the `if` argument is true.",
249+
"args" => [
250+
%{
251+
"name" => "if",
252+
"description" => "Skipped when true.",
253+
"type" => %{
254+
"kind" => "NON_NULL",
255+
"name" => nil,
256+
"ofType" => %{
257+
"kind" => "SCALAR",
258+
"name" => "Boolean",
259+
"ofType" => nil
260+
}
261+
},
262+
"defaultValue" => nil
263+
}
264+
],
265+
"onOperation" => false,
266+
"onFragment" => true,
267+
"onField" => true
268+
}
269+
],
270+
"mutationType" => nil, "queryType" => %{"name" => "Query"}, "subscriptionType" => nil,
223271
"types" => [%{"description" => "The `Boolean` scalar type represents `true` or `false`.", "enumValues" => nil, "fields" => nil, "inputFields" => nil, "interfaces" => nil, "kind" => "SCALAR", "name" => "Boolean", "possibleTypes" => nil},
224272
%{"description" => "A character in the Star Wars Trilogy", "enumValues" => nil,
225273
"fields" => [%{"args" => [], "deprecationReason" => nil, "description" => nil, "isDeprecated" => nil, "name" => "appears_in", "type" => %{"kind" => "LIST", "name" => nil, "ofType" => %{"kind" => "ENUM", "name" => "Episode", "ofType" => nil}}},

test/test_helper.exs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ defmodule ExUnit.TestHelpers do
2222
end
2323

2424
def assert_data(result, expected) do
25-
assert(
26-
result[:data] == stringify_keys(expected),
27-
message: "Expected result[:data] to equal #{inspect stringify_keys(expected)} but was #{inspect result[:data]}"
28-
)
25+
assert result[:data] == stringify_keys(expected)
2926
end
3027

3128
def assert_has_error(result, expected) do

0 commit comments

Comments
 (0)