graphql 1.11.3 → 1.11.4

Sign up to get free protection for your applications and to get access to all the features.
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