graphql 2.0.26 → 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.

Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/relay.rb +18 -1
  3. data/lib/graphql/execution/interpreter/runtime.rb +23 -21
  4. data/lib/graphql/language/document_from_schema_definition.rb +6 -16
  5. data/lib/graphql/language/lexer.rb +86 -56
  6. data/lib/graphql/language/nodes.rb +1 -1
  7. data/lib/graphql/language/parser.rb +706 -691
  8. data/lib/graphql/language/parser.y +1 -0
  9. data/lib/graphql/language/printer.rb +233 -145
  10. data/lib/graphql/language/sanitized_printer.rb +14 -21
  11. data/lib/graphql/language/visitor.rb +18 -81
  12. data/lib/graphql/pagination/connection.rb +23 -1
  13. data/lib/graphql/query.rb +2 -19
  14. data/lib/graphql/rake_task.rb +3 -12
  15. data/lib/graphql/schema/addition.rb +6 -0
  16. data/lib/graphql/schema/field/scope_extension.rb +7 -1
  17. data/lib/graphql/schema/field.rb +1 -1
  18. data/lib/graphql/schema/member/scoped.rb +19 -0
  19. data/lib/graphql/schema/object.rb +8 -0
  20. data/lib/graphql/schema/printer.rb +8 -7
  21. data/lib/graphql/schema/resolver.rb +10 -8
  22. data/lib/graphql/schema/subscription.rb +11 -4
  23. data/lib/graphql/schema/validator.rb +1 -1
  24. data/lib/graphql/schema/warden.rb +3 -34
  25. data/lib/graphql/schema.rb +4 -20
  26. data/lib/graphql/static_validation/validation_context.rb +0 -3
  27. data/lib/graphql/static_validation.rb +0 -1
  28. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
  29. data/lib/graphql/subscriptions.rb +11 -6
  30. data/lib/graphql/types/relay/connection_behaviors.rb +19 -2
  31. data/lib/graphql/types/relay/edge_behaviors.rb +7 -0
  32. data/lib/graphql/version.rb +1 -1
  33. data/lib/graphql.rb +0 -1
  34. metadata +2 -4
  35. data/lib/graphql/filter.rb +0 -59
  36. 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
- # Get a {NodeVisitor} for `node_class`
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:
@@ -88,7 +71,6 @@ module GraphQL
88
71
  # To customize this hook, override one of its make_visit_methods (or the base method?)
89
72
  # in your subclasses.
90
73
  #
91
- # For compatibility, it calls hook procs, too.
92
74
  # @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
93
75
  # @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
94
76
  # @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
@@ -98,29 +80,24 @@ module GraphQL
98
80
  # by a user hook, don't want to keep visiting in that case.
99
81
  [node, parent]
100
82
  else
101
- # Run hooks if there are any
102
83
  new_node = node
103
- no_hooks = !@visitors.key?(node.class)
104
- if no_hooks || begin_visit(new_node, parent)
105
- #{
106
- if method_defined?(child_visit_method)
107
- "new_node = #{child_visit_method}(new_node)"
108
- elsif children_of_type
109
- children_of_type.map do |child_accessor, child_class|
110
- "node.#{child_accessor}.each do |child_node|
111
- new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
112
- # Reassign `node` in case the child hook makes a modification
113
- if new_child_and_node.is_a?(Array)
114
- new_node = new_child_and_node[1]
115
- end
116
- end"
117
- end.join("\n")
118
- else
119
- ""
120
- end
121
- }
122
- end
123
- end_visit(new_node, parent) unless no_hooks
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
+ }
124
101
 
125
102
  if new_node.equal?(node)
126
103
  [node, parent]
@@ -305,46 +282,6 @@ module GraphQL
305
282
  new_node_and_new_parent
306
283
  end
307
284
  end
308
-
309
- def begin_visit(node, parent)
310
- node_visitor = self[node.class]
311
- self.class.apply_hooks(node_visitor.enter, node, parent)
312
- end
313
-
314
- # Should global `leave` visitors come first or last?
315
- def end_visit(node, parent)
316
- node_visitor = self[node.class]
317
- self.class.apply_hooks(node_visitor.leave, node, parent)
318
- end
319
-
320
- # If one of the visitors returns SKIP, stop visiting this node
321
- def self.apply_hooks(hooks, node, parent)
322
- hooks.each do |proc|
323
- return false if proc.call(node, parent) == SKIP
324
- end
325
- true
326
- end
327
-
328
- # Collect `enter` and `leave` hooks for classes in {GraphQL::Language::Nodes}
329
- #
330
- # Access {NodeVisitor}s via {GraphQL::Language::Visitor#[]}
331
- class NodeVisitor
332
- # @return [Array<Proc>] Hooks to call when entering a node of this type
333
- attr_reader :enter
334
- # @return [Array<Proc>] Hooks to call when leaving a node of this type
335
- attr_reader :leave
336
-
337
- def initialize
338
- @enter = []
339
- @leave = []
340
- end
341
-
342
- # Shorthand to add a hook to the {#enter} array
343
- # @param hook [Proc] A hook to add
344
- def <<(hook)
345
- enter << hook
346
- end
347
- end
348
285
  end
349
286
  end
350
287
  end
@@ -19,7 +19,14 @@ module GraphQL
19
19
  attr_reader :items
20
20
 
21
21
  # @return [GraphQL::Query::Context]
22
- attr_accessor :context
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
- # @param except [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns truthy
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(@filter, schema: @schema, context: @context)
386
+ @warden ||= @schema.warden_class.new(schema: @schema, context: @context)
404
387
  parse_error = nil
405
388
  @document ||= begin
406
389
  if query_string
@@ -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:`, `only:` and `except:` are supported so that
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
- only: @only, except: @except, context: context
111
+ context: context
121
112
  )
122
113
  when :to_definition
123
- schema.to_definition(only: @only, except: @except, context: context)
114
+ schema.to_definition(context: context)
124
115
  else
125
116
  raise ArgumentError, "Unexpected schema dump method: #{method_name.inspect}"
126
117
  end
@@ -258,6 +258,12 @@ module GraphQL
258
258
  end
259
259
  path.pop
260
260
  end
261
+
262
+ if type.kind.enum?
263
+ type.all_enum_value_definitions.each do |value_definition|
264
+ add_directives_from(value_definition)
265
+ end
266
+ end
261
267
  end
262
268
  end
263
269
  end
@@ -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
@@ -92,7 +92,7 @@ module GraphQL
92
92
  # @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
93
93
  # @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
94
94
  # @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
95
- # @return [GraphQL::Schema:Field] an instance of `self
95
+ # @return [GraphQL::Schema:Field] an instance of `self`
96
96
  # @see {.initialize} for other options
97
97
  def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
98
98
  if (resolver_class = resolver || mutation || subscription)
@@ -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, only: nil, except: nil, introspection: false)
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) { query(query_root) }
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
@@ -65,19 +65,20 @@ module GraphQL
65
65
  # @api private
66
66
  def resolve_with_support(**args)
67
67
  # First call the ready? hook which may raise
68
- ready_val = if args.any?
68
+ raw_ready_val = if args.any?
69
69
  ready?(**args)
70
70
  else
71
71
  ready?
72
72
  end
73
- context.query.after_lazy(ready_val) do |is_ready, ready_early_return|
74
- if ready_early_return
73
+ context.query.after_lazy(raw_ready_val) do |ready_val|
74
+ if ready_val.is_a?(Array)
75
+ is_ready, ready_early_return = ready_val
75
76
  if is_ready != false
76
77
  raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
77
78
  else
78
79
  ready_early_return
79
80
  end
80
- elsif is_ready
81
+ elsif ready_val
81
82
  # Then call each prepare hook, which may return a different value
82
83
  # for that argument, or may return a lazy object
83
84
  load_arguments_val = load_arguments(args)
@@ -85,21 +86,22 @@ module GraphQL
85
86
  @prepared_arguments = loaded_args
86
87
  Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
87
88
  # Then call `authorized?`, which may raise or may return a lazy object
88
- authorized_val = if loaded_args.any?
89
+ raw_authorized_val = if loaded_args.any?
89
90
  authorized?(**loaded_args)
90
91
  else
91
92
  authorized?
92
93
  end
93
- context.query.after_lazy(authorized_val) do |(authorized_result, early_return)|
94
+ context.query.after_lazy(raw_authorized_val) do |authorized_val|
94
95
  # If the `authorized?` returned two values, `false, early_return`,
95
96
  # then use the early return value instead of continuing
96
- if early_return
97
+ if authorized_val.is_a?(Array)
98
+ authorized_result, early_return = authorized_val
97
99
  if authorized_result == false
98
100
  early_return
99
101
  else
100
102
  raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
101
103
  end
102
- elsif authorized_result
104
+ elsif authorized_val
103
105
  # Finally, all the hooks have passed, so resolve it
104
106
  if loaded_args.any?
105
107
  public_send(self.class.resolve_method, **loaded_args)
@@ -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
- context.skip
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
- def unsubscribe
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
@@ -133,7 +133,7 @@ module GraphQL
133
133
  if all_errors.frozen? # It's empty
134
134
  all_errors = []
135
135
  end
136
- interpolation_vars = { validated: validated.graphql_name }
136
+ interpolation_vars = { validated: validated.graphql_name, value: value.inspect }
137
137
  if errors.is_a?(String)
138
138
  all_errors << (errors % interpolation_vars)
139
139
  else
@@ -4,37 +4,12 @@ require 'set'
4
4
 
5
5
  module GraphQL
6
6
  class Schema
7
- # Restrict access to a {GraphQL::Schema} with a user-defined filter.
7
+ # Restrict access to a {GraphQL::Schema} with a user-defined `visible?` implementations.
8
8
  #
9
9
  # When validating and executing a query, all access to schema members
10
10
  # should go through a warden. If you access the schema directly,
11
11
  # you may show a client something that it shouldn't be allowed to see.
12
12
  #
13
- # @example Hiding private fields
14
- # private_members = -> (member, ctx) { member.metadata[:private] }
15
- # result = Schema.execute(query_string, except: private_members)
16
- #
17
- # @example Custom filter implementation
18
- # # It must respond to `#call(member)`.
19
- # class MissingRequiredFlags
20
- # def initialize(user)
21
- # @user = user
22
- # end
23
- #
24
- # # Return `false` if any required flags are missing
25
- # def call(member, ctx)
26
- # member.metadata[:required_flags].any? do |flag|
27
- # !@user.has_flag?(flag)
28
- # end
29
- # end
30
- # end
31
- #
32
- # # Then, use the custom filter in query:
33
- # missing_required_flags = MissingRequiredFlags.new(current_user)
34
- #
35
- # # This query can only access members which match the user's flags
36
- # result = Schema.execute(query_string, except: missing_required_flags)
37
- #
38
13
  # @api private
39
14
  class Warden
40
15
  def self.from_context(context)
@@ -114,22 +89,16 @@ module GraphQL
114
89
  def interfaces(obj_type); obj_type.interfaces; end
115
90
  end
116
91
 
117
- # @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
118
92
  # @param context [GraphQL::Query::Context]
119
93
  # @param schema [GraphQL::Schema]
120
- def initialize(filter = nil, context:, schema:)
94
+ def initialize(context:, schema:)
121
95
  @schema = schema
122
96
  # Cache these to avoid repeated hits to the inheritance chain when one isn't present
123
97
  @query = @schema.query
124
98
  @mutation = @schema.mutation
125
99
  @subscription = @schema.subscription
126
100
  @context = context
127
- @visibility_cache = if filter
128
- read_through { |m| filter.call(m, context) }
129
- else
130
- read_through { |m| schema.visible?(m, context) }
131
- end
132
-
101
+ @visibility_cache = read_through { |m| schema.visible?(m, context) }
133
102
  @visibility_cache.compare_by_identity
134
103
  # Initialize all ivars to improve object shape consistency:
135
104
  @types = @visible_types = @reachable_types = @visible_parent_fields =
@@ -222,7 +222,7 @@ module GraphQL
222
222
  # @param include_specified_by_url [Boolean] If true, scalar types' `specifiedByUrl:` will be included in the response
223
223
  # @param include_is_one_of [Boolean] If true, `isOneOf: true|false` will be included with input objects
224
224
  # @return [Hash] GraphQL result
225
- def as_json(only: nil, except: nil, context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
225
+ def as_json(context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
226
226
  introspection_query = Introspection.query(
227
227
  include_deprecated_args: include_deprecated_args,
228
228
  include_schema_description: include_schema_description,
@@ -231,16 +231,14 @@ module GraphQL
231
231
  include_specified_by_url: include_specified_by_url,
232
232
  )
233
233
 
234
- execute(introspection_query, only: only, except: except, context: context).to_h
234
+ execute(introspection_query, context: context).to_h
235
235
  end
236
236
 
237
237
  # Return the GraphQL IDL for the schema
238
238
  # @param context [Hash]
239
- # @param only [<#call(member, ctx)>]
240
- # @param except [<#call(member, ctx)>]
241
239
  # @return [String]
242
- def to_definition(only: nil, except: nil, context: {})
243
- GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
240
+ def to_definition(context: {})
241
+ GraphQL::Schema::Printer.print_schema(self, context: context)
244
242
  end
245
243
 
246
244
  # Return the GraphQL::Language::Document IDL AST for the schema
@@ -268,20 +266,6 @@ module GraphQL
268
266
  @find_cache[path] ||= @finder.find(path)
269
267
  end
270
268
 
271
- def default_filter
272
- GraphQL::Filter.new(except: default_mask)
273
- end
274
-
275
- def default_mask(new_mask = nil)
276
- if new_mask
277
- line = caller(2, 10).find { |l| !l.include?("lib/graphql") }
278
- GraphQL::Deprecation.warn("GraphQL::Filter and Schema.mask are deprecated and will be removed in v2.1.0. Implement `visible?` on your schema members instead (https://graphql-ruby.org/authorization/visibility.html).\n #{line}")
279
- @own_default_mask = new_mask
280
- else
281
- @own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
282
- end
283
- end
284
-
285
269
  def static_validator
286
270
  GraphQL::StaticValidation::Validator.new(schema: self)
287
271
  end
@@ -8,9 +8,6 @@ module GraphQL
8
8
  # It provides access to the schema & fragments which validators may read from.
9
9
  #
10
10
  # It holds a list of errors which each validator may add to.
11
- #
12
- # It also provides limited access to the {TypeStack} instance,
13
- # which tracks state as you climb in and out of different fields.
14
11
  class ValidationContext
15
12
  extend Forwardable
16
13
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/static_validation/error"
3
3
  require "graphql/static_validation/definition_dependencies"
4
- require "graphql/static_validation/type_stack"
5
4
  require "graphql/static_validation/validator"
6
5
  require "graphql/static_validation/validation_context"
7
6
  require "graphql/static_validation/validation_timeout_error"
@@ -124,7 +124,8 @@ module GraphQL
124
124
  # This subscription was re-evaluated.
125
125
  # Send it to the specific stream where this client was waiting.
126
126
  def deliver(subscription_id, result)
127
- payload = { result: result.to_h, more: true }
127
+ has_more = !result.context.namespace(:subscriptions)[:final_update]
128
+ payload = { result: result.to_h, more: has_more }
128
129
  @action_cable.server.broadcast(stream_subscription_name(subscription_id), payload)
129
130
  end
130
131