graphql 2.3.8 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +46 -0
  3. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  4. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  5. data/lib/generators/graphql/type_generator.rb +1 -1
  6. data/lib/graphql/analysis.rb +1 -1
  7. data/lib/graphql/current.rb +52 -0
  8. data/lib/graphql/dataloader/async_dataloader.rb +3 -2
  9. data/lib/graphql/dataloader/source.rb +6 -3
  10. data/lib/graphql/dataloader.rb +35 -11
  11. data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
  12. data/lib/graphql/execution/interpreter/resolve.rb +10 -6
  13. data/lib/graphql/execution/interpreter/runtime.rb +23 -19
  14. data/lib/graphql/execution/interpreter.rb +2 -0
  15. data/lib/graphql/introspection/entry_points.rb +2 -2
  16. data/lib/graphql/introspection/schema_type.rb +4 -19
  17. data/lib/graphql/invalid_null_error.rb +1 -1
  18. data/lib/graphql/language/comment.rb +18 -0
  19. data/lib/graphql/language/document_from_schema_definition.rb +38 -4
  20. data/lib/graphql/language/lexer.rb +15 -12
  21. data/lib/graphql/language/nodes.rb +24 -16
  22. data/lib/graphql/language/parser.rb +14 -1
  23. data/lib/graphql/language/printer.rb +23 -7
  24. data/lib/graphql/language.rb +6 -5
  25. data/lib/graphql/query/context.rb +4 -2
  26. data/lib/graphql/query/null_context.rb +1 -5
  27. data/lib/graphql/query.rb +49 -20
  28. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
  29. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
  30. data/lib/graphql/rubocop.rb +2 -0
  31. data/lib/graphql/schema/addition.rb +1 -0
  32. data/lib/graphql/schema/always_visible.rb +6 -3
  33. data/lib/graphql/schema/argument.rb +14 -1
  34. data/lib/graphql/schema/build_from_definition.rb +9 -1
  35. data/lib/graphql/schema/directive/flagged.rb +1 -1
  36. data/lib/graphql/schema/enum.rb +49 -15
  37. data/lib/graphql/schema/enum_value.rb +9 -1
  38. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  39. data/lib/graphql/schema/field.rb +91 -36
  40. data/lib/graphql/schema/input_object.rb +20 -7
  41. data/lib/graphql/schema/interface.rb +21 -4
  42. data/lib/graphql/schema/introspection_system.rb +3 -2
  43. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  44. data/lib/graphql/schema/member/has_arguments.rb +9 -5
  45. data/lib/graphql/schema/member/has_fields.rb +5 -5
  46. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  47. data/lib/graphql/schema/printer.rb +1 -0
  48. data/lib/graphql/schema/resolver.rb +3 -4
  49. data/lib/graphql/schema/validator/all_validator.rb +2 -0
  50. data/lib/graphql/schema/validator/required_validator.rb +28 -4
  51. data/lib/graphql/schema/visibility/migration.rb +186 -0
  52. data/lib/graphql/schema/visibility/profile.rb +523 -0
  53. data/lib/graphql/schema/visibility.rb +75 -0
  54. data/lib/graphql/schema/warden.rb +80 -21
  55. data/lib/graphql/schema.rb +254 -85
  56. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
  57. data/lib/graphql/static_validation/rules/directives_are_defined.rb +2 -1
  58. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  59. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +2 -1
  60. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -0
  61. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +11 -1
  62. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  63. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +10 -1
  64. data/lib/graphql/static_validation/validation_context.rb +15 -0
  65. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
  66. data/lib/graphql/subscriptions.rb +3 -1
  67. data/lib/graphql/testing/helpers.rb +7 -3
  68. data/lib/graphql/tracing/notifications_trace.rb +2 -2
  69. data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
  70. data/lib/graphql/version.rb +1 -1
  71. data/lib/graphql.rb +3 -0
  72. metadata +28 -7
  73. data/lib/graphql/schema/subset.rb +0 -397
@@ -23,8 +23,18 @@ module GraphQL
23
23
  type_name = fragment_node.type.name
24
24
  type = @types.type(type_name)
25
25
  if type.nil?
26
+ @all_possible_fragment_type_names ||= begin
27
+ names = []
28
+ context.types.all_types.each do |type|
29
+ if type.kind.fields?
30
+ names << type.graphql_name
31
+ end
32
+ end
33
+ names
34
+ end
35
+
26
36
  add_error(GraphQL::StaticValidation::FragmentTypesExistError.new(
27
- "No such type #{type_name}, so it can't be a fragment condition",
37
+ "No such type #{type_name}, so it can't be a fragment condition#{context.did_you_mean_suggestion(type_name, @all_possible_fragment_type_names)}",
28
38
  nodes: fragment_node,
29
39
  type: type_name
30
40
  ))
@@ -5,36 +5,27 @@ module GraphQL
5
5
  def on_variable_definition(node, parent)
6
6
  if !node.default_value.nil?
7
7
  value = node.default_value
8
- if node.type.is_a?(GraphQL::Language::Nodes::NonNullType)
9
- add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
10
- "Non-null variable $#{node.name} can't have a default value",
11
- nodes: node,
12
- name: node.name,
13
- error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_ON_NON_NULL]
14
- ))
8
+ type = context.schema.type_from_ast(node.type, context: context)
9
+ if type.nil?
10
+ # This is handled by another validator
15
11
  else
16
- type = context.schema.type_from_ast(node.type, context: context)
17
- if type.nil?
18
- # This is handled by another validator
19
- else
20
- validation_result = context.validate_literal(value, type)
12
+ validation_result = context.validate_literal(value, type)
21
13
 
22
- if !validation_result.valid?
23
- problems = validation_result.problems
24
- first_problem = problems && problems.first
25
- if first_problem
26
- error_message = first_problem["explanation"]
27
- end
28
-
29
- error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
30
- add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
31
- error_message,
32
- nodes: node,
33
- name: node.name,
34
- type: type.to_type_signature,
35
- error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
36
- ))
14
+ if !validation_result.valid?
15
+ problems = validation_result.problems
16
+ first_problem = problems && problems.first
17
+ if first_problem
18
+ error_message = first_problem["explanation"]
37
19
  end
20
+
21
+ error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
22
+ add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
23
+ error_message,
24
+ nodes: node,
25
+ name: node.name,
26
+ type: type.to_type_signature,
27
+ error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
28
+ ))
38
29
  end
39
30
  end
40
31
  end
@@ -7,8 +7,17 @@ module GraphQL
7
7
  type = context.query.types.type(type_name)
8
8
 
9
9
  if type.nil?
10
+ @all_possible_input_type_names ||= begin
11
+ names = []
12
+ context.types.all_types.each { |(t)|
13
+ if t.kind.input?
14
+ names << t.graphql_name
15
+ end
16
+ }
17
+ names
18
+ end
10
19
  add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
11
- "#{type_name} isn't a defined input type (on $#{node.name})",
20
+ "#{type_name} isn't a defined input type (on $#{node.name})#{context.did_you_mean_suggestion(type_name, @all_possible_input_type_names)}",
12
21
  nodes: node,
13
22
  name: node.name,
14
23
  type: type_name
@@ -48,6 +48,21 @@ module GraphQL
48
48
  def schema_directives
49
49
  @schema_directives ||= schema.directives
50
50
  end
51
+
52
+ def did_you_mean_suggestion(name, options)
53
+ if did_you_mean = schema.did_you_mean
54
+ suggestions = did_you_mean::SpellChecker.new(dictionary: options).correct(name)
55
+ case suggestions.size
56
+ when 0
57
+ ""
58
+ when 1
59
+ " (Did you mean `#{suggestions.first}`?)"
60
+ else
61
+ last_sugg = suggestions.pop
62
+ " (Did you mean #{suggestions.map {|s| "`#{s}`"}.join(", ")} or `#{last_sugg}`?)"
63
+ end
64
+ end
65
+ end
51
66
  end
52
67
  end
53
68
  end
@@ -166,7 +166,8 @@ module GraphQL
166
166
  #
167
167
  def setup_stream(channel, initial_event)
168
168
  topic = initial_event.topic
169
- channel.stream_from(stream_event_name(initial_event), coder: @action_cable_coder) do |message|
169
+ event_stream = stream_event_name(initial_event)
170
+ channel.stream_from(event_stream, coder: @action_cable_coder) do |message|
170
171
  events_by_fingerprint = @events[topic]
171
172
  object = nil
172
173
  events_by_fingerprint.each do |_fingerprint, events|
@@ -250,6 +250,8 @@ module GraphQL
250
250
  def normalize_arguments(event_name, arg_owner, args, context)
251
251
  case arg_owner
252
252
  when GraphQL::Schema::Field, Class
253
+ return args if args.nil?
254
+
253
255
  if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
254
256
  # it's a type, but not an input object
255
257
  return args
@@ -302,7 +304,7 @@ module GraphQL
302
304
 
303
305
  normalized_args
304
306
  when GraphQL::Schema::List
305
- args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
307
+ args&.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
306
308
  when GraphQL::Schema::NonNull
307
309
  normalize_arguments(event_name, arg_owner.of_type, args, context)
308
310
  else
@@ -55,6 +55,7 @@ module GraphQL
55
55
  visible_field = dummy_query.types.field(object_type, field_name) # rubocop:disable Development/ContextIsPassedCop
56
56
  if visible_field
57
57
  dummy_query.context.dataloader.run_isolated {
58
+ query_context[:current_field] = visible_field
58
59
  field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
59
60
  field_args = schema.sync_lazy(field_args)
60
61
  if visible_field.extras.any?
@@ -90,10 +91,13 @@ module GraphQL
90
91
  end
91
92
  end
92
93
  graphql_result
93
- elsif schema.has_defined_type?(type_name)
94
- raise TypeNotVisibleError.new(type_name: type_name)
95
94
  else
96
- raise TypeNotDefinedError.new(type_name: type_name)
95
+ unfiltered_type = Schema::Visibility::Profile.pass_thru(schema: schema, context: context).type(type_name)
96
+ if unfiltered_type
97
+ raise TypeNotVisibleError.new(type_name: type_name)
98
+ else
99
+ raise TypeNotDefinedError.new(type_name: type_name)
100
+ end
97
101
  end
98
102
  end
99
103
 
@@ -33,8 +33,8 @@ module GraphQL
33
33
  "resolve_type_lazy" => "resolve_type.graphql",
34
34
  }.each do |trace_method, platform_key|
35
35
  module_eval <<-RUBY, __FILE__, __LINE__
36
- def #{trace_method}(**metadata, &blk)
37
- @notifications_engine.instrument("#{platform_key}", metadata, &blk)
36
+ def #{trace_method}(**metadata, &block)
37
+ @notifications_engine.instrument("#{platform_key}", metadata) { super(**metadata, &block) }
38
38
  end
39
39
  RUBY
40
40
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class UnauthorizedEnumValueError < GraphQL::UnauthorizedError
4
+ # @return [GraphQL::Schema::EnumValue] The value whose `#authorized?` check returned false
5
+ attr_accessor :enum_value
6
+
7
+ def initialize(type:, context:, enum_value:)
8
+ @enum_value = enum_value
9
+ message ||= "#{enum_value.path} failed authorization"
10
+ super(message, object: enum_value.value, type: type, context: context)
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.3.8"
3
+ VERSION = "2.4.0"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -4,6 +4,7 @@ require "json"
4
4
  require "set"
5
5
  require "singleton"
6
6
  require "forwardable"
7
+ require "fiber/storage"
7
8
 
8
9
  module GraphQL
9
10
  class Error < StandardError
@@ -118,6 +119,8 @@ require "graphql/parse_error"
118
119
  require "graphql/backtrace"
119
120
 
120
121
  require "graphql/unauthorized_error"
122
+ require "graphql/unauthorized_enum_value_error"
121
123
  require "graphql/unauthorized_field_error"
122
124
  require "graphql/load_application_object_failed_error"
123
125
  require "graphql/testing"
126
+ require "graphql/current"
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: 2.3.8
4
+ version: 2.4.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: 2024-07-12 00:00:00.000000000 Z
11
+ date: 2024-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fiber-storage
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: benchmark-ips
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -154,16 +168,16 @@ dependencies:
154
168
  name: rubocop
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
- - - '='
171
+ - - ">="
158
172
  - !ruby/object:Gem::Version
159
- version: '1.12'
173
+ version: '0'
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
- - - '='
178
+ - - ">="
165
179
  - !ruby/object:Gem::Version
166
- version: '1.12'
180
+ version: '0'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: jekyll
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -321,6 +335,7 @@ files:
321
335
  - lib/graphql/backtrace/traced_error.rb
322
336
  - lib/graphql/backtrace/tracer.rb
323
337
  - lib/graphql/coercion_error.rb
338
+ - lib/graphql/current.rb
324
339
  - lib/graphql/dataloader.rb
325
340
  - lib/graphql/dataloader/async_dataloader.rb
326
341
  - lib/graphql/dataloader/null_dataloader.rb
@@ -367,6 +382,7 @@ files:
367
382
  - lib/graphql/language.rb
368
383
  - lib/graphql/language/block_string.rb
369
384
  - lib/graphql/language/cache.rb
385
+ - lib/graphql/language/comment.rb
370
386
  - lib/graphql/language/definition_slice.rb
371
387
  - lib/graphql/language/document_from_schema_definition.rb
372
388
  - lib/graphql/language/generation.rb
@@ -407,6 +423,8 @@ files:
407
423
  - lib/graphql/rubocop/graphql/base_cop.rb
408
424
  - lib/graphql/rubocop/graphql/default_null_true.rb
409
425
  - lib/graphql/rubocop/graphql/default_required_true.rb
426
+ - lib/graphql/rubocop/graphql/field_type_in_block.rb
427
+ - lib/graphql/rubocop/graphql/root_types_in_block.rb
410
428
  - lib/graphql/runtime_type_error.rb
411
429
  - lib/graphql/schema.rb
412
430
  - lib/graphql/schema/addition.rb
@@ -468,7 +486,6 @@ files:
468
486
  - lib/graphql/schema/resolver/has_payload_type.rb
469
487
  - lib/graphql/schema/scalar.rb
470
488
  - lib/graphql/schema/subscription.rb
471
- - lib/graphql/schema/subset.rb
472
489
  - lib/graphql/schema/timeout.rb
473
490
  - lib/graphql/schema/type_expression.rb
474
491
  - lib/graphql/schema/type_membership.rb
@@ -484,6 +501,9 @@ files:
484
501
  - lib/graphql/schema/validator/length_validator.rb
485
502
  - lib/graphql/schema/validator/numericality_validator.rb
486
503
  - lib/graphql/schema/validator/required_validator.rb
504
+ - lib/graphql/schema/visibility.rb
505
+ - lib/graphql/schema/visibility/migration.rb
506
+ - lib/graphql/schema/visibility/profile.rb
487
507
  - lib/graphql/schema/warden.rb
488
508
  - lib/graphql/schema/wrapper.rb
489
509
  - lib/graphql/static_validation.rb
@@ -614,6 +634,7 @@ files:
614
634
  - lib/graphql/types/relay/page_info.rb
615
635
  - lib/graphql/types/relay/page_info_behaviors.rb
616
636
  - lib/graphql/types/string.rb
637
+ - lib/graphql/unauthorized_enum_value_error.rb
617
638
  - lib/graphql/unauthorized_error.rb
618
639
  - lib/graphql/unauthorized_field_error.rb
619
640
  - lib/graphql/unresolved_type_error.rb