graphql 1.11.3 → 1.11.4

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +8 -0
  3. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  4. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  5. data/lib/generators/graphql/templates/base_field.erb +2 -0
  6. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  7. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  8. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  9. data/lib/generators/graphql/templates/base_object.erb +2 -0
  10. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  11. data/lib/generators/graphql/templates/base_union.erb +2 -0
  12. data/lib/generators/graphql/templates/enum.erb +2 -0
  13. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  14. data/lib/generators/graphql/templates/interface.erb +2 -0
  15. data/lib/generators/graphql/templates/loader.erb +2 -0
  16. data/lib/generators/graphql/templates/mutation.erb +2 -0
  17. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  18. data/lib/generators/graphql/templates/object.erb +2 -0
  19. data/lib/generators/graphql/templates/query_type.erb +2 -0
  20. data/lib/generators/graphql/templates/scalar.erb +2 -0
  21. data/lib/generators/graphql/templates/schema.erb +2 -0
  22. data/lib/generators/graphql/templates/union.erb +2 -0
  23. data/lib/graphql/execution/interpreter/runtime.rb +24 -25
  24. data/lib/graphql/query/context.rb +20 -1
  25. data/lib/graphql/query/fingerprint.rb +2 -0
  26. data/lib/graphql/query/validation_pipeline.rb +3 -0
  27. data/lib/graphql/schema.rb +4 -0
  28. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  29. data/lib/graphql/schema/subscription.rb +2 -12
  30. data/lib/graphql/schema/warden.rb +2 -3
  31. data/lib/graphql/subscriptions.rb +31 -19
  32. data/lib/graphql/tracing/appoptics_tracing.rb +10 -2
  33. data/lib/graphql/types/iso_8601_date_time.rb +2 -1
  34. data/lib/graphql/types/relay/base_connection.rb +6 -5
  35. data/lib/graphql/version.rb +1 -1
  36. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f64724e3b46476cf0a622ef5d5d1beb4360c7d5de031907d5173cb462928ee4
4
- data.tar.gz: 9b8098bab2bfdc704bf98dc011a452f1bce8c480c9435f1b37a79430ee81bc06
3
+ metadata.gz: c5bf42de25927dab863bd600879d33d204c54bdf124b2b4cc5b27c4c16d4f28b
4
+ data.tar.gz: 58b21a4dd5ba80ec0f6c3362013a6adb07c2f1af243e5a851d4c3f08554fe09d
5
5
  SHA512:
6
- metadata.gz: 6dabc15fe0688fc37233e23f5bc5647bf55ad176456257c088e15a87f7fabc07b6da43e86efcd9e982ecfc8b47c6eca331a0ced9a82f20076c21aa4ccf20f223
7
- data.tar.gz: d98a3193ab5759d206aabf9db378c38c669cbc2752f4b8908484fcf2cbee9012f00721403ffe999cd19e43016a6b27bd2c0f5f1dc602b93543772f1e7a4791b5
6
+ metadata.gz: f199d24a190910e44b189340b6a3d2a3c121ab56ba10ec6cf44d8801107db8d73541f24788b00b13ee7dd357f7bfe6ecff7001f053fe417c777bca59db5851db
7
+ data.tar.gz: fd0955c7f67b20370ea376d6a286fdf0ac7272ac5b243d6c309d2159a780cd0b8f92fd0e06ca312a69a16b7c8ad0ebd7bb4587feac9dc77b27da507c9a44cd8f
@@ -41,6 +41,14 @@ module Graphql
41
41
  end
42
42
  end
43
43
 
44
+ def module_namespacing_when_supported
45
+ if defined?(module_namespacing)
46
+ module_namespacing { yield }
47
+ else
48
+ yield
49
+ end
50
+ end
51
+
44
52
  private
45
53
 
46
54
  def schema_name
@@ -1,4 +1,6 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseArgument < GraphQL::Schema::Argument
3
4
  end
4
5
  end
6
+ <% end -%>
@@ -1,4 +1,6 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseEnum < GraphQL::Schema::Enum
3
4
  end
4
5
  end
6
+ <% end -%>
@@ -1,5 +1,7 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseField < GraphQL::Schema::Field
3
4
  argument_class Types::BaseArgument
4
5
  end
5
6
  end
7
+ <% end -%>
@@ -1,5 +1,7 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseInputObject < GraphQL::Schema::InputObject
3
4
  argument_class Types::BaseArgument
4
5
  end
5
6
  end
7
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  module BaseInterface
3
4
  include GraphQL::Schema::Interface
@@ -5,3 +6,4 @@ module Types
5
6
  field_class Types::BaseField
6
7
  end
7
8
  end
9
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Mutations
2
3
  class BaseMutation < GraphQL::Schema::RelayClassicMutation
3
4
  argument_class Types::BaseArgument
@@ -6,3 +7,4 @@ module Mutations
6
7
  object_class Types::BaseObject
7
8
  end
8
9
  end
10
+ <% end -%>
@@ -1,5 +1,7 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseObject < GraphQL::Schema::Object
3
4
  field_class Types::BaseField
4
5
  end
5
6
  end
7
+ <% end -%>
@@ -1,4 +1,6 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseScalar < GraphQL::Schema::Scalar
3
4
  end
4
5
  end
6
+ <% end -%>
@@ -1,4 +1,6 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class BaseUnion < GraphQL::Schema::Union
3
4
  end
4
5
  end
6
+ <% end -%>
@@ -1,5 +1,7 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class <%= type_ruby_name.split('::')[-1] %> < Types::BaseEnum
3
4
  <% prepared_values.each do |v| %> value "<%= v[0] %>"<%= v.length > 1 ? ", value: #{v[1]}" : "" %>
4
5
  <% end %> end
5
6
  end
7
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  class GraphqlController < ApplicationController
2
3
  # If accessing from outside this domain, nullify the session
3
4
  # This allows for outside API access while preventing CSRF attacks,
@@ -48,3 +49,4 @@ class GraphqlController < ApplicationController
48
49
  render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: 500
49
50
  end
50
51
  end
52
+ <% end -%>
@@ -1,6 +1,8 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  module <%= type_ruby_name.split('::')[-1] %>
3
4
  include Types::BaseInterface
4
5
  <% normalized_fields.each do |f| %> <%= f.to_ruby %>
5
6
  <% end %> end
6
7
  end
8
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Loaders
2
3
  class <%= class_name %> < GraphQL::Batch::Loader
3
4
  # Define `initialize` to store grouping arguments, eg
@@ -15,3 +16,4 @@ module Loaders
15
16
  end
16
17
  end
17
18
  end
19
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Mutations
2
3
  class <%= mutation_name %> < BaseMutation
3
4
  # TODO: define return fields
@@ -12,3 +13,4 @@ module Mutations
12
13
  # end
13
14
  end
14
15
  end
16
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class MutationType < Types::BaseObject
3
4
  # TODO: remove me
@@ -8,3 +9,4 @@ module Types
8
9
  end
9
10
  end
10
11
  end
12
+ <% end -%>
@@ -1,6 +1,8 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class <%= type_ruby_name.split('::')[-1] %> < Types::BaseObject
3
4
  <% if options.node %> implements GraphQL::Relay::Node.interface
4
5
  <% end %><% normalized_fields.each do |f| %> <%= f.to_ruby %>
5
6
  <% end %> end
6
7
  end
8
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class QueryType < Types::BaseObject
3
4
  # Add root-level fields here.
@@ -13,3 +14,4 @@ module Types
13
14
  field :node, field: GraphQL::Relay::Node.field
14
15
  <% end %> end
15
16
  end
17
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class <%= type_ruby_name.split('::')[-1] %> < Types::BaseScalar
3
4
  def self.coerce_input(input_value, context)
@@ -11,3 +12,4 @@ module Types
11
12
  end
12
13
  end
13
14
  end
15
+ <% end -%>
@@ -1,3 +1,4 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  class <%= schema_name %> < GraphQL::Schema
2
3
  query(Types::QueryType)
3
4
 
@@ -38,3 +39,4 @@ class <%= schema_name %> < GraphQL::Schema
38
39
  # GraphQL::Batch setup:
39
40
  use GraphQL::Batch
40
41
  <% end %>end
42
+ <% end -%>
@@ -1,5 +1,7 @@
1
+ <% module_namespacing_when_supported do -%>
1
2
  module Types
2
3
  class <%= type_ruby_name.split('::')[-1] %> < Types::BaseUnion
3
4
  <% if possible_types.any? %> possible_types [<%= normalized_possible_types.join(", ") %>]
4
5
  <% end %> end
5
6
  end
7
+ <% end -%>
@@ -170,13 +170,13 @@ module GraphQL
170
170
  begin
171
171
  kwarg_arguments = arguments(object, field_defn, ast_node)
172
172
  rescue GraphQL::ExecutionError => e
173
- continue_value(next_path, e, field_defn, return_type.non_null?, ast_node)
173
+ continue_value(next_path, e, owner_type, field_defn, return_type.non_null?, ast_node)
174
174
  next
175
175
  end
176
176
 
177
177
  after_lazy(kwarg_arguments, owner: owner_type, field: field_defn, path: next_path, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments) do |resolved_arguments|
178
178
  if resolved_arguments.is_a? GraphQL::ExecutionError
179
- continue_value(next_path, resolved_arguments, field_defn, return_type.non_null?, ast_node)
179
+ continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node)
180
180
  next
181
181
  end
182
182
 
@@ -228,12 +228,12 @@ module GraphQL
228
228
  err
229
229
  end
230
230
  after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments) do |inner_result|
231
- continue_value = continue_value(next_path, inner_result, field_defn, return_type.non_null?, ast_node)
231
+ continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node)
232
232
  if RawValue === continue_value
233
233
  # Write raw value directly to the response without resolving nested objects
234
234
  write_in_response(next_path, continue_value.resolve)
235
235
  elsif HALT != continue_value
236
- continue_field(next_path, continue_value, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments)
236
+ continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments)
237
237
  end
238
238
  end
239
239
  end
@@ -251,10 +251,9 @@ module GraphQL
251
251
  end
252
252
 
253
253
  HALT = Object.new
254
- def continue_value(path, value, field, is_non_null, ast_node)
254
+ def continue_value(path, value, parent_type, field, is_non_null, ast_node)
255
255
  if value.nil?
256
256
  if is_non_null
257
- parent_type = field.owner_type
258
257
  err = parent_type::InvalidNullError.new(parent_type, field, value)
259
258
  write_invalid_null_in_response(path, err)
260
259
  else
@@ -282,7 +281,7 @@ module GraphQL
282
281
  err
283
282
  end
284
283
 
285
- continue_value(path, next_value, field, is_non_null, ast_node)
284
+ continue_value(path, next_value, parent_type, field, is_non_null, ast_node)
286
285
  elsif GraphQL::Execution::Execute::SKIP == value
287
286
  HALT
288
287
  else
@@ -298,49 +297,49 @@ module GraphQL
298
297
  # Location information from `path` and `ast_node`.
299
298
  #
300
299
  # @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
301
- def continue_field(path, value, field, type, ast_node, next_selections, is_non_null, owner_object, arguments) # rubocop:disable Metrics/ParameterLists
302
- case type.kind.name
300
+ def continue_field(path, value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments) # rubocop:disable Metrics/ParameterLists
301
+ case current_type.kind.name
303
302
  when "SCALAR", "ENUM"
304
- r = type.coerce_result(value, context)
303
+ r = current_type.coerce_result(value, context)
305
304
  write_in_response(path, r)
306
305
  r
307
306
  when "UNION", "INTERFACE"
308
- resolved_type_or_lazy, resolved_value = resolve_type(type, value, path)
307
+ resolved_type_or_lazy, resolved_value = resolve_type(current_type, value, path)
309
308
  resolved_value ||= value
310
309
 
311
- after_lazy(resolved_type_or_lazy, owner: type, path: path, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false) do |resolved_type|
312
- possible_types = query.possible_types(type)
310
+ after_lazy(resolved_type_or_lazy, owner: current_type, path: path, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false) do |resolved_type|
311
+ possible_types = query.possible_types(current_type)
313
312
 
314
313
  if !possible_types.include?(resolved_type)
315
314
  parent_type = field.owner_type
316
- err_class = type::UnresolvedTypeError
315
+ err_class = current_type::UnresolvedTypeError
317
316
  type_error = err_class.new(resolved_value, field, parent_type, resolved_type, possible_types)
318
317
  schema.type_error(type_error, context)
319
318
  write_in_response(path, nil)
320
319
  nil
321
320
  else
322
- continue_field(path, resolved_value, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments)
321
+ continue_field(path, resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments)
323
322
  end
324
323
  end
325
324
  when "OBJECT"
326
325
  object_proxy = begin
327
- authorized_new(type, value, context, path)
326
+ authorized_new(current_type, value, context, path)
328
327
  rescue GraphQL::ExecutionError => err
329
328
  err
330
329
  end
331
- after_lazy(object_proxy, owner: type, path: path, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false) do |inner_object|
332
- continue_value = continue_value(path, inner_object, field, is_non_null, ast_node)
330
+ after_lazy(object_proxy, owner: current_type, path: path, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false) do |inner_object|
331
+ continue_value = continue_value(path, inner_object, owner_type, field, is_non_null, ast_node)
333
332
  if HALT != continue_value
334
333
  response_hash = {}
335
334
  write_in_response(path, response_hash)
336
- evaluate_selections(path, context.scoped_context, continue_value, type, next_selections)
335
+ evaluate_selections(path, context.scoped_context, continue_value, current_type, next_selections)
337
336
  response_hash
338
337
  end
339
338
  end
340
339
  when "LIST"
341
340
  response_list = []
342
341
  write_in_response(path, response_list)
343
- inner_type = type.of_type
342
+ inner_type = current_type.of_type
344
343
  idx = 0
345
344
  scoped_context = context.scoped_context
346
345
  begin
@@ -352,9 +351,9 @@ module GraphQL
352
351
  set_type_at_path(next_path, inner_type)
353
352
  # This will update `response_list` with the lazy
354
353
  after_lazy(inner_value, owner: inner_type, path: next_path, scoped_context: scoped_context, field: field, owner_object: owner_object, arguments: arguments) do |inner_inner_value|
355
- continue_value = continue_value(next_path, inner_inner_value, field, inner_type.non_null?, ast_node)
354
+ continue_value = continue_value(next_path, inner_inner_value, owner_type, field, inner_type.non_null?, ast_node)
356
355
  if HALT != continue_value
357
- continue_field(next_path, continue_value, field, inner_type, ast_node, next_selections, false, owner_object, arguments)
356
+ continue_field(next_path, continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments)
358
357
  end
359
358
  end
360
359
  end
@@ -371,12 +370,12 @@ module GraphQL
371
370
 
372
371
  response_list
373
372
  when "NON_NULL"
374
- inner_type = type.of_type
373
+ inner_type = current_type.of_type
375
374
  # Don't `set_type_at_path` because we want the static type,
376
375
  # we're going to use that to determine whether a `nil` should be propagated or not.
377
- continue_field(path, value, field, inner_type, ast_node, next_selections, true, owner_object, arguments)
376
+ continue_field(path, value, owner_type, field, inner_type, ast_node, next_selections, true, owner_object, arguments)
378
377
  else
379
- raise "Invariant: Unhandled type kind #{type.kind} (#{type})"
378
+ raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
380
379
  end
381
380
  end
382
381
 
@@ -168,7 +168,6 @@ module GraphQL
168
168
  attr_accessor :scoped_context
169
169
 
170
170
  def_delegators :@provided_values, :[]=
171
- def_delegators :to_h, :fetch, :dig
172
171
  def_delegators :@query, :trace, :interpreter?
173
172
 
174
173
  # @!method []=(key, value)
@@ -180,6 +179,26 @@ module GraphQL
180
179
  @provided_values[key]
181
180
  end
182
181
 
182
+ UNSPECIFIED_FETCH_DEFAULT = Object.new
183
+
184
+ def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
185
+ if @scoped_context.key?(key)
186
+ @scoped_context[key]
187
+ elsif @provided_values.key?(key)
188
+ @provided_values[key]
189
+ elsif default != UNSPECIFIED_FETCH_DEFAULT
190
+ default
191
+ elsif block_given?
192
+ yield(self, key)
193
+ else
194
+ raise KeyError.new(key: key)
195
+ end
196
+ end
197
+
198
+ def dig(key, *other_keys)
199
+ @scoped_context.key?(key) ? @scoped_context.dig(key, *other_keys) : @provided_values.dig(key, *other_keys)
200
+ end
201
+
183
202
  def to_h
184
203
  @provided_values.merge(@scoped_context)
185
204
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'digest/sha2'
4
+
3
5
  module GraphQL
4
6
  class Query
5
7
  # @api private
@@ -90,6 +90,9 @@ module GraphQL
90
90
  end
91
91
 
92
92
  @valid = @validation_errors.empty?
93
+ rescue SystemStackError => err
94
+ @valid = false
95
+ @schema.query_stack_error(@query, err)
93
96
  end
94
97
 
95
98
  # If there are max_* values, add them,
@@ -1663,6 +1663,10 @@ module GraphQL
1663
1663
  end
1664
1664
  end
1665
1665
 
1666
+ def query_stack_error(query, err)
1667
+ query.analysis_errors.push(GraphQL::AnalysisError.new("This query is too large to execute."))
1668
+ end
1669
+
1666
1670
  private
1667
1671
 
1668
1672
  def lazy_methods
@@ -44,7 +44,7 @@ module GraphQL
44
44
  if field.has_max_page_size? && !value.has_max_page_size_override?
45
45
  value.max_page_size = field.max_page_size
46
46
  end
47
- if (custom_t = context.schema.connections.edge_class_for_field(@field))
47
+ if context.schema.new_connections? && (custom_t = context.schema.connections.edge_class_for_field(@field))
48
48
  value.edge_class = custom_t
49
49
  end
50
50
  value
@@ -12,16 +12,6 @@ module GraphQL
12
12
  #
13
13
  # Also, `#unsubscribe` terminates the subscription.
14
14
  class Subscription < GraphQL::Schema::Resolver
15
- class EarlyTerminationError < StandardError
16
- end
17
-
18
- # Raised when `unsubscribe` is called; caught by `subscriptions.rb`
19
- class UnsubscribedError < EarlyTerminationError
20
- end
21
-
22
- # Raised when `no_update` is returned; caught by `subscriptions.rb`
23
- class NoUpdateError < EarlyTerminationError
24
- end
25
15
  extend GraphQL::Schema::Resolver::HasPayloadType
26
16
  extend GraphQL::Schema::Member::HasFields
27
17
 
@@ -65,7 +55,7 @@ module GraphQL
65
55
  def resolve_update(**args)
66
56
  ret_val = args.any? ? update(**args) : update
67
57
  if ret_val == :no_update
68
- raise NoUpdateError
58
+ throw :graphql_no_subscription_update
69
59
  else
70
60
  ret_val
71
61
  end
@@ -90,7 +80,7 @@ module GraphQL
90
80
 
91
81
  # Call this to halt execution and remove this subscription from the system
92
82
  def unsubscribe
93
- raise UnsubscribedError
83
+ throw :graphql_subscription_unsubscribed
94
84
  end
95
85
 
96
86
  READING_SCOPE = ::Object.new
@@ -40,7 +40,6 @@ module GraphQL
40
40
  # @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
41
41
  # @param context [GraphQL::Query::Context]
42
42
  # @param schema [GraphQL::Schema]
43
- # @param deep_check [Boolean]
44
43
  def initialize(filter, context:, schema:)
45
44
  @schema = schema.interpreter? ? schema : schema.graphql_definition
46
45
  # Cache these to avoid repeated hits to the inheritance chain when one isn't present
@@ -51,7 +50,7 @@ module GraphQL
51
50
  @visibility_cache = read_through { |m| filter.call(m, context) }
52
51
  end
53
52
 
54
- # @return [Array<GraphQL::BaseType>] Visible types in the schema
53
+ # @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
55
54
  def types
56
55
  @types ||= begin
57
56
  vis_types = {}
@@ -199,7 +198,7 @@ module GraphQL
199
198
  if (iface_field_defn = interface_type.get_field(field_defn.graphql_name))
200
199
  any_interface_has_field = true
201
200
 
202
- if visible?(interface_type) && visible_field?(interface_type, iface_field_defn)
201
+ if interfaces(type_defn).include?(interface_type) && visible_field?(interface_type, iface_field_defn)
203
202
  any_interface_has_visible_field = true
204
203
  end
205
204
  end
@@ -100,31 +100,43 @@ module GraphQL
100
100
  # Lookup the saved data for this subscription
101
101
  query_data = read_subscription(subscription_id)
102
102
  if query_data.nil?
103
- # Jump down to the `delete_subscription` call
104
- raise GraphQL::Schema::Subscription::UnsubscribedError
103
+ delete_subscription(subscription_id)
104
+ return nil
105
105
  end
106
+
106
107
  # Fetch the required keys from the saved data
107
108
  query_string = query_data.fetch(:query_string)
108
109
  variables = query_data.fetch(:variables)
109
110
  context = query_data.fetch(:context)
110
111
  operation_name = query_data.fetch(:operation_name)
111
- # Re-evaluate the saved query
112
- @schema.execute(
113
- query: query_string,
114
- context: context,
115
- subscription_topic: event.topic,
116
- operation_name: operation_name,
117
- variables: variables,
118
- root_value: object,
119
- )
120
- rescue GraphQL::Schema::Subscription::NoUpdateError
121
- # This update was skipped in user code; do nothing.
122
- nil
123
- rescue GraphQL::Schema::Subscription::UnsubscribedError
124
- # `unsubscribe` was called, clean up on our side
125
- # TODO also send `{more: false}` to client?
126
- delete_subscription(subscription_id)
127
- nil
112
+ result = nil
113
+ # this will be set to `false` unless `.execute` is terminated
114
+ # with a `throw :graphql_subscription_unsubscribed`
115
+ unsubscribed = true
116
+ catch(:graphql_subscription_unsubscribed) do
117
+ catch(:graphql_no_subscription_update) do
118
+ # Re-evaluate the saved query,
119
+ # but if it terminates early with a `throw`,
120
+ # it will stay `nil`
121
+ result = @schema.execute(
122
+ query: query_string,
123
+ context: context,
124
+ subscription_topic: event.topic,
125
+ operation_name: operation_name,
126
+ variables: variables,
127
+ root_value: object,
128
+ )
129
+ end
130
+ unsubscribed = false
131
+ end
132
+
133
+ if unsubscribed
134
+ # `unsubscribe` was called, clean up on our side
135
+ # TODO also send `{more: false}` to client?
136
+ delete_subscription(subscription_id)
137
+ end
138
+
139
+ result
128
140
  end
129
141
 
130
142
  # Run the update query for this subscription and deliver it
@@ -55,7 +55,15 @@ module GraphQL
55
55
  end
56
56
 
57
57
  def platform_field_key(type, field)
58
- "graphql.#{type.name}.#{field.name}"
58
+ "graphql.#{type.graphql_name}.#{field.graphql_name}"
59
+ end
60
+
61
+ def platform_authorized_key(type)
62
+ "graphql.authorized.#{type.graphql_name}"
63
+ end
64
+
65
+ def platform_resolve_type_key(type)
66
+ "graphql.resolve_type.#{type.graphql_name}"
59
67
  end
60
68
 
61
69
  private
@@ -107,7 +115,7 @@ module GraphQL
107
115
  else
108
116
  [key, data[key]]
109
117
  end
110
- end.flatten.each_slice(2).to_h.merge(Spec: 'graphql')
118
+ end.flatten(2).each_slice(2).to_h.merge(Spec: 'graphql')
111
119
  end
112
120
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
113
121
 
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
 
3
- # frozen_string_literal: true
4
5
  module GraphQL
5
6
  module Types
6
7
  # This scalar takes `Time`s and transmits them as strings,
@@ -48,7 +48,7 @@ module GraphQL
48
48
  # It's called when you subclass this base connection, trying to use the
49
49
  # class name to set defaults. You can call it again in the class definition
50
50
  # to override the default (or provide a value, if the default lookup failed).
51
- def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true)
51
+ def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true, node_nullable: true)
52
52
  # Set this connection's graphql name
53
53
  node_type_name = node_type.graphql_name
54
54
 
@@ -61,7 +61,7 @@ module GraphQL
61
61
  description: "A list of edges.",
62
62
  edge_class: edge_class
63
63
 
64
- define_nodes_field if nodes_field
64
+ define_nodes_field(node_nullable) if nodes_field
65
65
 
66
66
  description("The connection type for #{node_type_name}.")
67
67
  end
@@ -90,9 +90,10 @@ module GraphQL
90
90
 
91
91
  private
92
92
 
93
- def define_nodes_field
94
- field :nodes, [@node_type, null: true],
95
- null: true,
93
+ def define_nodes_field(nullable = true)
94
+ type = nullable ? [@node_type, null: true] : [@node_type]
95
+ field :nodes, type,
96
+ null: nullable,
96
97
  description: "A list of nodes."
97
98
  end
98
99
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.11.3"
3
+ VERSION = "1.11.4"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.3
4
+ version: 1.11.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-13 00:00:00.000000000 Z
11
+ date: 2020-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips