graphql 1.13.0 → 1.13.24

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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +3 -8
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install_generator.rb +10 -3
  8. data/lib/generators/graphql/interface_generator.rb +7 -7
  9. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  10. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  11. data/lib/generators/graphql/mutation_generator.rb +5 -30
  12. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  13. data/lib/generators/graphql/object_generator.rb +8 -37
  14. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  15. data/lib/generators/graphql/scalar_generator.rb +4 -2
  16. data/lib/generators/graphql/templates/enum.erb +5 -1
  17. data/lib/generators/graphql/templates/input.erb +9 -0
  18. data/lib/generators/graphql/templates/interface.erb +4 -2
  19. data/lib/generators/graphql/templates/mutation.erb +1 -1
  20. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  21. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  22. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  23. data/lib/generators/graphql/templates/object.erb +4 -2
  24. data/lib/generators/graphql/templates/scalar.erb +3 -1
  25. data/lib/generators/graphql/templates/union.erb +4 -2
  26. data/lib/generators/graphql/type_generator.rb +46 -9
  27. data/lib/generators/graphql/union_generator.rb +5 -5
  28. data/lib/graphql/analysis/ast/field_usage.rb +6 -2
  29. data/lib/graphql/analysis/ast/visitor.rb +2 -1
  30. data/lib/graphql/argument.rb +1 -1
  31. data/lib/graphql/base_type.rb +5 -3
  32. data/lib/graphql/boolean_type.rb +1 -1
  33. data/lib/graphql/dataloader/source.rb +2 -2
  34. data/lib/graphql/date_encoding_error.rb +16 -0
  35. data/lib/graphql/define/instance_definable.rb +15 -0
  36. data/lib/graphql/directive/deprecated_directive.rb +1 -1
  37. data/lib/graphql/directive/include_directive.rb +1 -1
  38. data/lib/graphql/directive/skip_directive.rb +1 -1
  39. data/lib/graphql/directive.rb +1 -1
  40. data/lib/graphql/enum_type.rb +2 -2
  41. data/lib/graphql/execution/interpreter/arguments_cache.rb +4 -2
  42. data/lib/graphql/execution/interpreter/runtime.rb +48 -28
  43. data/lib/graphql/execution/multiplex.rb +3 -0
  44. data/lib/graphql/field.rb +1 -1
  45. data/lib/graphql/float_type.rb +1 -1
  46. data/lib/graphql/id_type.rb +1 -1
  47. data/lib/graphql/input_object_type.rb +1 -1
  48. data/lib/graphql/int_type.rb +1 -1
  49. data/lib/graphql/interface_type.rb +1 -1
  50. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  51. data/lib/graphql/introspection/directive_type.rb +4 -2
  52. data/lib/graphql/introspection/field_type.rb +1 -1
  53. data/lib/graphql/introspection/schema_type.rb +7 -2
  54. data/lib/graphql/introspection/type_type.rb +14 -8
  55. data/lib/graphql/introspection.rb +4 -1
  56. data/lib/graphql/language/block_string.rb +2 -2
  57. data/lib/graphql/language/document_from_schema_definition.rb +8 -3
  58. data/lib/graphql/language/lexer.rb +50 -25
  59. data/lib/graphql/language/lexer.rl +2 -0
  60. data/lib/graphql/language/nodes.rb +15 -3
  61. data/lib/graphql/language/parser.rb +829 -816
  62. data/lib/graphql/language/parser.y +8 -2
  63. data/lib/graphql/language/printer.rb +4 -0
  64. data/lib/graphql/object_type.rb +2 -2
  65. data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
  66. data/lib/graphql/pagination/relation_connection.rb +59 -29
  67. data/lib/graphql/query/context.rb +10 -0
  68. data/lib/graphql/query/input_validation_result.rb +9 -0
  69. data/lib/graphql/query/validation_pipeline.rb +2 -3
  70. data/lib/graphql/query/variable_validation_error.rb +2 -2
  71. data/lib/graphql/query/variables.rb +30 -3
  72. data/lib/graphql/query.rb +0 -1
  73. data/lib/graphql/relay/connection_type.rb +15 -2
  74. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  75. data/lib/graphql/relay/mutation.rb +1 -1
  76. data/lib/graphql/relay/page_info.rb +1 -1
  77. data/lib/graphql/relay/range_add.rb +4 -0
  78. data/lib/graphql/rubocop/graphql/default_required_true.rb +4 -4
  79. data/lib/graphql/scalar_type.rb +1 -1
  80. data/lib/graphql/schema/argument.rb +29 -16
  81. data/lib/graphql/schema/build_from_definition.rb +9 -7
  82. data/lib/graphql/schema/directive.rb +25 -2
  83. data/lib/graphql/schema/enum.rb +4 -3
  84. data/lib/graphql/schema/enum_value.rb +3 -1
  85. data/lib/graphql/schema/field.rb +196 -92
  86. data/lib/graphql/schema/field_extension.rb +89 -2
  87. data/lib/graphql/schema/input_object.rb +27 -9
  88. data/lib/graphql/schema/interface.rb +8 -2
  89. data/lib/graphql/schema/introspection_system.rb +1 -1
  90. data/lib/graphql/schema/list.rb +21 -4
  91. data/lib/graphql/schema/loader.rb +3 -0
  92. data/lib/graphql/schema/member/accepts_definition.rb +7 -2
  93. data/lib/graphql/schema/member/base_dsl_methods.rb +1 -1
  94. data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
  95. data/lib/graphql/schema/member/has_arguments.rb +2 -2
  96. data/lib/graphql/schema/member/has_fields.rb +1 -1
  97. data/lib/graphql/schema/member/has_interfaces.rb +11 -1
  98. data/lib/graphql/schema/member/validates_input.rb +2 -2
  99. data/lib/graphql/schema/non_null.rb +9 -3
  100. data/lib/graphql/schema/object.rb +3 -1
  101. data/lib/graphql/schema/relay_classic_mutation.rb +8 -0
  102. data/lib/graphql/schema/resolver.rb +19 -13
  103. data/lib/graphql/schema/scalar.rb +15 -1
  104. data/lib/graphql/schema/traversal.rb +1 -1
  105. data/lib/graphql/schema/union.rb +2 -0
  106. data/lib/graphql/schema/validator/required_validator.rb +29 -15
  107. data/lib/graphql/schema/validator.rb +4 -7
  108. data/lib/graphql/schema/warden.rb +11 -2
  109. data/lib/graphql/schema.rb +34 -10
  110. data/lib/graphql/static_validation/all_rules.rb +1 -0
  111. data/lib/graphql/static_validation/base_visitor.rb +1 -1
  112. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  113. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  114. data/lib/graphql/static_validation/rules/fields_will_merge.rb +14 -7
  115. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  116. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  117. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -1
  118. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  119. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +6 -0
  120. data/lib/graphql/static_validation/validation_context.rb +4 -0
  121. data/lib/graphql/string_type.rb +1 -1
  122. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -0
  123. data/lib/graphql/subscriptions/serialize.rb +22 -2
  124. data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
  125. data/lib/graphql/tracing/data_dog_tracing.rb +24 -15
  126. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  127. data/lib/graphql/tracing/platform_tracing.rb +20 -10
  128. data/lib/graphql/types/iso_8601_date.rb +13 -5
  129. data/lib/graphql/types/iso_8601_date_time.rb +8 -1
  130. data/lib/graphql/types/relay/connection_behaviors.rb +28 -10
  131. data/lib/graphql/types/relay/default_relay.rb +5 -1
  132. data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
  133. data/lib/graphql/types/relay/node_field.rb +2 -3
  134. data/lib/graphql/types/relay/nodes_field.rb +19 -3
  135. data/lib/graphql/types/string.rb +1 -1
  136. data/lib/graphql/union_type.rb +1 -1
  137. data/lib/graphql/version.rb +1 -1
  138. data/lib/graphql.rb +14 -1
  139. metadata +56 -30
  140. /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
  141. /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
@@ -15,23 +15,110 @@ module GraphQL
15
15
  # @return [Object]
16
16
  attr_reader :options
17
17
 
18
+ # @return [Array<Symbol>, nil] `default_argument`s added, if any were added (otherwise, `nil`)
19
+ attr_reader :added_default_arguments
20
+
18
21
  # Called when the extension is mounted with `extension(name, options)`.
19
- # The instance is frozen to avoid improper use of state during execution.
22
+ # The instance will be frozen to avoid improper use of state during execution.
20
23
  # @param field [GraphQL::Schema::Field] The field where this extension was mounted
21
24
  # @param options [Object] The second argument to `extension`, or `{}` if nothing was passed.
22
25
  def initialize(field:, options:)
23
26
  @field = field
24
27
  @options = options || {}
28
+ @added_default_arguments = nil
25
29
  apply
26
- freeze
27
30
  end
28
31
 
32
+ class << self
33
+ # @return [Array(Array, Hash), nil] A list of default argument configs, or `nil` if there aren't any
34
+ def default_argument_configurations
35
+ args = superclass.respond_to?(:default_argument_configurations) ? superclass.default_argument_configurations : nil
36
+ if @own_default_argument_configurations
37
+ if args
38
+ args.concat(@own_default_argument_configurations)
39
+ else
40
+ args = @own_default_argument_configurations.dup
41
+ end
42
+ end
43
+ args
44
+ end
45
+
46
+ # @see Argument#initialize
47
+ # @see HasArguments#argument
48
+ def default_argument(*argument_args, **argument_kwargs)
49
+ configs = @own_default_argument_configurations ||= []
50
+ configs << [argument_args, argument_kwargs]
51
+ end
52
+
53
+ # If configured, these `extras` will be added to the field if they aren't already present,
54
+ # but removed by from `arguments` before the field's `resolve` is called.
55
+ # (The extras _will_ be present for other extensions, though.)
56
+ #
57
+ # @param new_extras [Array<Symbol>] If provided, assign extras used by this extension
58
+ # @return [Array<Symbol>] any extras assigned to this extension
59
+ def extras(new_extras = nil)
60
+ if new_extras
61
+ @own_extras = new_extras
62
+ end
63
+
64
+ inherited_extras = self.superclass.respond_to?(:extras) ? superclass.extras : nil
65
+ if @own_extras
66
+ if inherited_extras
67
+ inherited_extras + @own_extras
68
+ else
69
+ @own_extras
70
+ end
71
+ elsif inherited_extras
72
+ inherited_extras
73
+ else
74
+ NO_EXTRAS
75
+ end
76
+ end
77
+ end
78
+
79
+ NO_EXTRAS = [].freeze
80
+ private_constant :NO_EXTRAS
81
+
29
82
  # Called when this extension is attached to a field.
30
83
  # The field definition may be extended during this method.
31
84
  # @return [void]
32
85
  def apply
33
86
  end
34
87
 
88
+ # Called after the field's definition block has been executed.
89
+ # (Any arguments from the block are present on `field`)
90
+ # @return [void]
91
+ def after_define
92
+ end
93
+
94
+ # @api private
95
+ def after_define_apply
96
+ after_define
97
+ if (configs = self.class.default_argument_configurations)
98
+ existing_keywords = field.all_argument_definitions.map(&:keyword)
99
+ existing_keywords.uniq!
100
+ @added_default_arguments = []
101
+ configs.each do |config|
102
+ argument_args, argument_kwargs = config
103
+ arg_name = argument_args[0]
104
+ if !existing_keywords.include?(arg_name)
105
+ @added_default_arguments << arg_name
106
+ field.argument(*argument_args, **argument_kwargs)
107
+ end
108
+ end
109
+ end
110
+ if (extras = self.class.extras).any?
111
+ @added_extras = extras - field.extras
112
+ field.extras(@added_extras)
113
+ else
114
+ @added_extras = nil
115
+ end
116
+ freeze
117
+ end
118
+
119
+ # @api private
120
+ attr_reader :added_extras
121
+
35
122
  # Called before resolving {#field}. It should either:
36
123
  #
37
124
  # - `yield` values to continue execution; OR
@@ -79,6 +79,21 @@ module GraphQL
79
79
  end
80
80
  end
81
81
 
82
+ def self.authorized?(obj, value, ctx)
83
+ # Authorize each argument (but this doesn't apply if `prepare` is implemented):
84
+ if value.respond_to?(:key?)
85
+ arguments(ctx).each do |_name, input_obj_arg|
86
+ input_obj_arg = input_obj_arg.type_class
87
+ if value.key?(input_obj_arg.keyword) &&
88
+ !input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
89
+ return false
90
+ end
91
+ end
92
+ end
93
+ # It didn't early-return false:
94
+ true
95
+ end
96
+
82
97
  def unwrap_value(value)
83
98
  case value
84
99
  when Array
@@ -123,15 +138,12 @@ module GraphQL
123
138
  def argument(*args, **kwargs, &block)
124
139
  argument_defn = super(*args, **kwargs, &block)
125
140
  # Add a method access
126
- method_name = argument_defn.keyword
127
- class_eval <<-RUBY, __FILE__, __LINE__
128
- def #{method_name}
129
- self[#{method_name.inspect}]
130
- end
131
- RUBY
141
+ define_accessor_method(argument_defn.keyword)
132
142
  argument_defn
133
143
  end
134
144
 
145
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
146
+
135
147
  def to_graphql
136
148
  type_defn = GraphQL::InputObjectType.new
137
149
  type_defn.name = graphql_name
@@ -140,7 +152,7 @@ module GraphQL
140
152
  type_defn.mutation = mutation
141
153
  type_defn.ast_node = ast_node
142
154
  all_argument_definitions.each do |arg|
143
- type_defn.arguments[arg.graphql_definition.name] = arg.graphql_definition # rubocop:disable Development/ContextIsPassedCop -- legacy-related
155
+ type_defn.arguments[arg.graphql_definition(silence_deprecation_warning: true).name] = arg.graphql_definition(silence_deprecation_warning: true) # rubocop:disable Development/ContextIsPassedCop -- legacy-related
144
156
  end
145
157
  # Make a reference to a classic-style Arguments class
146
158
  self.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(type_defn)
@@ -156,9 +168,8 @@ module GraphQL
156
168
  # @api private
157
169
  INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
158
170
 
159
- def validate_non_null_input(input, ctx)
171
+ def validate_non_null_input(input, ctx, max_errors: nil)
160
172
  result = GraphQL::Query::InputValidationResult.new
161
-
162
173
  warden = ctx.warden
163
174
 
164
175
  if input.is_a?(Array)
@@ -237,6 +248,13 @@ module GraphQL
237
248
 
238
249
  result
239
250
  end
251
+
252
+ private
253
+
254
+ def define_accessor_method(method_name)
255
+ define_method(method_name) { self[method_name] }
256
+ alias_method(method_name, method_name)
257
+ end
240
258
  end
241
259
 
242
260
  private
@@ -81,7 +81,11 @@ module GraphQL
81
81
  end
82
82
  elsif child_class < GraphQL::Schema::Object
83
83
  # This is being included into an object type, make sure it's using `implements(...)`
84
- backtrace_line = caller(0, 10).find { |line| line.include?("schema/member/has_interfaces.rb") && line.include?("in `implements'")}
84
+ backtrace_line = caller_locations(0, 10).find do |location|
85
+ location.base_label == "implements" &&
86
+ location.path.end_with?("schema/member/has_interfaces.rb")
87
+ end
88
+
85
89
  if !backtrace_line
86
90
  raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
87
91
  end
@@ -100,6 +104,8 @@ module GraphQL
100
104
  end
101
105
  end
102
106
 
107
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
108
+
103
109
  def to_graphql
104
110
  type_defn = GraphQL::InterfaceType.new
105
111
  type_defn.name = graphql_name
@@ -108,7 +114,7 @@ module GraphQL
108
114
  type_defn.type_membership_class = self.type_membership_class
109
115
  type_defn.ast_node = ast_node
110
116
  fields.each do |field_name, field_inst| # rubocop:disable Development/ContextIsPassedCop -- legacy-related
111
- field_defn = field_inst.graphql_definition
117
+ field_defn = field_inst.graphql_definition(silence_deprecation_warning: true)
112
118
  type_defn.fields[field_defn.name] = field_defn # rubocop:disable Development/ContextIsPassedCop -- legacy-related
113
119
  end
114
120
  type_defn.metadata[:type_class] = self
@@ -107,7 +107,7 @@ module GraphQL
107
107
  dup_type_class(const)
108
108
  else
109
109
  # Use `.to_graphql` to get a freshly-made version, not shared between schemas
110
- const.to_graphql
110
+ const.deprecated_to_graphql
111
111
  end
112
112
  rescue NameError
113
113
  # Dup the built-in so that the cached fields aren't shared
@@ -8,8 +8,10 @@ module GraphQL
8
8
  class List < GraphQL::Schema::Wrapper
9
9
  include Schema::Member::ValidatesInput
10
10
 
11
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
12
+
11
13
  def to_graphql
12
- @of_type.graphql_definition.to_list_type
14
+ @of_type.graphql_definition(silence_deprecation_warning: true).to_list_type
13
15
  end
14
16
 
15
17
  # @return [GraphQL::TypeKinds::LIST]
@@ -49,15 +51,24 @@ module GraphQL
49
51
  end
50
52
  end
51
53
 
52
- def validate_non_null_input(value, ctx)
54
+ def validate_non_null_input(value, ctx, max_errors: nil)
53
55
  result = GraphQL::Query::InputValidationResult.new
54
56
  ensure_array(value).each_with_index do |item, index|
55
57
  item_result = of_type.validate_input(item, ctx)
56
- if !item_result.valid?
58
+ unless item_result.valid?
59
+ if max_errors
60
+ if max_errors == 0
61
+ add_max_errros_reached_message(result)
62
+ break
63
+ end
64
+
65
+ max_errors -= 1
66
+ end
67
+
57
68
  result.merge_result!(index, item_result)
58
69
  end
59
70
  end
60
- result
71
+ result.valid? ? nil : result
61
72
  end
62
73
 
63
74
  private
@@ -70,6 +81,12 @@ module GraphQL
70
81
  [value]
71
82
  end
72
83
  end
84
+
85
+ def add_max_errros_reached_message(result)
86
+ message = "Too many errors processing list variable, max validation error limit reached. Execution aborted"
87
+ item_result = GraphQL::Query::InputValidationResult.from_problem(message)
88
+ result.merge_result!(nil, item_result)
89
+ end
73
90
  end
74
91
  end
75
92
  end
@@ -34,6 +34,7 @@ module GraphQL
34
34
  Class.new(GraphQL::Schema) do
35
35
  orphan_types(types.values)
36
36
  directives(directives)
37
+ description(schema["description"])
37
38
 
38
39
  def self.resolve_type(*)
39
40
  raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
@@ -141,6 +142,7 @@ module GraphQL
141
142
  Class.new(GraphQL::Schema::Scalar) do
142
143
  graphql_name(type["name"])
143
144
  description(type["description"])
145
+ specified_by_url(type["specifiedByUrl"])
144
146
  end
145
147
  end
146
148
  when "UNION"
@@ -160,6 +162,7 @@ module GraphQL
160
162
  graphql_name(directive["name"])
161
163
  description(directive["description"])
162
164
  locations(*directive["locations"].map(&:to_sym))
165
+ repeatable(directive["isRepeatable"])
163
166
  loader.build_arguments(self, directive["args"], type_resolver)
164
167
  end
165
168
  end
@@ -123,8 +123,13 @@ module GraphQL
123
123
  end
124
124
 
125
125
  module ToGraphQLExtension
126
- def to_graphql
127
- defn = super
126
+ def to_graphql(*args, **kwargs)
127
+
128
+ defn = if args.empty? && kwargs.empty?
129
+ super()
130
+ else
131
+ super
132
+ end
128
133
  accepts_definition_methods.each do |method_name|
129
134
  value = public_send(method_name)
130
135
  if !value.nil?
@@ -108,7 +108,7 @@ module GraphQL
108
108
  @default_graphql_name ||= begin
109
109
  raise GraphQL::RequiredImplementationMissingError, 'Anonymous class should declare a `graphql_name`' if name.nil?
110
110
 
111
- name.split("::").last.sub(/Type\Z/, "")
111
+ -name.split("::").last.sub(/Type\Z/, "")
112
112
  end
113
113
  end
114
114
 
@@ -11,8 +11,24 @@ module GraphQL
11
11
  # A cached result of {.to_graphql}.
12
12
  # It's cached here so that user-overridden {.to_graphql} implementations
13
13
  # are also cached
14
- def graphql_definition
15
- @graphql_definition ||= to_graphql
14
+ def graphql_definition(silence_deprecation_warning: false)
15
+ @graphql_definition ||= begin
16
+ unless silence_deprecation_warning
17
+ message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Remove `.graphql_definition` to use a class-based definition instead."
18
+ caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
19
+ GraphQL::Deprecation.warn(message + caller_message)
20
+ end
21
+ deprecated_to_graphql
22
+ end
23
+ end
24
+
25
+ def deprecated_to_graphql
26
+ case method(:to_graphql).arity
27
+ when 0
28
+ to_graphql
29
+ else
30
+ to_graphql(silence_deprecation_warning: true)
31
+ end
16
32
  end
17
33
 
18
34
  # This is for a common interface with .define-based types
@@ -25,6 +41,17 @@ module GraphQL
25
41
  super
26
42
  @graphql_definition = nil
27
43
  end
44
+
45
+ module DeprecatedToGraphQL
46
+ def to_graphql(silence_deprecation_warning: false)
47
+ unless silence_deprecation_warning
48
+ message = "Legacy `.to_graphql` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Remove `.to_graphql` to use a class-based definition instead."
49
+ caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
50
+ GraphQL::Deprecation.warn(message + caller_message)
51
+ end
52
+ super()
53
+ end
54
+ end
28
55
  end
29
56
  end
30
57
  end
@@ -167,7 +167,7 @@ module GraphQL
167
167
  # @return [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
168
168
  def coerce_arguments(parent_object, values, context, &block)
169
169
  # Cache this hash to avoid re-merging it
170
- arg_defns = self.arguments(context)
170
+ arg_defns = context.warden.arguments(self)
171
171
  total_args_count = arg_defns.size
172
172
 
173
173
  finished_args = nil
@@ -181,7 +181,7 @@ module GraphQL
181
181
  argument_values = {}
182
182
  resolved_args_count = 0
183
183
  raised_error = false
184
- arg_defns.each do |arg_name, arg_defn|
184
+ arg_defns.each do |arg_defn|
185
185
  context.dataloader.append_job do
186
186
  begin
187
187
  arg_defn.coerce_into_values(parent_object, values, context, argument_values)
@@ -134,7 +134,7 @@ module GraphQL
134
134
  if type.respond_to?(:kind) && type.kind.interface?
135
135
  implements_this_interface = false
136
136
  implementation_is_visible = false
137
- interface_type_memberships.each do |tm|
137
+ warden.interface_type_memberships(self, context).each do |tm|
138
138
  if tm.abstract_type == type
139
139
  implements_this_interface ||= true
140
140
  if warden.visible_type_membership?(tm, context)
@@ -57,7 +57,17 @@ module GraphQL
57
57
  end
58
58
 
59
59
  def interface_type_memberships
60
- own_interface_type_memberships + ((self.is_a?(Class) && superclass.respond_to?(:interface_type_memberships)) ? superclass.interface_type_memberships : [])
60
+ own_tms = own_interface_type_memberships
61
+ if (self.is_a?(Class) && superclass.respond_to?(:interface_type_memberships))
62
+ inherited_tms = superclass.interface_type_memberships
63
+ if inherited_tms.size > 0
64
+ own_tms + inherited_tms
65
+ else
66
+ own_tms
67
+ end
68
+ else
69
+ own_tms
70
+ end
61
71
  end
62
72
 
63
73
  # param context [Query::Context] If omitted, skip filtering.
@@ -8,11 +8,11 @@ module GraphQL
8
8
  validate_input(val, ctx).valid?
9
9
  end
10
10
 
11
- def validate_input(val, ctx)
11
+ def validate_input(val, ctx, max_errors: nil)
12
12
  if val.nil?
13
13
  GraphQL::Query::InputValidationResult.new
14
14
  else
15
- validate_non_null_input(val, ctx)
15
+ validate_non_null_input(val, ctx, max_errors: max_errors) || Query::InputValidationResult::VALID
16
16
  end
17
17
  end
18
18
 
@@ -8,8 +8,10 @@ module GraphQL
8
8
  class NonNull < GraphQL::Schema::Wrapper
9
9
  include Schema::Member::ValidatesInput
10
10
 
11
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
12
+
11
13
  def to_graphql
12
- @of_type.graphql_definition.to_non_null_type
14
+ @of_type.graphql_definition(silence_deprecation_warning: true).to_non_null_type
13
15
  end
14
16
 
15
17
  # @return [GraphQL::TypeKinds::NON_NULL]
@@ -35,13 +37,13 @@ module GraphQL
35
37
  "#<#{self.class.name} @of_type=#{@of_type.inspect}>"
36
38
  end
37
39
 
38
- def validate_input(value, ctx)
40
+ def validate_input(value, ctx, max_errors: nil)
39
41
  if value.nil?
40
42
  result = GraphQL::Query::InputValidationResult.new
41
43
  result.add_problem("Expected value to not be null")
42
44
  result
43
45
  else
44
- of_type.validate_input(value, ctx)
46
+ of_type.validate_input(value, ctx, max_errors: max_errors)
45
47
  end
46
48
  end
47
49
 
@@ -51,6 +53,10 @@ module GraphQL
51
53
  end
52
54
 
53
55
  def coerce_input(value, ctx)
56
+ # `.validate_input` above is used for variables, but this method is used for arguments
57
+ if value.nil?
58
+ raise GraphQL::ExecutionError, "`null` is not a valid input for `#{to_type_signature}`, please provide a value for this argument."
59
+ end
54
60
  of_type.coerce_input(value, ctx)
55
61
  end
56
62
 
@@ -122,6 +122,8 @@ module GraphQL
122
122
  all_fields
123
123
  end
124
124
 
125
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
126
+
125
127
  # @return [GraphQL::ObjectType]
126
128
  def to_graphql
127
129
  obj_type = GraphQL::ObjectType.new
@@ -132,7 +134,7 @@ module GraphQL
132
134
  obj_type.mutation = mutation
133
135
  obj_type.ast_node = ast_node
134
136
  fields.each do |field_name, field_inst| # rubocop:disable Development/ContextIsPassedCop -- legacy-related
135
- field_defn = field_inst.to_graphql
137
+ field_defn = field_inst.to_graphql(silence_deprecation_warning: true)
136
138
  obj_type.fields[field_defn.name] = field_defn # rubocop:disable Development/ContextIsPassedCop -- legacy-related
137
139
  end
138
140
 
@@ -155,6 +155,14 @@ module GraphQL
155
155
  end
156
156
  end
157
157
  end
158
+
159
+ private
160
+
161
+ def authorize_arguments(args, values)
162
+ # remove the `input` wrapper to match values
163
+ input_args = args["input"].type.unwrap.arguments(context)
164
+ super(input_args, values)
165
+ end
158
166
  end
159
167
  end
160
168
  end
@@ -145,19 +145,9 @@ module GraphQL
145
145
  # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
146
146
  # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
147
147
  def authorized?(**inputs)
148
- self.class.arguments(context).each_value do |argument|
149
- arg_keyword = argument.keyword
150
- if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
151
- arg_auth, err = argument.authorized?(self, arg_value, context)
152
- if !arg_auth
153
- return arg_auth, err
154
- else
155
- true
156
- end
157
- else
158
- true
159
- end
160
- end
148
+ arg_owner = @field # || self.class
149
+ args = arg_owner.arguments(context)
150
+ authorize_arguments(args, inputs)
161
151
  end
162
152
 
163
153
  # Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
@@ -172,6 +162,22 @@ module GraphQL
172
162
 
173
163
  private
174
164
 
165
+ def authorize_arguments(args, inputs)
166
+ args.each_value do |argument|
167
+ arg_keyword = argument.keyword
168
+ if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
169
+ arg_auth, err = argument.authorized?(self, arg_value, context)
170
+ if !arg_auth
171
+ return arg_auth, err
172
+ else
173
+ true
174
+ end
175
+ else
176
+ true
177
+ end
178
+ end
179
+ end
180
+
175
181
  def load_arguments(args)
176
182
  prepared_args = {}
177
183
  prepare_lazies = []
@@ -14,6 +14,8 @@ module GraphQL
14
14
  val
15
15
  end
16
16
 
17
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
18
+
17
19
  def to_graphql
18
20
  type_defn = GraphQL::ScalarType.new
19
21
  type_defn.name = graphql_name
@@ -30,6 +32,18 @@ module GraphQL
30
32
  GraphQL::TypeKinds::SCALAR
31
33
  end
32
34
 
35
+ def specified_by_url(new_url = nil)
36
+ if new_url
37
+ @specified_by_url = new_url
38
+ elsif defined?(@specified_by_url)
39
+ @specified_by_url
40
+ elsif superclass.respond_to?(:specified_by_url)
41
+ superclass.specified_by_url
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
33
47
  def default_scalar(is_default = nil)
34
48
  if !is_default.nil?
35
49
  @default_scalar = is_default
@@ -41,7 +55,7 @@ module GraphQL
41
55
  @default_scalar ||= false
42
56
  end
43
57
 
44
- def validate_non_null_input(value, ctx)
58
+ def validate_non_null_input(value, ctx, max_errors: nil)
45
59
  result = Query::InputValidationResult.new
46
60
  coerced_result = begin
47
61
  ctx.query.with_error_handling do
@@ -173,7 +173,7 @@ Some late-bound types couldn't be resolved:
173
173
  end
174
174
  when Class
175
175
  if member.respond_to?(:graphql_definition)
176
- graphql_member = member.graphql_definition
176
+ graphql_member = member.graphql_definition(silence_deprecation_warning: true)
177
177
  visit(schema, graphql_member, context_description)
178
178
  else
179
179
  raise GraphQL::Schema::InvalidTypeError.new("Unexpected traversal member: #{member} (#{member.class.name})")
@@ -33,6 +33,8 @@ module GraphQL
33
33
  type_memberships.map(&:object_type)
34
34
  end
35
35
 
36
+ prepend GraphQL::Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
37
+
36
38
  def to_graphql
37
39
  type_defn = GraphQL::UnionType.new
38
40
  type_defn.name = graphql_name