Skip to content

Commit 42138c1

Browse files
committed
feat(Schema) accept optional directives in definition
1 parent db6fff0 commit 42138c1

File tree

6 files changed

+63
-17
lines changed

6 files changed

+63
-17
lines changed

lib/graphql/execution/deferred_execution.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -329,14 +329,12 @@ def resolve_field_frame(scope, thread, frame, field_defn)
329329
# Build arguments according to query-string literals, default values, and query variables
330330
arguments = query.arguments_for(frame.node, field_defn)
331331

332+
query.context.ast_node = ast_node
333+
query.context.irep_node = frame.node
334+
332335
# This is the last call in the middleware chain; it actually calls the user's resolve proc
333336
field_resolve_middleware_proc = -> (_parent_type, parent_object, field_definition, field_args, query_ctx, _next) {
334-
query_ctx.ast_node = ast_node
335-
query_ctx.irep_node = frame.node
336-
value = field_definition.resolve(parent_object, field_args, query_ctx)
337-
query_ctx.ast_node = nil
338-
query_ctx.irep_node = frame.node
339-
value
337+
field_definition.resolve(parent_object, field_args, query_ctx)
340338
}
341339

342340
# Send arguments through the middleware stack,
@@ -353,6 +351,9 @@ def resolve_field_frame(scope, thread, frame, field_defn)
353351
resolve_fn_value = err
354352
end
355353

354+
query.context.ast_node = nil
355+
query.context.irep_node = nil
356+
356357
case resolve_fn_value
357358
when GraphQL::ExecutionError
358359
thread.errors << resolve_fn_value

lib/graphql/schema.rb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Schema
4646
include GraphQL::Define::InstanceDefinable
4747
accepts_definitions \
4848
:query, :mutation, :subscription,
49+
:directives,
4950
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
5051
:max_depth, :max_complexity,
5152
:orphan_types, :resolve_type,
@@ -61,14 +62,17 @@ class Schema
6162
:orphan_types,
6263
:query_analyzers, :middleware
6364

64-
DIRECTIVES = [
65+
BUILT_IN_DIRECTIVES = [
6566
GraphQL::Directive::IncludeDirective,
6667
GraphQL::Directive::SkipDirective,
6768
GraphQL::Directive::DeprecatedDirective,
68-
GraphQL::Directive::DeferDirective,
69-
GraphQL::Directive::StreamDirective,
7069
]
7170

71+
OPTIONAL_DIRECTIVES = {
72+
"@defer" => GraphQL::Directive::DeferDirective,
73+
"@stream" => GraphQL::Directive::StreamDirective,
74+
}
75+
7276
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
7377

7478
attr_reader :directives, :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
@@ -83,7 +87,7 @@ class Schema
8387
# @param types [Array<GraphQL::BaseType>] additional types to include in this schema
8488
def initialize
8589
@orphan_types = []
86-
@directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
90+
@directives = BUILT_IN_DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
8791
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
8892
@middleware = []
8993
@query_analyzers = []
@@ -96,6 +100,15 @@ def initialize
96100
@subscription_execution_strategy = GraphQL::Query::SerialExecution
97101
end
98102

103+
def directives=(directive_names)
104+
ensure_defined
105+
directive_names.each do |name|
106+
dir = OPTIONAL_DIRECTIVES.fetch(name)
107+
@directives[dir.name] = dir
108+
end
109+
@directives
110+
end
111+
99112
def rescue_from(*args, &block)
100113
ensure_defined
101114
rescue_middleware.rescue_from(*args, &block)

spec/graphql/execution/deferred_execution_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def merged_result
334334
}
335335
end
336336
end
337-
schema = GraphQL::Schema.define(query: query_type)
337+
schema = GraphQL::Schema.define(query: query_type, directives: ["@stream", "@defer"])
338338
schema.query_execution_strategy = GraphQL::Execution::DeferredExecution
339339
schema
340340
}

spec/graphql/schema/printer_spec.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,6 @@
154154
reason: String = "No longer supported"
155155
) on FIELD_DEFINITION | ENUM_VALUE
156156
157-
# Push this part of the query in a later patch
158-
directive @defer on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
159-
160-
# Push items from this list in sequential patches
161-
directive @stream on FIELD
162-
163157
# A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
164158
#
165159
# In some cases, you need to provide options to alter GraphQL's execution behavior

spec/graphql/schema_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,40 @@
124124
end
125125
end
126126
end
127+
128+
describe "#directives" do
129+
let(:schema) {
130+
query_type = GraphQL::ObjectType.define do
131+
name "Query"
132+
field :one, types.Int, resolve: -> (o,a,c) { 1 }
133+
end
134+
135+
schema_directives = directives
136+
137+
GraphQL::Schema.define do
138+
query(query_type)
139+
directives(schema_directives)
140+
end
141+
}
142+
143+
describe "when @defer is not provided" do
144+
let(:directives) { [] }
145+
it "doesn't execute queries with defer" do
146+
res = schema.execute("{ one @defer }")
147+
assert_equal nil, res["data"]
148+
assert_equal 1, res["errors"].length
149+
end
150+
end
151+
152+
describe "when @defer is provided" do
153+
let(:directives) { ["@defer"] }
154+
155+
it "executes queries with defer" do
156+
res = schema.execute("{ one @defer, two: one }")
157+
# The deferred field is left out ??
158+
assert_equal({ "two" => 1 }, res["data"])
159+
assert_equal nil, res["errors"]
160+
end
161+
end
162+
end
127163
end

spec/support/dairy_app.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ def self.create(type:, data:)
356356

357357
rescue_from(NoSuchDairyError) { |err| err.message }
358358

359+
directives ["@defer", "@stream"]
360+
359361
resolve_type ->(obj, ctx) {
360362
DummySchema.types[obj.class.name]
361363
}

0 commit comments

Comments
 (0)