graphql 2.0.32 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/graphql/execution/interpreter/runtime.rb +27 -34
- data/lib/graphql/language/document_from_schema_definition.rb +6 -16
- data/lib/graphql/language/nodes.rb +1 -4
- data/lib/graphql/language/printer.rb +233 -145
- data/lib/graphql/language/sanitized_printer.rb +14 -21
- data/lib/graphql/language/visitor.rb +56 -122
- data/lib/graphql/pagination/connection.rb +23 -1
- data/lib/graphql/query.rb +2 -19
- data/lib/graphql/rake_task.rb +3 -12
- data/lib/graphql/schema/argument.rb +5 -3
- data/lib/graphql/schema/build_from_definition.rb +7 -8
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum_value.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +7 -1
- data/lib/graphql/schema/field.rb +1 -1
- data/lib/graphql/schema/input_object.rb +6 -8
- data/lib/graphql/schema/interface.rb +1 -5
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/has_interfaces.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/object.rb +8 -0
- data/lib/graphql/schema/printer.rb +8 -7
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/warden.rb +3 -34
- data/lib/graphql/schema.rb +4 -20
- data/lib/graphql/static_validation/validation_context.rb +0 -3
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
- data/lib/graphql/subscriptions.rb +11 -6
- data/lib/graphql/tracing/appoptics_trace.rb +0 -4
- data/lib/graphql/tracing/appsignal_trace.rb +0 -4
- data/lib/graphql/tracing/data_dog_trace.rb +34 -25
- data/lib/graphql/tracing/data_dog_tracing.rb +21 -7
- data/lib/graphql/tracing/notifications_trace.rb +0 -4
- data/lib/graphql/tracing/platform_trace.rb +0 -5
- data/lib/graphql/tracing/prometheus_trace.rb +0 -4
- data/lib/graphql/tracing/scout_trace.rb +0 -3
- data/lib/graphql/tracing/statsd_trace.rb +0 -4
- data/lib/graphql/types/relay/connection_behaviors.rb +20 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +8 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +0 -1
- metadata +24 -37
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/static_validation/type_stack.rb +0 -216
@@ -31,11 +31,6 @@ module GraphQL
|
|
31
31
|
# visitor.count
|
32
32
|
# # => 3
|
33
33
|
class Visitor
|
34
|
-
# If any hook returns this value, the {Visitor} stops visiting this
|
35
|
-
# node right away
|
36
|
-
# @deprecated Use `super` to continue the visit; or don't call it to halt.
|
37
|
-
SKIP = :_skip
|
38
|
-
|
39
34
|
class DeleteNode; end
|
40
35
|
|
41
36
|
# When this is returned from a visitor method,
|
@@ -44,25 +39,13 @@ module GraphQL
|
|
44
39
|
|
45
40
|
def initialize(document)
|
46
41
|
@document = document
|
47
|
-
@visitors = {}
|
48
42
|
@result = nil
|
49
43
|
end
|
50
44
|
|
51
45
|
# @return [GraphQL::Language::Nodes::Document] The document with any modifications applied
|
52
46
|
attr_reader :result
|
53
47
|
|
54
|
-
#
|
55
|
-
# @param node_class [Class] The node class that you want to listen to
|
56
|
-
# @return [NodeVisitor]
|
57
|
-
#
|
58
|
-
# @example Run a hook whenever you enter a new Field
|
59
|
-
# visitor[GraphQL::Language::Nodes::Field] << ->(node, parent) { p "Here's a field" }
|
60
|
-
# @deprecated see `on_` methods, like {#on_field}
|
61
|
-
def [](node_class)
|
62
|
-
@visitors[node_class] ||= NodeVisitor.new
|
63
|
-
end
|
64
|
-
|
65
|
-
# Visit `document` and all children, applying hooks as you go
|
48
|
+
# Visit `document` and all children
|
66
49
|
# @return [void]
|
67
50
|
def visit
|
68
51
|
# `@document` may be any kind of node:
|
@@ -76,6 +59,61 @@ module GraphQL
|
|
76
59
|
end
|
77
60
|
end
|
78
61
|
|
62
|
+
# We don't use `alias` here because it breaks `super`
|
63
|
+
def self.make_visit_methods(ast_node_class)
|
64
|
+
node_method = ast_node_class.visit_method
|
65
|
+
children_of_type = ast_node_class.children_of_type
|
66
|
+
child_visit_method = :"#{node_method}_children"
|
67
|
+
|
68
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
69
|
+
# The default implementation for visiting an AST node.
|
70
|
+
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
71
|
+
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
72
|
+
# in your subclasses.
|
73
|
+
#
|
74
|
+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
75
|
+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
76
|
+
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
77
|
+
def #{node_method}(node, parent)
|
78
|
+
if node.equal?(DELETE_NODE)
|
79
|
+
# This might be passed to `super(DELETE_NODE, ...)`
|
80
|
+
# by a user hook, don't want to keep visiting in that case.
|
81
|
+
[node, parent]
|
82
|
+
else
|
83
|
+
new_node = node
|
84
|
+
#{
|
85
|
+
if method_defined?(child_visit_method)
|
86
|
+
"new_node = #{child_visit_method}(new_node)"
|
87
|
+
elsif children_of_type
|
88
|
+
children_of_type.map do |child_accessor, child_class|
|
89
|
+
"node.#{child_accessor}.each do |child_node|
|
90
|
+
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
91
|
+
# Reassign `node` in case the child hook makes a modification
|
92
|
+
if new_child_and_node.is_a?(Array)
|
93
|
+
new_node = new_child_and_node[1]
|
94
|
+
end
|
95
|
+
end"
|
96
|
+
end.join("\n")
|
97
|
+
else
|
98
|
+
""
|
99
|
+
end
|
100
|
+
}
|
101
|
+
|
102
|
+
if new_node.equal?(node)
|
103
|
+
[node, parent]
|
104
|
+
else
|
105
|
+
[new_node, parent]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def #{node_method}_with_modifications(node, parent)
|
111
|
+
new_node_and_new_parent = #{node_method}(node, parent)
|
112
|
+
apply_modifications(node, parent, new_node_and_new_parent)
|
113
|
+
end
|
114
|
+
RUBY
|
115
|
+
end
|
116
|
+
|
79
117
|
def on_document_children(document_node)
|
80
118
|
new_node = document_node
|
81
119
|
document_node.children.each do |child_node|
|
@@ -176,68 +214,6 @@ module GraphQL
|
|
176
214
|
new_node
|
177
215
|
end
|
178
216
|
|
179
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
180
|
-
|
181
|
-
def self.make_visit_methods(ast_node_class)
|
182
|
-
node_method = ast_node_class.visit_method
|
183
|
-
children_of_type = ast_node_class.children_of_type
|
184
|
-
child_visit_method = :"#{node_method}_children"
|
185
|
-
|
186
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
187
|
-
# The default implementation for visiting an AST node.
|
188
|
-
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
189
|
-
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
190
|
-
# in your subclasses.
|
191
|
-
#
|
192
|
-
# For compatibility, it calls hook procs, too.
|
193
|
-
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
194
|
-
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
195
|
-
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
196
|
-
def #{node_method}(node, parent)
|
197
|
-
if node.equal?(DELETE_NODE)
|
198
|
-
# This might be passed to `super(DELETE_NODE, ...)`
|
199
|
-
# by a user hook, don't want to keep visiting in that case.
|
200
|
-
[node, parent]
|
201
|
-
else
|
202
|
-
# Run hooks if there are any
|
203
|
-
new_node = node
|
204
|
-
no_hooks = !@visitors.key?(node.class)
|
205
|
-
if no_hooks || begin_visit(new_node, parent)
|
206
|
-
#{
|
207
|
-
if method_defined?(child_visit_method)
|
208
|
-
"new_node = #{child_visit_method}(new_node)"
|
209
|
-
elsif children_of_type
|
210
|
-
children_of_type.map do |child_accessor, child_class|
|
211
|
-
"node.#{child_accessor}.each do |child_node|
|
212
|
-
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
213
|
-
# Reassign `node` in case the child hook makes a modification
|
214
|
-
if new_child_and_node.is_a?(Array)
|
215
|
-
new_node = new_child_and_node[1]
|
216
|
-
end
|
217
|
-
end"
|
218
|
-
end.join("\n")
|
219
|
-
else
|
220
|
-
""
|
221
|
-
end
|
222
|
-
}
|
223
|
-
end
|
224
|
-
end_visit(new_node, parent) unless no_hooks
|
225
|
-
if new_node.equal?(node)
|
226
|
-
[node, parent]
|
227
|
-
else
|
228
|
-
[new_node, parent]
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
def #{node_method}_with_modifications(node, parent)
|
233
|
-
new_node_and_new_parent = #{node_method}(node, parent)
|
234
|
-
apply_modifications(node, parent, new_node_and_new_parent)
|
235
|
-
end
|
236
|
-
RUBY
|
237
|
-
end
|
238
|
-
|
239
|
-
|
240
|
-
|
241
217
|
[
|
242
218
|
Language::Nodes::Argument,
|
243
219
|
Language::Nodes::Directive,
|
@@ -278,8 +254,6 @@ module GraphQL
|
|
278
254
|
make_visit_methods(ast_node_class)
|
279
255
|
end
|
280
256
|
|
281
|
-
# rubocop:enable Development/NoEvalCop
|
282
|
-
|
283
257
|
private
|
284
258
|
|
285
259
|
def apply_modifications(node, parent, new_node_and_new_parent)
|
@@ -308,46 +282,6 @@ module GraphQL
|
|
308
282
|
new_node_and_new_parent
|
309
283
|
end
|
310
284
|
end
|
311
|
-
|
312
|
-
def begin_visit(node, parent)
|
313
|
-
node_visitor = self[node.class]
|
314
|
-
self.class.apply_hooks(node_visitor.enter, node, parent)
|
315
|
-
end
|
316
|
-
|
317
|
-
# Should global `leave` visitors come first or last?
|
318
|
-
def end_visit(node, parent)
|
319
|
-
node_visitor = self[node.class]
|
320
|
-
self.class.apply_hooks(node_visitor.leave, node, parent)
|
321
|
-
end
|
322
|
-
|
323
|
-
# If one of the visitors returns SKIP, stop visiting this node
|
324
|
-
def self.apply_hooks(hooks, node, parent)
|
325
|
-
hooks.each do |proc|
|
326
|
-
return false if proc.call(node, parent) == SKIP
|
327
|
-
end
|
328
|
-
true
|
329
|
-
end
|
330
|
-
|
331
|
-
# Collect `enter` and `leave` hooks for classes in {GraphQL::Language::Nodes}
|
332
|
-
#
|
333
|
-
# Access {NodeVisitor}s via {GraphQL::Language::Visitor#[]}
|
334
|
-
class NodeVisitor
|
335
|
-
# @return [Array<Proc>] Hooks to call when entering a node of this type
|
336
|
-
attr_reader :enter
|
337
|
-
# @return [Array<Proc>] Hooks to call when leaving a node of this type
|
338
|
-
attr_reader :leave
|
339
|
-
|
340
|
-
def initialize
|
341
|
-
@enter = []
|
342
|
-
@leave = []
|
343
|
-
end
|
344
|
-
|
345
|
-
# Shorthand to add a hook to the {#enter} array
|
346
|
-
# @param hook [Proc] A hook to add
|
347
|
-
def <<(hook)
|
348
|
-
enter << hook
|
349
|
-
end
|
350
|
-
end
|
351
285
|
end
|
352
286
|
end
|
353
287
|
end
|
@@ -19,7 +19,14 @@ module GraphQL
|
|
19
19
|
attr_reader :items
|
20
20
|
|
21
21
|
# @return [GraphQL::Query::Context]
|
22
|
-
|
22
|
+
attr_reader :context
|
23
|
+
|
24
|
+
def context=(new_ctx)
|
25
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
26
|
+
query_runtime_state = current_runtime_state[new_ctx.query]
|
27
|
+
@was_authorized_by_scope_items = query_runtime_state.was_authorized_by_scope_items
|
28
|
+
@context = new_ctx
|
29
|
+
end
|
23
30
|
|
24
31
|
# @return [Object] the object this collection belongs to
|
25
32
|
attr_accessor :parent
|
@@ -83,6 +90,17 @@ module GraphQL
|
|
83
90
|
else
|
84
91
|
default_page_size
|
85
92
|
end
|
93
|
+
@was_authorized_by_scope_items = if @context
|
94
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
95
|
+
query_runtime_state = current_runtime_state[@context.query]
|
96
|
+
query_runtime_state.was_authorized_by_scope_items
|
97
|
+
else
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def was_authorized_by_scope_items?
|
103
|
+
@was_authorized_by_scope_items
|
86
104
|
end
|
87
105
|
|
88
106
|
def max_page_size=(new_value)
|
@@ -247,6 +265,10 @@ module GraphQL
|
|
247
265
|
def cursor
|
248
266
|
@cursor ||= @connection.cursor_for(@node)
|
249
267
|
end
|
268
|
+
|
269
|
+
def was_authorized_by_scope_items?
|
270
|
+
@connection.was_authorized_by_scope_items?
|
271
|
+
end
|
250
272
|
end
|
251
273
|
end
|
252
274
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -95,15 +95,10 @@ module GraphQL
|
|
95
95
|
# @param root_value [Object] the object used to resolve fields on the root type
|
96
96
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
97
97
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
98
|
-
|
99
|
-
# @param only [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns false
|
100
|
-
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
|
98
|
+
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil)
|
101
99
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
102
100
|
variables ||= {}
|
103
101
|
@schema = schema
|
104
|
-
if only || except
|
105
|
-
merge_filters(except: except, only: only)
|
106
|
-
end
|
107
102
|
@context = schema.context_class.new(query: self, object: root_value, values: context)
|
108
103
|
@warden = warden
|
109
104
|
@subscription_topic = subscription_topic
|
@@ -129,7 +124,6 @@ module GraphQL
|
|
129
124
|
raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
|
130
125
|
end
|
131
126
|
|
132
|
-
|
133
127
|
@analysis_errors = []
|
134
128
|
if variables.is_a?(String)
|
135
129
|
raise ArgumentError, "Query variables should be a Hash, not a String. Try JSON.parse to prepare variables."
|
@@ -354,17 +348,6 @@ module GraphQL
|
|
354
348
|
with_prepared_ast { @query }
|
355
349
|
end
|
356
350
|
|
357
|
-
# @return [void]
|
358
|
-
def merge_filters(only: nil, except: nil)
|
359
|
-
if @prepared_ast
|
360
|
-
raise "Can't add filters after preparing the query"
|
361
|
-
else
|
362
|
-
@filter ||= @schema.default_filter
|
363
|
-
@filter = @filter.merge(only: only, except: except)
|
364
|
-
end
|
365
|
-
nil
|
366
|
-
end
|
367
|
-
|
368
351
|
def subscription?
|
369
352
|
with_prepared_ast { @subscription }
|
370
353
|
end
|
@@ -400,7 +383,7 @@ module GraphQL
|
|
400
383
|
|
401
384
|
def prepare_ast
|
402
385
|
@prepared_ast = true
|
403
|
-
@warden ||= @schema.warden_class.new(
|
386
|
+
@warden ||= @schema.warden_class.new(schema: @schema, context: @context)
|
404
387
|
parse_error = nil
|
405
388
|
@document ||= begin
|
406
389
|
if query_string
|
data/lib/graphql/rake_task.rb
CHANGED
@@ -9,8 +9,7 @@ module GraphQL
|
|
9
9
|
# By default, schemas are looked up by name as constants using `schema_name:`.
|
10
10
|
# You can provide a `load_schema` function to return your schema another way.
|
11
11
|
#
|
12
|
-
# `load_context
|
13
|
-
# you can keep an eye on how filters affect your schema.
|
12
|
+
# Use `load_context:` and `visible?` to dump schemas under certain visibility constraints.
|
14
13
|
#
|
15
14
|
# @example Dump a Schema to .graphql + .json files
|
16
15
|
# require "graphql/rake_task"
|
@@ -36,8 +35,6 @@ module GraphQL
|
|
36
35
|
schema_name: nil,
|
37
36
|
load_schema: ->(task) { Object.const_get(task.schema_name) },
|
38
37
|
load_context: ->(task) { {} },
|
39
|
-
only: nil,
|
40
|
-
except: nil,
|
41
38
|
directory: ".",
|
42
39
|
idl_outfile: "schema.graphql",
|
43
40
|
json_outfile: "schema.json",
|
@@ -68,12 +65,6 @@ module GraphQL
|
|
68
65
|
# @return [<#call(task)>] A callable for loading the query context
|
69
66
|
attr_accessor :load_context
|
70
67
|
|
71
|
-
# @return [<#call(member, ctx)>, nil] A filter for this task
|
72
|
-
attr_accessor :only
|
73
|
-
|
74
|
-
# @return [<#call(member, ctx)>, nil] A filter for this task
|
75
|
-
attr_accessor :except
|
76
|
-
|
77
68
|
# @return [String] target for IDL task
|
78
69
|
attr_accessor :idl_outfile
|
79
70
|
|
@@ -117,10 +108,10 @@ module GraphQL
|
|
117
108
|
include_is_repeatable: include_is_repeatable,
|
118
109
|
include_specified_by_url: include_specified_by_url,
|
119
110
|
include_schema_description: include_schema_description,
|
120
|
-
|
111
|
+
context: context
|
121
112
|
)
|
122
113
|
when :to_definition
|
123
|
-
schema.to_definition(
|
114
|
+
schema.to_definition(context: context)
|
124
115
|
else
|
125
116
|
raise ArgumentError, "Unexpected schema dump method: #{method_name.inspect}"
|
126
117
|
end
|
@@ -53,7 +53,6 @@ module GraphQL
|
|
53
53
|
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NOT_CONFIGURED, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
54
54
|
arg_name ||= name
|
55
55
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
56
|
-
NameValidator.validate!(@name)
|
57
56
|
@type_expr = type_expr || type
|
58
57
|
@description = desc || description
|
59
58
|
@null = required != true
|
@@ -89,8 +88,11 @@ module GraphQL
|
|
89
88
|
end
|
90
89
|
|
91
90
|
if definition_block
|
92
|
-
|
93
|
-
|
91
|
+
if definition_block.arity == 1
|
92
|
+
instance_exec(self, &definition_block)
|
93
|
+
else
|
94
|
+
instance_eval(&definition_block)
|
95
|
+
end
|
94
96
|
end
|
95
97
|
end
|
96
98
|
|
@@ -453,18 +453,17 @@ module GraphQL
|
|
453
453
|
|
454
454
|
# Don't do this for interfaces
|
455
455
|
if default_resolve
|
456
|
-
|
456
|
+
owner.class_eval <<-RUBY, __FILE__, __LINE__
|
457
|
+
# frozen_string_literal: true
|
458
|
+
def #{resolve_method_name}(**args)
|
459
|
+
field_instance = self.class.get_field("#{field_definition.name}")
|
460
|
+
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
461
|
+
end
|
462
|
+
RUBY
|
457
463
|
end
|
458
464
|
end
|
459
465
|
end
|
460
466
|
|
461
|
-
def define_field_resolve_method(owner, method_name, field_name)
|
462
|
-
owner.define_method(method_name) { |**args|
|
463
|
-
field_instance = self.class.get_field(field_name)
|
464
|
-
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
465
|
-
}
|
466
|
-
end
|
467
|
-
|
468
467
|
def build_resolve_type(lookup_hash, directives, missing_type_handler)
|
469
468
|
resolve_type_proc = nil
|
470
469
|
resolve_type_proc = ->(ast_node) {
|
@@ -10,7 +10,13 @@ module GraphQL
|
|
10
10
|
else
|
11
11
|
ret_type = @field.type.unwrap
|
12
12
|
if ret_type.respond_to?(:scope_items)
|
13
|
-
ret_type.scope_items(value, context)
|
13
|
+
scoped_items = ret_type.scope_items(value, context)
|
14
|
+
if !scoped_items.equal?(value) && !ret_type.reauthorize_scoped_objects
|
15
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
16
|
+
query_runtime_state = current_runtime_state[context.query]
|
17
|
+
query_runtime_state.was_authorized_by_scope_items = true
|
18
|
+
end
|
19
|
+
scoped_items
|
14
20
|
else
|
15
21
|
value
|
16
22
|
end
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -233,7 +233,7 @@ module GraphQL
|
|
233
233
|
|
234
234
|
@underscored_name = -Member::BuildType.underscore(name_s)
|
235
235
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
236
|
-
|
236
|
+
|
237
237
|
@description = description
|
238
238
|
@type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
|
239
239
|
|
@@ -131,7 +131,12 @@ module GraphQL
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
# Add a method access
|
134
|
-
|
134
|
+
method_name = argument_defn.keyword
|
135
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
136
|
+
def #{method_name}
|
137
|
+
self[#{method_name.inspect}]
|
138
|
+
end
|
139
|
+
RUBY
|
135
140
|
argument_defn
|
136
141
|
end
|
137
142
|
|
@@ -237,13 +242,6 @@ module GraphQL
|
|
237
242
|
|
238
243
|
result
|
239
244
|
end
|
240
|
-
|
241
|
-
private
|
242
|
-
|
243
|
-
def define_accessor_method(method_name)
|
244
|
-
define_method(method_name) { self[method_name] }
|
245
|
-
alias_method(method_name, method_name)
|
246
|
-
end
|
247
245
|
end
|
248
246
|
|
249
247
|
private
|
@@ -69,11 +69,7 @@ module GraphQL
|
|
69
69
|
end
|
70
70
|
elsif child_class < GraphQL::Schema::Object
|
71
71
|
# This is being included into an object type, make sure it's using `implements(...)`
|
72
|
-
backtrace_line =
|
73
|
-
location.base_label == "implements" &&
|
74
|
-
location.path.end_with?("schema/member/has_interfaces.rb")
|
75
|
-
end
|
76
|
-
|
72
|
+
backtrace_line = caller(0, 10).find { |line| line.include?("schema/member/has_interfaces.rb") && line.include?("in `implements'")}
|
77
73
|
if !backtrace_line
|
78
74
|
raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
|
79
75
|
end
|
@@ -15,6 +15,25 @@ module GraphQL
|
|
15
15
|
def scope_items(items, context)
|
16
16
|
items
|
17
17
|
end
|
18
|
+
|
19
|
+
def reauthorize_scoped_objects(new_value = nil)
|
20
|
+
if new_value.nil?
|
21
|
+
if @reauthorize_scoped_objects != nil
|
22
|
+
@reauthorize_scoped_objects
|
23
|
+
else
|
24
|
+
find_inherited_value(:reauthorize_scoped_objects, nil)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@reauthorize_scoped_objects = new_value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def inherited(subclass)
|
32
|
+
super
|
33
|
+
subclass.class_eval do
|
34
|
+
@reauthorize_scoped_objects = nil
|
35
|
+
end
|
36
|
+
end
|
18
37
|
end
|
19
38
|
end
|
20
39
|
end
|
@@ -30,6 +30,10 @@ module GraphQL
|
|
30
30
|
# @see authorized_new to make instances
|
31
31
|
protected :new
|
32
32
|
|
33
|
+
def wrap_scoped(object, context)
|
34
|
+
scoped_new(object, context)
|
35
|
+
end
|
36
|
+
|
33
37
|
# This is called by the runtime to return an object to call methods on.
|
34
38
|
def wrap(object, context)
|
35
39
|
authorized_new(object, context)
|
@@ -91,6 +95,10 @@ module GraphQL
|
|
91
95
|
end
|
92
96
|
end
|
93
97
|
end
|
98
|
+
|
99
|
+
def scoped_new(object, context)
|
100
|
+
self.new(object, context)
|
101
|
+
end
|
94
102
|
end
|
95
103
|
|
96
104
|
def initialize(object, context)
|
@@ -36,15 +36,11 @@ module GraphQL
|
|
36
36
|
|
37
37
|
# @param schema [GraphQL::Schema]
|
38
38
|
# @param context [Hash]
|
39
|
-
# @param only [<#call(member, ctx)>]
|
40
|
-
# @param except [<#call(member, ctx)>]
|
41
39
|
# @param introspection [Boolean] Should include the introspection types in the string?
|
42
|
-
def initialize(schema, context: nil,
|
40
|
+
def initialize(schema, context: nil, introspection: false)
|
43
41
|
@document_from_schema = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
44
42
|
schema,
|
45
43
|
context: context,
|
46
|
-
only: only,
|
47
|
-
except: except,
|
48
44
|
include_introspection_types: introspection,
|
49
45
|
)
|
50
46
|
|
@@ -61,7 +57,12 @@ module GraphQL
|
|
61
57
|
false
|
62
58
|
end
|
63
59
|
end
|
64
|
-
schema = Class.new(GraphQL::Schema) {
|
60
|
+
schema = Class.new(GraphQL::Schema) {
|
61
|
+
query(query_root)
|
62
|
+
def self.visible?(member, _ctx)
|
63
|
+
member.graphql_name != "Root"
|
64
|
+
end
|
65
|
+
}
|
65
66
|
|
66
67
|
introspection_schema_ast = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
67
68
|
schema,
|
@@ -94,7 +95,7 @@ module GraphQL
|
|
94
95
|
|
95
96
|
class IntrospectionPrinter < GraphQL::Language::Printer
|
96
97
|
def print_schema_definition(schema)
|
97
|
-
"schema {\n query: Root\n}"
|
98
|
+
print_string("schema {\n query: Root\n}")
|
98
99
|
end
|
99
100
|
end
|
100
101
|
end
|
@@ -28,14 +28,19 @@ module GraphQL
|
|
28
28
|
def resolve_with_support(**args)
|
29
29
|
result = nil
|
30
30
|
unsubscribed = true
|
31
|
-
catch :graphql_subscription_unsubscribed do
|
31
|
+
unsubscribed_result = catch :graphql_subscription_unsubscribed do
|
32
32
|
result = super
|
33
33
|
unsubscribed = false
|
34
34
|
end
|
35
35
|
|
36
36
|
|
37
37
|
if unsubscribed
|
38
|
-
|
38
|
+
if unsubscribed_result
|
39
|
+
context.namespace(:subscriptions)[:final_update] = true
|
40
|
+
unsubscribed_result
|
41
|
+
else
|
42
|
+
context.skip
|
43
|
+
end
|
39
44
|
else
|
40
45
|
result
|
41
46
|
end
|
@@ -94,9 +99,11 @@ module GraphQL
|
|
94
99
|
end
|
95
100
|
|
96
101
|
# Call this to halt execution and remove this subscription from the system
|
97
|
-
|
102
|
+
# @param update_value [Object] if present, deliver this update before unsubscribing
|
103
|
+
# @return [void]
|
104
|
+
def unsubscribe(update_value = nil)
|
98
105
|
context.namespace(:subscriptions)[:unsubscribed] = true
|
99
|
-
throw :graphql_subscription_unsubscribed
|
106
|
+
throw :graphql_subscription_unsubscribed, update_value
|
100
107
|
end
|
101
108
|
|
102
109
|
READING_SCOPE = ::Object.new
|