graphql 1.12.23 → 1.13.3

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +3 -1
  3. data/lib/generators/graphql/install_generator.rb +9 -2
  4. data/lib/generators/graphql/mutation_generator.rb +1 -1
  5. data/lib/generators/graphql/type_generator.rb +0 -1
  6. data/lib/graphql/analysis/ast/field_usage.rb +2 -2
  7. data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
  8. data/lib/graphql/analysis/ast/visitor.rb +4 -4
  9. data/lib/graphql/backtrace/table.rb +1 -1
  10. data/lib/graphql/base_type.rb +4 -2
  11. data/lib/graphql/boolean_type.rb +1 -1
  12. data/lib/graphql/dataloader.rb +55 -22
  13. data/lib/graphql/directive/deprecated_directive.rb +1 -1
  14. data/lib/graphql/directive/include_directive.rb +1 -1
  15. data/lib/graphql/directive/skip_directive.rb +1 -1
  16. data/lib/graphql/directive.rb +0 -4
  17. data/lib/graphql/enum_type.rb +5 -1
  18. data/lib/graphql/execution/errors.rb +1 -0
  19. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  20. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -2
  21. data/lib/graphql/execution/interpreter/runtime.rb +31 -19
  22. data/lib/graphql/execution/lookahead.rb +2 -2
  23. data/lib/graphql/execution/multiplex.rb +4 -1
  24. data/lib/graphql/float_type.rb +1 -1
  25. data/lib/graphql/id_type.rb +1 -1
  26. data/lib/graphql/int_type.rb +1 -1
  27. data/lib/graphql/introspection/directive_type.rb +1 -1
  28. data/lib/graphql/introspection/entry_points.rb +2 -2
  29. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  30. data/lib/graphql/introspection/field_type.rb +2 -2
  31. data/lib/graphql/introspection/input_value_type.rb +4 -4
  32. data/lib/graphql/introspection/schema_type.rb +2 -2
  33. data/lib/graphql/introspection/type_type.rb +10 -10
  34. data/lib/graphql/language/block_string.rb +2 -6
  35. data/lib/graphql/language/document_from_schema_definition.rb +10 -4
  36. data/lib/graphql/language/lexer.rb +0 -3
  37. data/lib/graphql/language/lexer.rl +0 -4
  38. data/lib/graphql/language/nodes.rb +3 -2
  39. data/lib/graphql/language/parser.rb +442 -434
  40. data/lib/graphql/language/parser.y +5 -4
  41. data/lib/graphql/language/printer.rb +6 -1
  42. data/lib/graphql/language/sanitized_printer.rb +5 -5
  43. data/lib/graphql/language/token.rb +0 -4
  44. data/lib/graphql/name_validator.rb +0 -4
  45. data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
  46. data/lib/graphql/pagination/relation_connection.rb +55 -28
  47. data/lib/graphql/query/arguments.rb +1 -1
  48. data/lib/graphql/query/arguments_cache.rb +1 -1
  49. data/lib/graphql/query/context.rb +15 -2
  50. data/lib/graphql/query/literal_input.rb +1 -1
  51. data/lib/graphql/query/null_context.rb +12 -7
  52. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  53. data/lib/graphql/query/variables.rb +5 -1
  54. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  55. data/lib/graphql/relay/global_id_resolve.rb +1 -1
  56. data/lib/graphql/relay/page_info.rb +1 -1
  57. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  58. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  59. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  60. data/lib/graphql/rubocop.rb +4 -0
  61. data/lib/graphql/schema/addition.rb +37 -28
  62. data/lib/graphql/schema/argument.rb +13 -15
  63. data/lib/graphql/schema/build_from_definition.rb +5 -5
  64. data/lib/graphql/schema/directive/feature.rb +1 -1
  65. data/lib/graphql/schema/directive/flagged.rb +2 -2
  66. data/lib/graphql/schema/directive/include.rb +1 -1
  67. data/lib/graphql/schema/directive/skip.rb +1 -1
  68. data/lib/graphql/schema/directive/transform.rb +1 -1
  69. data/lib/graphql/schema/directive.rb +7 -3
  70. data/lib/graphql/schema/enum.rb +60 -10
  71. data/lib/graphql/schema/enum_value.rb +6 -0
  72. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  73. data/lib/graphql/schema/field.rb +229 -77
  74. data/lib/graphql/schema/field_extension.rb +89 -2
  75. data/lib/graphql/schema/find_inherited_value.rb +1 -0
  76. data/lib/graphql/schema/finder.rb +5 -5
  77. data/lib/graphql/schema/input_object.rb +23 -5
  78. data/lib/graphql/schema/interface.rb +11 -20
  79. data/lib/graphql/schema/introspection_system.rb +1 -1
  80. data/lib/graphql/schema/list.rb +3 -1
  81. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  82. data/lib/graphql/schema/member/build_type.rb +0 -4
  83. data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
  84. data/lib/graphql/schema/member/has_arguments.rb +55 -13
  85. data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
  86. data/lib/graphql/schema/member/has_fields.rb +76 -18
  87. data/lib/graphql/schema/member/has_interfaces.rb +90 -0
  88. data/lib/graphql/schema/member.rb +1 -0
  89. data/lib/graphql/schema/non_null.rb +7 -1
  90. data/lib/graphql/schema/object.rb +10 -75
  91. data/lib/graphql/schema/printer.rb +1 -1
  92. data/lib/graphql/schema/relay_classic_mutation.rb +37 -3
  93. data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
  94. data/lib/graphql/schema/resolver.rb +37 -17
  95. data/lib/graphql/schema/scalar.rb +2 -0
  96. data/lib/graphql/schema/subscription.rb +11 -1
  97. data/lib/graphql/schema/traversal.rb +1 -1
  98. data/lib/graphql/schema/type_expression.rb +1 -1
  99. data/lib/graphql/schema/type_membership.rb +18 -4
  100. data/lib/graphql/schema/union.rb +8 -1
  101. data/lib/graphql/schema/validator/format_validator.rb +0 -4
  102. data/lib/graphql/schema/validator/numericality_validator.rb +1 -0
  103. data/lib/graphql/schema/validator/required_validator.rb +29 -15
  104. data/lib/graphql/schema/validator.rb +4 -7
  105. data/lib/graphql/schema/warden.rb +116 -52
  106. data/lib/graphql/schema.rb +111 -23
  107. data/lib/graphql/static_validation/all_rules.rb +1 -0
  108. data/lib/graphql/static_validation/base_visitor.rb +5 -5
  109. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  110. data/lib/graphql/static_validation/literal_validator.rb +1 -1
  111. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  112. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
  113. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  114. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  115. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +2 -2
  116. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
  117. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
  118. data/lib/graphql/string_type.rb +1 -1
  119. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -4
  120. data/lib/graphql/subscriptions/event.rb +20 -12
  121. data/lib/graphql/subscriptions/serialize.rb +22 -2
  122. data/lib/graphql/subscriptions.rb +17 -19
  123. data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
  124. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  125. data/lib/graphql/types/relay/connection_behaviors.rb +26 -9
  126. data/lib/graphql/types/relay/default_relay.rb +5 -1
  127. data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
  128. data/lib/graphql/types/relay/has_node_field.rb +1 -1
  129. data/lib/graphql/types/relay/has_nodes_field.rb +1 -1
  130. data/lib/graphql/types/relay/node_field.rb +14 -3
  131. data/lib/graphql/types/relay/nodes_field.rb +13 -3
  132. data/lib/graphql/version.rb +1 -1
  133. data/lib/graphql.rb +10 -32
  134. metadata +13 -5
@@ -24,7 +24,13 @@ module GraphQL
24
24
  end
25
25
 
26
26
  def get_type(name)
27
- @types[name] || @schema.get_type(name)
27
+ local_type = @types[name]
28
+ # This isn't really sophisticated, but
29
+ # I think it's good enough to support the current usage of LateBoundTypes
30
+ if local_type.is_a?(Array)
31
+ local_type = local_type.first
32
+ end
33
+ local_type || @schema.get_type(name)
28
34
  end
29
35
 
30
36
  # Lookup using `own_types` here because it's ok to override
@@ -77,13 +83,13 @@ module GraphQL
77
83
 
78
84
  def update_type_owner(owner, type)
79
85
  case owner
80
- when Class
86
+ when Module
81
87
  if owner.kind.union?
82
88
  # It's a union with possible_types
83
89
  # Replace the item by class name
84
90
  owner.assign_type_membership_object_type(type)
85
91
  @possible_types[owner.graphql_name] = owner.possible_types
86
- elsif type.kind.interface? && owner.kind.object?
92
+ elsif type.kind.interface? && (owner.kind.object? || owner.kind.interface?)
87
93
  new_interfaces = []
88
94
  owner.interfaces.each do |int_t|
89
95
  if int_t.is_a?(String) && int_t == type.graphql_name
@@ -98,12 +104,11 @@ module GraphQL
98
104
  owner.implements(*new_interfaces)
99
105
  new_interfaces.each do |int|
100
106
  pt = @possible_types[int.graphql_name] ||= []
101
- if !pt.include?(owner)
107
+ if !pt.include?(owner) && owner.is_a?(Class)
102
108
  pt << owner
103
109
  end
104
110
  end
105
111
  end
106
-
107
112
  when nil
108
113
  # It's a root type
109
114
  @types[type.graphql_name] = type
@@ -148,42 +153,42 @@ module GraphQL
148
153
  um << owner
149
154
  end
150
155
 
151
- if (prev_type = get_local_type(type.graphql_name))
152
- if prev_type != type
153
- raise DuplicateTypeNamesError.new(
154
- type_name: type.graphql_name,
155
- first_definition: prev_type,
156
- second_definition: type,
157
- path: path,
158
- )
159
- else
160
- # This type was already added
161
- end
156
+ if (prev_type = get_local_type(type.graphql_name)) && prev_type == type
157
+ # No need to re-visit
162
158
  elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
163
159
  @directives << type
164
- type.arguments.each do |name, arg|
160
+ type.all_argument_definitions.each do |arg|
165
161
  arg_type = arg.type.unwrap
166
162
  references_to(arg_type, from: arg)
167
- add_type(arg_type, owner: arg, late_types: late_types, path: path + [name])
163
+ add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
168
164
  if arg.default_value?
169
165
  @arguments_with_default_values << arg
170
166
  end
171
167
  end
172
168
  else
173
- @types[type.graphql_name] = type
169
+ prev_type = @types[type.graphql_name]
170
+ if prev_type.nil?
171
+ @types[type.graphql_name] = type
172
+ elsif prev_type.is_a?(Array)
173
+ prev_type << type
174
+ else
175
+ @types[type.graphql_name] = [prev_type, type]
176
+ end
177
+
174
178
  add_directives_from(type)
175
179
  if type.kind.fields?
176
- type.fields.each do |name, field|
180
+ type.all_field_definitions.each do |field|
181
+ name = field.graphql_name
177
182
  field_type = field.type.unwrap
178
183
  references_to(field_type, from: field)
179
184
  field_path = path + [name]
180
185
  add_type(field_type, owner: field, late_types: late_types, path: field_path)
181
186
  add_directives_from(field)
182
- field.arguments.each do |arg_name, arg|
187
+ field.all_argument_definitions.each do |arg|
183
188
  add_directives_from(arg)
184
189
  arg_type = arg.type.unwrap
185
190
  references_to(arg_type, from: arg)
186
- add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg_name])
191
+ add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg.graphql_name])
187
192
  if arg.default_value?
188
193
  @arguments_with_default_values << arg
189
194
  end
@@ -191,19 +196,19 @@ module GraphQL
191
196
  end
192
197
  end
193
198
  if type.kind.input_object?
194
- type.arguments.each do |arg_name, arg|
199
+ type.all_argument_definitions.each do |arg|
195
200
  add_directives_from(arg)
196
201
  arg_type = arg.type.unwrap
197
202
  references_to(arg_type, from: arg)
198
- add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg_name])
203
+ add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
199
204
  if arg.default_value?
200
205
  @arguments_with_default_values << arg
201
206
  end
202
207
  end
203
208
  end
204
209
  if type.kind.union?
205
- @possible_types[type.graphql_name] = type.possible_types
206
- type.possible_types.each do |t|
210
+ @possible_types[type.graphql_name] = type.all_possible_types
211
+ type.all_possible_types.each do |t|
207
212
  add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
208
213
  end
209
214
  end
@@ -213,13 +218,17 @@ module GraphQL
213
218
  end
214
219
  end
215
220
  if type.kind.object?
216
- @possible_types[type.graphql_name] = [type]
221
+ possible_types_for_this_name = @possible_types[type.graphql_name] ||= []
222
+ possible_types_for_this_name << type
223
+ end
224
+
225
+ if type.kind.object? || type.kind.interface?
217
226
  type.interface_type_memberships.each do |interface_type_membership|
218
227
  case interface_type_membership
219
228
  when Schema::TypeMembership
220
229
  interface_type = interface_type_membership.abstract_type
221
230
  # We can get these now; we'll have to get late-bound types later
222
- if interface_type.is_a?(Module)
231
+ if interface_type.is_a?(Module) && type.is_a?(Class)
223
232
  implementers = @possible_types[interface_type.graphql_name] ||= []
224
233
  implementers << type
225
234
  end
@@ -2,10 +2,6 @@
2
2
  module GraphQL
3
3
  class Schema
4
4
  class Argument
5
- if !String.method_defined?(:-@)
6
- using GraphQL::StringDedupBackport
7
- end
8
-
9
5
  include GraphQL::Schema::Member::CachedGraphQLDefinition
10
6
  include GraphQL::Schema::Member::AcceptsDefinition
11
7
  include GraphQL::Schema::Member::HasPath
@@ -41,7 +37,7 @@ module GraphQL
41
37
  # @param arg_name [Symbol]
42
38
  # @param type_expr
43
39
  # @param desc [String]
44
- # @param required [Boolean] if true, this argument is non-null; if false, this argument is nullable
40
+ # @param required [Boolean, :nullable] if true, this argument is non-null; if false, this argument is nullable. If `:nullable`, then the argument must be provided, though it may be `null`.
45
41
  # @param description [String]
46
42
  # @param default_value [Object]
47
43
  # @param as [Symbol] Override the keyword name when passed to a method
@@ -52,12 +48,12 @@ module GraphQL
52
48
  # @param directives [Hash{Class => Hash}]
53
49
  # @param deprecation_reason [String]
54
50
  # @param validates [Hash, nil] Options for building validators, if any should be applied
55
- def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, validates: nil, directives: nil, deprecation_reason: nil, &definition_block)
51
+ def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, validates: nil, directives: nil, deprecation_reason: nil, &definition_block)
56
52
  arg_name ||= name
57
53
  @name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
58
54
  @type_expr = type_expr || type
59
55
  @description = desc || description
60
- @null = !required
56
+ @null = required != true
61
57
  @default_value = default_value
62
58
  @owner = owner
63
59
  @as = as
@@ -76,6 +72,9 @@ module GraphQL
76
72
  end
77
73
 
78
74
  self.validates(validates)
75
+ if required == :nullable
76
+ self.owner.validates(required: { argument: arg_name })
77
+ end
79
78
 
80
79
  if definition_block
81
80
  if definition_block.arity == 1
@@ -86,6 +85,10 @@ module GraphQL
86
85
  end
87
86
  end
88
87
 
88
+ def inspect
89
+ "#<#{self.class} #{path}: #{type.to_type_signature}#{description ? " @description=#{description.inspect}" : ""}>"
90
+ end
91
+
89
92
  # @return [Object] the value used when the client doesn't provide a value for this argument
90
93
  attr_reader :default_value
91
94
 
@@ -147,20 +150,15 @@ module GraphQL
147
150
  end
148
151
  end
149
152
  elsif as_type.kind.input_object?
150
- as_type.arguments.each do |_name, input_obj_arg|
151
- input_obj_arg = input_obj_arg.type_class
152
- # TODO: this skips input objects whose values were alread replaced with application objects.
153
- # See: https://github.com/rmosolgo/graphql-ruby/issues/2633
154
- if value.is_a?(InputObject) && value.key?(input_obj_arg.keyword) && !input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
155
- return false
156
- end
157
- end
153
+ return as_type.authorized?(obj, value, ctx)
158
154
  end
159
155
  # None of the early-return conditions were activated,
160
156
  # so this is authorized.
161
157
  true
162
158
  end
163
159
 
160
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
161
+
164
162
  def to_graphql
165
163
  argument = GraphQL::Argument.new
166
164
  argument.name = @name
@@ -3,12 +3,7 @@ require "graphql/schema/build_from_definition/resolve_map"
3
3
 
4
4
  module GraphQL
5
5
  class Schema
6
- # TODO Populate `.directive(...)` from here
7
6
  module BuildFromDefinition
8
- if !String.method_defined?(:-@)
9
- using GraphQL::StringDedupBackport
10
- end
11
-
12
7
  class << self
13
8
  # @see {Schema.from_definition}
14
9
  def from_definition(definition_string, parser: GraphQL.default_parser, **kwargs)
@@ -394,6 +389,11 @@ module GraphQL
394
389
  include GraphQL::Schema::Interface
395
390
  graphql_name(interface_type_definition.name)
396
391
  description(interface_type_definition.description)
392
+ interface_type_definition.interfaces.each do |interface_name|
393
+ "Implements: #{interface_type_definition} -> #{interface_name}"
394
+ interface_defn = type_resolver.call(interface_name)
395
+ implements(interface_defn)
396
+ end
397
397
  ast_node(interface_type_definition)
398
398
  builder.build_directives(self, interface_type_definition, type_resolver)
399
399
 
@@ -42,7 +42,7 @@ module GraphQL
42
42
  GraphQL::Schema::Directive::INLINE_FRAGMENT
43
43
  )
44
44
 
45
- argument :flag, String, required: true,
45
+ argument :flag, String,
46
46
  description: "The name of the feature to check before continuing"
47
47
 
48
48
  # Implement the Directive API
@@ -35,7 +35,7 @@ module GraphQL
35
35
  GraphQL::Schema::Directive::INPUT_FIELD_DEFINITION,
36
36
  )
37
37
 
38
- argument :by, [String], "Flags to check for this schema member", required: true
38
+ argument :by, [String], "Flags to check for this schema member"
39
39
 
40
40
  module VisibleByFlag
41
41
  def self.included(schema_class)
@@ -44,7 +44,7 @@ module GraphQL
44
44
 
45
45
  def visible?(context)
46
46
  if dir = self.directives.find { |d| d.is_a?(Flagged) }
47
- relevant_flags = (f = context[:flags]) && dir.arguments[:by] & f
47
+ relevant_flags = (f = context[:flags]) && dir.arguments[:by] & f # rubocop:disable Development/ContextIsPassedCop -- definition-related
48
48
  relevant_flags && relevant_flags.any? && super
49
49
  else
50
50
  super
@@ -11,7 +11,7 @@ module GraphQL
11
11
  GraphQL::Schema::Directive::INLINE_FRAGMENT
12
12
  )
13
13
 
14
- argument :if, Boolean, required: true,
14
+ argument :if, Boolean,
15
15
  description: "Included when true."
16
16
 
17
17
  default_directive true
@@ -11,7 +11,7 @@ module GraphQL
11
11
  GraphQL::Schema::Directive::INLINE_FRAGMENT
12
12
  )
13
13
 
14
- argument :if, Boolean, required: true,
14
+ argument :if, Boolean,
15
15
  description: "Skipped when true."
16
16
 
17
17
  default_directive true
@@ -24,7 +24,7 @@ module GraphQL
24
24
  GraphQL::Schema::Directive::FIELD,
25
25
  )
26
26
 
27
- argument :by, String, required: true,
27
+ argument :by, String,
28
28
  description: "The name of the transform to run if applicable"
29
29
 
30
30
  TRANSFORMS = [
@@ -8,6 +8,8 @@ module GraphQL
8
8
  # - {.resolve}: Wraps field resolution (so it should call `yield` to continue)
9
9
  class Directive < GraphQL::Schema::Member
10
10
  extend GraphQL::Schema::Member::HasArguments
11
+ extend GraphQL::Schema::Member::AcceptsDefinition
12
+
11
13
  class << self
12
14
  # Directives aren't types, they don't have kinds.
13
15
  undef_method :kind
@@ -53,6 +55,8 @@ module GraphQL
53
55
  default_directive
54
56
  end
55
57
 
58
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
59
+
56
60
  def to_graphql
57
61
  defn = GraphQL::Directive.new
58
62
  defn.name = self.graphql_name
@@ -61,9 +65,9 @@ module GraphQL
61
65
  defn.default_directive = self.default_directive
62
66
  defn.ast_node = ast_node
63
67
  defn.metadata[:type_class] = self
64
- arguments.each do |name, arg_defn|
65
- arg_graphql = arg_defn.to_graphql
66
- defn.arguments[arg_graphql.name] = arg_graphql
68
+ all_argument_definitions.each do |arg_defn|
69
+ arg_graphql = arg_defn.to_graphql(silence_deprecation_warning: true)
70
+ defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
67
71
  end
68
72
  # Make a reference to a classic-style Arguments class
69
73
  defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(defn)
@@ -46,20 +46,70 @@ module GraphQL
46
46
  def value(*args, **kwargs, &block)
47
47
  kwargs[:owner] = self
48
48
  value = enum_value_class.new(*args, **kwargs, &block)
49
- if own_values.key?(value.graphql_name)
50
- raise ArgumentError, "#{value.graphql_name} is already defined for #{self.graphql_name}, please remove one of the definitions."
49
+ key = value.graphql_name
50
+ prev_value = own_values[key]
51
+ case prev_value
52
+ when nil
53
+ own_values[key] = value
54
+ when GraphQL::Schema::EnumValue
55
+ own_values[key] = [prev_value, value]
56
+ when Array
57
+ prev_value << value
58
+ else
59
+ raise "Invariant: Unexpected enum value for #{key.inspect}: #{prev_value.inspect}"
51
60
  end
52
- own_values[value.graphql_name] = value
53
- nil
61
+ value
54
62
  end
55
63
 
56
- # @return [Hash<String => GraphQL::Schema::Enum::Value>] Possible values of this enum, keyed by name
57
- def values
58
- inherited_values = superclass <= GraphQL::Schema::Enum ? superclass.values : {}
59
- # Local values take precedence over inherited ones
60
- inherited_values.merge(own_values)
64
+ # @return [Array<GraphQL::Schema::EnumValue>] Possible values of this enum
65
+ def enum_values(context = GraphQL::Query::NullContext)
66
+ inherited_values = superclass.respond_to?(:enum_values) ? superclass.enum_values(context) : nil
67
+ visible_values = []
68
+ warden = Warden.from_context(context)
69
+ own_values.each do |key, values_entry|
70
+ if (v = Warden.visible_entry?(:visible_enum_value?, values_entry, context, warden))
71
+ visible_values << v
72
+ end
73
+ end
74
+
75
+ if inherited_values
76
+ # Local values take precedence over inherited ones
77
+ inherited_values.each do |i_val|
78
+ if !visible_values.any? { |v| v.graphql_name == i_val.graphql_name }
79
+ visible_values << i_val
80
+ end
81
+ end
82
+ end
83
+
84
+ visible_values
61
85
  end
62
86
 
87
+ # @return [Array<Schema::EnumValue>] An unfiltered list of all definitions
88
+ def all_enum_value_definitions
89
+ all_defns = if superclass.respond_to?(:all_enum_value_definitions)
90
+ superclass.all_enum_value_definitions
91
+ else
92
+ []
93
+ end
94
+
95
+ @own_values && @own_values.each do |_key, value|
96
+ if value.is_a?(Array)
97
+ all_defns.concat(value)
98
+ else
99
+ all_defns << value
100
+ end
101
+ end
102
+
103
+ all_defns
104
+ end
105
+
106
+ # @return [Hash<String => GraphQL::Schema::EnumValue>] Possible values of this enum, keyed by name.
107
+ def values(context = GraphQL::Query::NullContext)
108
+ enum_values(context).each_with_object({}) { |val, obj| obj[val.graphql_name] = val }
109
+ end
110
+
111
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
112
+
63
113
  # @return [GraphQL::EnumType]
64
114
  def to_graphql
65
115
  enum_type = GraphQL::EnumType.new
@@ -68,7 +118,7 @@ module GraphQL
68
118
  enum_type.introspection = introspection
69
119
  enum_type.ast_node = ast_node
70
120
  values.each do |name, val|
71
- enum_type.add_value(val.to_graphql)
121
+ enum_type.add_value(val.deprecated_to_graphql)
72
122
  end
73
123
  enum_type.metadata[:type_class] = self
74
124
  enum_type
@@ -73,6 +73,8 @@ module GraphQL
73
73
  @value
74
74
  end
75
75
 
76
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
77
+
76
78
  # @return [GraphQL::EnumType::EnumValue] A runtime-ready object derived from this object
77
79
  def to_graphql
78
80
  enum_value = GraphQL::EnumType::EnumValue.new
@@ -85,6 +87,10 @@ module GraphQL
85
87
  enum_value
86
88
  end
87
89
 
90
+ def inspect
91
+ "#<#{self.class} #{path} @value=#{@value.inspect}#{description ? " @description=#{description.inspect}" : ""}>"
92
+ end
93
+
88
94
  def visible?(_ctx); true; end
89
95
  def accessible?(_ctx); true; end
90
96
  def authorized?(_ctx); true; end
@@ -42,7 +42,7 @@ module GraphQL
42
42
  value.after_value ||= original_arguments[:after]
43
43
  value.last_value ||= original_arguments[:last]
44
44
  value.before_value ||= original_arguments[:before]
45
- value.arguments ||= original_arguments
45
+ value.arguments ||= original_arguments # rubocop:disable Development/ContextIsPassedCop -- unrelated .arguments method
46
46
  value.field ||= field
47
47
  if field.has_max_page_size? && !value.has_max_page_size_override?
48
48
  value.max_page_size = field.max_page_size