graphql 1.12.22 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/mutation_generator.rb +1 -1
  3. data/lib/generators/graphql/type_generator.rb +0 -1
  4. data/lib/graphql/analysis/ast/field_usage.rb +2 -2
  5. data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
  6. data/lib/graphql/analysis/ast/visitor.rb +4 -4
  7. data/lib/graphql/backtrace/table.rb +1 -1
  8. data/lib/graphql/dataloader.rb +55 -22
  9. data/lib/graphql/directive.rb +0 -4
  10. data/lib/graphql/enum_type.rb +5 -1
  11. data/lib/graphql/execution/errors.rb +1 -0
  12. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  13. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -2
  14. data/lib/graphql/execution/interpreter/runtime.rb +20 -12
  15. data/lib/graphql/execution/lookahead.rb +2 -2
  16. data/lib/graphql/execution/multiplex.rb +1 -1
  17. data/lib/graphql/introspection/directive_type.rb +1 -1
  18. data/lib/graphql/introspection/entry_points.rb +2 -2
  19. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  20. data/lib/graphql/introspection/field_type.rb +2 -2
  21. data/lib/graphql/introspection/input_value_type.rb +4 -4
  22. data/lib/graphql/introspection/schema_type.rb +2 -2
  23. data/lib/graphql/introspection/type_type.rb +10 -10
  24. data/lib/graphql/language/block_string.rb +0 -4
  25. data/lib/graphql/language/document_from_schema_definition.rb +4 -2
  26. data/lib/graphql/language/lexer.rb +0 -3
  27. data/lib/graphql/language/lexer.rl +0 -4
  28. data/lib/graphql/language/nodes.rb +3 -11
  29. data/lib/graphql/language/parser.rb +442 -434
  30. data/lib/graphql/language/parser.y +5 -4
  31. data/lib/graphql/language/printer.rb +6 -1
  32. data/lib/graphql/language/sanitized_printer.rb +5 -5
  33. data/lib/graphql/language/token.rb +0 -4
  34. data/lib/graphql/name_validator.rb +0 -4
  35. data/lib/graphql/query/arguments.rb +1 -1
  36. data/lib/graphql/query/arguments_cache.rb +1 -1
  37. data/lib/graphql/query/context.rb +5 -2
  38. data/lib/graphql/query/literal_input.rb +1 -1
  39. data/lib/graphql/query/null_context.rb +12 -7
  40. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  41. data/lib/graphql/query/variables.rb +5 -1
  42. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  43. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  44. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  45. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  46. data/lib/graphql/rubocop.rb +4 -0
  47. data/lib/graphql/schema/addition.rb +37 -28
  48. data/lib/graphql/schema/argument.rb +6 -6
  49. data/lib/graphql/schema/build_from_definition.rb +5 -5
  50. data/lib/graphql/schema/directive/feature.rb +1 -1
  51. data/lib/graphql/schema/directive/flagged.rb +2 -2
  52. data/lib/graphql/schema/directive/include.rb +1 -1
  53. data/lib/graphql/schema/directive/skip.rb +1 -1
  54. data/lib/graphql/schema/directive/transform.rb +1 -1
  55. data/lib/graphql/schema/directive.rb +2 -2
  56. data/lib/graphql/schema/enum.rb +57 -9
  57. data/lib/graphql/schema/enum_value.rb +4 -0
  58. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  59. data/lib/graphql/schema/field.rb +92 -17
  60. data/lib/graphql/schema/find_inherited_value.rb +1 -0
  61. data/lib/graphql/schema/finder.rb +5 -5
  62. data/lib/graphql/schema/input_object.rb +6 -5
  63. data/lib/graphql/schema/interface.rb +8 -19
  64. data/lib/graphql/schema/member/accepts_definition.rb +8 -1
  65. data/lib/graphql/schema/member/build_type.rb +0 -4
  66. data/lib/graphql/schema/member/has_arguments.rb +55 -13
  67. data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
  68. data/lib/graphql/schema/member/has_fields.rb +76 -18
  69. data/lib/graphql/schema/member/has_interfaces.rb +90 -0
  70. data/lib/graphql/schema/member.rb +1 -0
  71. data/lib/graphql/schema/object.rb +7 -74
  72. data/lib/graphql/schema/printer.rb +1 -1
  73. data/lib/graphql/schema/relay_classic_mutation.rb +29 -3
  74. data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
  75. data/lib/graphql/schema/resolver.rb +19 -5
  76. data/lib/graphql/schema/subscription.rb +11 -1
  77. data/lib/graphql/schema/type_expression.rb +1 -1
  78. data/lib/graphql/schema/type_membership.rb +18 -4
  79. data/lib/graphql/schema/union.rb +6 -1
  80. data/lib/graphql/schema/validator/format_validator.rb +0 -4
  81. data/lib/graphql/schema/validator/numericality_validator.rb +1 -0
  82. data/lib/graphql/schema/warden.rb +116 -52
  83. data/lib/graphql/schema.rb +87 -15
  84. data/lib/graphql/static_validation/base_visitor.rb +5 -5
  85. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  86. data/lib/graphql/static_validation/literal_validator.rb +1 -1
  87. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  88. data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
  89. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -3
  90. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
  91. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +7 -7
  92. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +6 -4
  93. data/lib/graphql/subscriptions/event.rb +20 -12
  94. data/lib/graphql/subscriptions.rb +17 -19
  95. data/lib/graphql/types/relay/has_node_field.rb +1 -1
  96. data/lib/graphql/types/relay/has_nodes_field.rb +1 -1
  97. data/lib/graphql/version.rb +1 -1
  98. data/lib/graphql.rb +9 -31
  99. metadata +10 -5
@@ -170,10 +170,12 @@ module GraphQL
170
170
  first_subscription_id = first_event.context.fetch(:subscription_id)
171
171
  object ||= load_action_cable_message(message, first_event.context)
172
172
  result = execute_update(first_subscription_id, first_event, object)
173
- # Having calculated the result _once_, send the same payload to all subscribers
174
- events.each do |event|
175
- subscription_id = event.context.fetch(:subscription_id)
176
- deliver(subscription_id, result)
173
+ if !result.nil?
174
+ # Having calculated the result _once_, send the same payload to all subscribers
175
+ events.each do |event|
176
+ subscription_id = event.context.fetch(:subscription_id)
177
+ deliver(subscription_id, result)
178
+ end
177
179
  end
178
180
  end
179
181
  end
@@ -23,15 +23,23 @@ module GraphQL
23
23
  @arguments = arguments
24
24
  @context = context
25
25
  field ||= context.field
26
- scope_val = scope || (context && field.subscription_scope && context[field.subscription_scope])
26
+ scope_key = field.subscription_scope
27
+ scope_val = scope || (context && scope_key && context[scope_key])
28
+ if scope_key &&
29
+ (subscription = field.resolver) &&
30
+ (subscription.respond_to?(:subscription_scope_optional?)) &&
31
+ !subscription.subscription_scope_optional? &&
32
+ scope_val.nil?
33
+ raise Subscriptions::SubscriptionScopeMissingError, "#{field.path} (#{subscription}) requires a `scope:` value to trigger updates (Set `subscription_scope ..., optional: true` to disable this requirement)"
34
+ end
27
35
 
28
- @topic = self.class.serialize(name, arguments, field, scope: scope_val)
36
+ @topic = self.class.serialize(name, arguments, field, scope: scope_val, context: context)
29
37
  end
30
38
 
31
39
  # @return [String] an identifier for this unit of subscription
32
- def self.serialize(_name, arguments, field, scope:)
40
+ def self.serialize(_name, arguments, field, scope:, context: GraphQL::Query::NullContext)
33
41
  subscription = field.resolver || GraphQL::Schema::Subscription
34
- normalized_args = stringify_args(field, arguments.to_h)
42
+ normalized_args = stringify_args(field, arguments.to_h, context)
35
43
  subscription.topic_for(arguments: normalized_args, field: field, scope: scope)
36
44
  end
37
45
 
@@ -83,7 +91,7 @@ module GraphQL
83
91
  end
84
92
  end
85
93
 
86
- def stringify_args(arg_owner, args)
94
+ def stringify_args(arg_owner, args, context)
87
95
  arg_owner = arg_owner.respond_to?(:unwrap) ? arg_owner.unwrap : arg_owner # remove list and non-null wrappers
88
96
  case args
89
97
  when Hash
@@ -91,13 +99,13 @@ module GraphQL
91
99
  args.each do |k, v|
92
100
  arg_name = k.to_s
93
101
  camelized_arg_name = GraphQL::Schema::Member::BuildType.camelize(arg_name)
94
- arg_defn = get_arg_definition(arg_owner, camelized_arg_name)
102
+ arg_defn = get_arg_definition(arg_owner, camelized_arg_name, context)
95
103
 
96
104
  if arg_defn
97
105
  normalized_arg_name = camelized_arg_name
98
106
  else
99
107
  normalized_arg_name = arg_name
100
- arg_defn = get_arg_definition(arg_owner, normalized_arg_name)
108
+ arg_defn = get_arg_definition(arg_owner, normalized_arg_name, context)
101
109
  end
102
110
  arg_base_type = arg_defn.type.unwrap
103
111
  # In the case where the value being emitted is seen as a "JSON"
@@ -113,22 +121,22 @@ module GraphQL
113
121
  end
114
122
  next_args[normalized_arg_name] = sorted_value.respond_to?(:to_json) ? sorted_value.to_json : sorted_value
115
123
  else
116
- next_args[normalized_arg_name] = stringify_args(arg_base_type, v)
124
+ next_args[normalized_arg_name] = stringify_args(arg_base_type, v, context)
117
125
  end
118
126
  end
119
127
  # Make sure they're deeply sorted
120
128
  next_args.sort.to_h
121
129
  when Array
122
- args.map { |a| stringify_args(arg_owner, a) }
130
+ args.map { |a| stringify_args(arg_owner, a, context) }
123
131
  when GraphQL::Schema::InputObject
124
- stringify_args(arg_owner, args.to_h)
132
+ stringify_args(arg_owner, args.to_h, context)
125
133
  else
126
134
  args
127
135
  end
128
136
  end
129
137
 
130
- def get_arg_definition(arg_owner, arg_name)
131
- arg_owner.arguments[arg_name] || arg_owner.arguments.each_value.find { |v| v.keyword.to_s == arg_name }
138
+ def get_arg_definition(arg_owner, arg_name, context)
139
+ arg_owner.get_argument(arg_name, context) || arg_owner.arguments(context).each_value.find { |v| v.keyword.to_s == arg_name }
132
140
  end
133
141
  end
134
142
  end
@@ -16,6 +16,13 @@ module GraphQL
16
16
  class InvalidTriggerError < GraphQL::Error
17
17
  end
18
18
 
19
+ # Raised when either:
20
+ # - An initial subscription didn't have a value for `context[subscription_scope]`
21
+ # - Or, an update didn't pass `.trigger(..., scope:)`
22
+ # When raised, the initial subscription or update fails completely.
23
+ class SubscriptionScopeMissingError < GraphQL::Error
24
+ end
25
+
19
26
  # @see {Subscriptions#initialize} for options, concrete implementations may add options.
20
27
  def self.use(defn, options = {})
21
28
  schema = defn.is_a?(Class) ? defn : defn.target
@@ -76,7 +83,8 @@ module GraphQL
76
83
  end
77
84
 
78
85
  # Normalize symbol-keyed args to strings, try camelizing them
79
- normalized_args = normalize_arguments(normalized_event_name, field, args)
86
+ # Should this accept a real context somehow?
87
+ normalized_args = normalize_arguments(normalized_event_name, field, args, GraphQL::Query::NullContext)
80
88
 
81
89
  event = Subscriptions::Event.new(
82
90
  name: normalized_event_name,
@@ -151,16 +159,6 @@ module GraphQL
151
159
  # @param object [Object]
152
160
  # @return [void]
153
161
  def execute_all(event, object)
154
- each_subscription_id(event) do |subscription_id|
155
- execute(subscription_id, event, object)
156
- end
157
- end
158
-
159
- # Get each `subscription_id` subscribed to `event.topic` and yield them
160
- # @param event [GraphQL::Subscriptions::Event]
161
- # @yieldparam subscription_id [String]
162
- # @return [void]
163
- def each_subscription_id(event)
164
162
  raise GraphQL::RequiredImplementationMissingError
165
163
  end
166
164
 
@@ -233,7 +231,7 @@ module GraphQL
233
231
  # @param arg_owner [GraphQL::Field, GraphQL::BaseType]
234
232
  # @param args [Hash, Array, Any] some GraphQL input value to coerce as `arg_owner`
235
233
  # @return [Any] normalized arguments value
236
- def normalize_arguments(event_name, arg_owner, args)
234
+ def normalize_arguments(event_name, arg_owner, args, context)
237
235
  case arg_owner
238
236
  when GraphQL::Field, GraphQL::InputObjectType, GraphQL::Schema::Field, Class
239
237
  if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
@@ -244,19 +242,19 @@ module GraphQL
244
242
  missing_arg_names = []
245
243
  args.each do |k, v|
246
244
  arg_name = k.to_s
247
- arg_defn = arg_owner.arguments[arg_name]
245
+ arg_defn = arg_owner.get_argument(arg_name, context)
248
246
  if arg_defn
249
247
  normalized_arg_name = arg_name
250
248
  else
251
249
  normalized_arg_name = normalize_name(arg_name)
252
- arg_defn = arg_owner.arguments[normalized_arg_name]
250
+ arg_defn = arg_owner.get_argument(normalized_arg_name, context)
253
251
  end
254
252
 
255
253
  if arg_defn
256
254
  if arg_defn.loads
257
255
  normalized_arg_name = arg_defn.keyword.to_s
258
256
  end
259
- normalized = normalize_arguments(event_name, arg_defn.type, v)
257
+ normalized = normalize_arguments(event_name, arg_defn.type, v, context)
260
258
  normalized_args[normalized_arg_name] = normalized
261
259
  else
262
260
  # Couldn't find a matching argument definition
@@ -266,12 +264,12 @@ module GraphQL
266
264
 
267
265
  # Backfill default values so that trigger arguments
268
266
  # match query arguments.
269
- arg_owner.arguments.each do |name, arg_defn|
267
+ arg_owner.arguments(context).each do |_name, arg_defn|
270
268
  if arg_defn.default_value? && !normalized_args.key?(arg_defn.name)
271
269
  default_value = arg_defn.default_value
272
270
  # We don't have an underlying "object" here, so it can't call methods.
273
271
  # This is broken.
274
- normalized_args[arg_defn.name] = arg_defn.prepare_value(nil, default_value, context: GraphQL::Query::NullContext)
272
+ normalized_args[arg_defn.name] = arg_defn.prepare_value(nil, default_value, context: context)
275
273
  end
276
274
  end
277
275
 
@@ -290,9 +288,9 @@ module GraphQL
290
288
 
291
289
  normalized_args
292
290
  when GraphQL::ListType, GraphQL::Schema::List
293
- args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a) }
291
+ args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
294
292
  when GraphQL::NonNullType, GraphQL::Schema::NonNull
295
- normalize_arguments(event_name, arg_owner.of_type, args)
293
+ normalize_arguments(event_name, arg_owner.of_type, args, context)
296
294
  else
297
295
  args
298
296
  end
@@ -22,7 +22,7 @@ module GraphQL
22
22
 
23
23
  def field_block
24
24
  Proc.new {
25
- argument :id, "ID!", required: true,
25
+ argument :id, "ID!",
26
26
  description: "ID of the object."
27
27
 
28
28
  def resolve(obj, args, ctx)
@@ -22,7 +22,7 @@ module GraphQL
22
22
 
23
23
  def field_block
24
24
  Proc.new {
25
- argument :ids, "[ID!]!", required: true,
25
+ argument :ids, "[ID!]!",
26
26
  description: "IDs of the objects."
27
27
 
28
28
  def resolve(obj, args, ctx)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.12.22"
3
+ VERSION = "1.13.0"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -55,31 +55,6 @@ module GraphQL
55
55
  def self.scan_with_ragel(graphql_string)
56
56
  GraphQL::Language::Lexer.tokenize(graphql_string)
57
57
  end
58
-
59
- # Support Ruby 2.2 by implementing `-"str"`. If we drop 2.2 support, we can remove this backport.
60
- if !String.method_defined?(:-@)
61
- module StringDedupBackport
62
- refine String do
63
- def -@
64
- if frozen?
65
- self
66
- else
67
- self.dup.freeze
68
- end
69
- end
70
- end
71
- end
72
- end
73
-
74
- if !String.method_defined?(:match?)
75
- module StringMatchBackport
76
- refine String do
77
- def match?(pattern)
78
- self =~ pattern
79
- end
80
- end
81
- end
82
- end
83
58
  end
84
59
 
85
60
  # Order matters for these:
@@ -125,10 +100,13 @@ require "graphql/execution"
125
100
  require "graphql/pagination"
126
101
  require "graphql/schema"
127
102
  require "graphql/query"
103
+ require "graphql/types"
104
+ require "graphql/dataloader"
105
+ require "graphql/filter"
106
+ require "graphql/internal_representation"
128
107
  require "graphql/directive"
108
+ require "graphql/static_validation"
129
109
  require "graphql/execution"
130
- require "graphql/types"
131
- require "graphql/relay"
132
110
  require "graphql/boolean_type"
133
111
  require "graphql/float_type"
134
112
  require "graphql/id_type"
@@ -137,11 +115,8 @@ require "graphql/string_type"
137
115
  require "graphql/schema/built_in_types"
138
116
  require "graphql/schema/loader"
139
117
  require "graphql/schema/printer"
140
- require "graphql/filter"
141
- require "graphql/internal_representation"
142
- require "graphql/static_validation"
143
- require "graphql/dataloader"
144
118
  require "graphql/introspection"
119
+ require "graphql/relay"
145
120
 
146
121
  require "graphql/version"
147
122
  require "graphql/compatibility"
@@ -156,6 +131,9 @@ require "graphql/unauthorized_error"
156
131
  require "graphql/unauthorized_field_error"
157
132
  require "graphql/load_application_object_failed_error"
158
133
  require "graphql/deprecation"
134
+ require "graphql/directive/include_directive"
135
+ require "graphql/directive/skip_directive"
136
+ require "graphql/directive/deprecated_directive"
159
137
 
160
138
  module GraphQL
161
139
  # Ruby has `deprecate_constant`,
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.12.22
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-08 00:00:00.000000000 Z
11
+ date: 2021-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - '='
130
130
  - !ruby/object:Gem::Version
131
- version: '0.68'
131
+ version: '1.12'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
- version: '0.68'
138
+ version: '1.12'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: parser
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -467,6 +467,10 @@ files:
467
467
  - lib/graphql/relay/range_add.rb
468
468
  - lib/graphql/relay/relation_connection.rb
469
469
  - lib/graphql/relay/type_extensions.rb
470
+ - lib/graphql/rubocop.rb
471
+ - lib/graphql/rubocop/graphql/base_cop.rb
472
+ - lib/graphql/rubocop/graphql/default_null_true.rb
473
+ - lib/graphql/rubocop/graphql/default_required_true.rb
470
474
  - lib/graphql/runtime_type_error.rb
471
475
  - lib/graphql/scalar_type.rb
472
476
  - lib/graphql/schema.rb
@@ -514,6 +518,7 @@ files:
514
518
  - lib/graphql/schema/member/has_deprecation_reason.rb
515
519
  - lib/graphql/schema/member/has_directives.rb
516
520
  - lib/graphql/schema/member/has_fields.rb
521
+ - lib/graphql/schema/member/has_interfaces.rb
517
522
  - lib/graphql/schema/member/has_path.rb
518
523
  - lib/graphql/schema/member/has_unresolved_type_error.rb
519
524
  - lib/graphql/schema/member/has_validators.rb
@@ -695,7 +700,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
695
700
  requirements:
696
701
  - - ">="
697
702
  - !ruby/object:Gem::Version
698
- version: 2.2.0
703
+ version: 2.4.0
699
704
  required_rubygems_version: !ruby/object:Gem::Requirement
700
705
  requirements:
701
706
  - - ">="