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
@@ -8,13 +8,28 @@ require_relative 'core'
8
8
 
9
9
  module Graphql
10
10
  module Generators
11
- class TypeGeneratorBase < Rails::Generators::Base
11
+ class TypeGeneratorBase < Rails::Generators::NamedBase
12
12
  include Core
13
13
 
14
- argument :type_name,
15
- type: :string,
16
- banner: "TypeName",
17
- desc: "Name of this object type (expressed as Ruby or GraphQL)"
14
+ class_option 'namespaced_types',
15
+ type: :boolean,
16
+ required: false,
17
+ default: false,
18
+ banner: "Namespaced",
19
+ desc: "If the generated types will be namespaced"
20
+
21
+ argument :custom_fields,
22
+ type: :array,
23
+ default: [],
24
+ banner: "name:type name:type ...",
25
+ desc: "Fields for this object (type may be expressed as Ruby or GraphQL)"
26
+
27
+
28
+ attr_accessor :graphql_type
29
+
30
+ def create_type_file
31
+ template "#{graphql_type}.erb", "#{options[:directory]}/types#{subdirectory}/#{type_file_name}.rb"
32
+ end
18
33
 
19
34
  # Take a type expression in any combination of GraphQL or Ruby styles
20
35
  # and return it in a specified output style
@@ -60,12 +75,12 @@ module Graphql
60
75
 
61
76
  # @return [String] The user-provided type name, normalized to Ruby code
62
77
  def type_ruby_name
63
- @type_ruby_name ||= self.class.normalize_type_expression(type_name, mode: :ruby)[0]
78
+ @type_ruby_name ||= self.class.normalize_type_expression(name, mode: :ruby)[0]
64
79
  end
65
80
 
66
81
  # @return [String] The user-provided type name, as a GraphQL name
67
82
  def type_graphql_name
68
- @type_graphql_name ||= self.class.normalize_type_expression(type_name, mode: :graphql)[0]
83
+ @type_graphql_name ||= self.class.normalize_type_expression(name, mode: :graphql)[0]
69
84
  end
70
85
 
71
86
  # @return [String] The user-provided type name, as a file name (without extension)
@@ -82,6 +97,24 @@ module Graphql
82
97
  }
83
98
  end
84
99
 
100
+ def ruby_class_name
101
+ class_prefix =
102
+ if options[:namespaced_types]
103
+ "#{graphql_type.pluralize.camelize}::"
104
+ else
105
+ ""
106
+ end
107
+ @ruby_class_name || class_prefix + type_ruby_name.sub(/^Types::/, "")
108
+ end
109
+
110
+ def subdirectory
111
+ if options[:namespaced_types]
112
+ "/#{graphql_type.pluralize}"
113
+ else
114
+ ""
115
+ end
116
+ end
117
+
85
118
  class NormalizedField
86
119
  def initialize(name, type_expr, null)
87
120
  @name = name
@@ -89,8 +122,12 @@ module Graphql
89
122
  @null = null
90
123
  end
91
124
 
92
- def to_ruby
93
- "field :#{@name}, #{@type_expr}, null: #{@null}"
125
+ def to_object_field
126
+ "field :#{@name}, #{@type_expr}#{@null ? '' : ', null: false'}"
127
+ end
128
+
129
+ def to_input_argument
130
+ "argument :#{@name}, #{@type_expr}, required: false"
94
131
  end
95
132
  end
96
133
  end
@@ -19,14 +19,14 @@ module Graphql
19
19
  banner: "type type ...",
20
20
  desc: "Possible types for this union (expressed as Ruby or GraphQL)"
21
21
 
22
- def create_type_file
23
- template "union.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
24
- end
25
-
26
22
  private
27
23
 
24
+ def graphql_type
25
+ "union"
26
+ end
27
+
28
28
  def normalized_possible_types
29
- possible_types.map { |t| self.class.normalize_type_expression(t, mode: :ruby)[0] }
29
+ custom_fields.map { |t| self.class.normalize_type_expression(t, mode: :ruby)[0] }
30
30
  end
31
31
  end
32
32
  end
@@ -15,8 +15,12 @@ module GraphQL
15
15
  field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
16
16
  @used_fields << field
17
17
  @used_deprecated_fields << field if field_defn.deprecation_reason
18
-
19
- extract_deprecated_arguments(visitor.query.arguments_for(node, visitor.field_definition).argument_values)
18
+ arguments = visitor.query.arguments_for(node, visitor.field_definition)
19
+ # If there was an error when preparing this argument object,
20
+ # then this might be an error or something:
21
+ if arguments.respond_to?(:argument_values)
22
+ extract_deprecated_arguments(arguments.argument_values)
23
+ end
20
24
  end
21
25
 
22
26
  def result
@@ -100,7 +100,8 @@ module GraphQL
100
100
  def on_field(node, parent)
101
101
  @response_path.push(node.alias || node.name)
102
102
  parent_type = @object_types.last
103
- field_definition = @schema.get_field(parent_type, node.name, @query.context)
103
+ # This could be nil if the previous field wasn't found:
104
+ field_definition = parent_type && @schema.get_field(parent_type, node.name, @query.context)
104
105
  @field_definitions.push(field_definition)
105
106
  if !field_definition.nil?
106
107
  next_object_type = field_definition.type.unwrap
@@ -3,7 +3,7 @@ module GraphQL
3
3
  # @api deprecated
4
4
  class Argument
5
5
  include GraphQL::Define::InstanceDefinable
6
- accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access, :deprecation_reason
6
+ deprecated_accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access, :deprecation_reason
7
7
  attr_reader :default_value
8
8
  attr_accessor :description, :name, :as, :deprecation_reason
9
9
  attr_accessor :ast_node
@@ -8,7 +8,7 @@ module GraphQL
8
8
  include GraphQL::Define::InstanceDefinable
9
9
  include GraphQL::Relay::TypeExtensions
10
10
 
11
- accepts_definitions :name, :description,
11
+ deprecated_accepts_definitions :name, :description,
12
12
  :introspection,
13
13
  :default_scalar,
14
14
  :default_relay,
@@ -41,7 +41,9 @@ module GraphQL
41
41
  alias :graphql_name :name
42
42
  # Future-compatible alias
43
43
  # @see {GraphQL::SchemaMember}
44
- alias :graphql_definition :itself
44
+ def graphql_definition(silence_deprecation_warning: false)
45
+ itself
46
+ end
45
47
 
46
48
  def type_class
47
49
  metadata[:type_class]
@@ -194,7 +196,7 @@ module GraphQL
194
196
  resolve_related_type(Object.const_get(type_arg))
195
197
  else
196
198
  if type_arg.respond_to?(:graphql_definition)
197
- type_arg.graphql_definition
199
+ type_arg.graphql_definition(silence_deprecation_warning: true)
198
200
  else
199
201
  type_arg
200
202
  end
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::BOOLEAN_TYPE = GraphQL::Types::Boolean.graphql_definition
2
+ GraphQL::BOOLEAN_TYPE = GraphQL::Types::Boolean.graphql_definition(silence_deprecation_warning: true)
@@ -138,8 +138,8 @@ module GraphQL
138
138
  # @api private
139
139
  def result_for(key)
140
140
  if !@results.key?(key)
141
- raise <<-ERR
142
- Invariant: fetching result for a key on #{self.class} that hasn't been loaded yet (#{key.inspect}, loaded: #{@results.keys})
141
+ raise GraphQL::InvariantError, <<-ERR
142
+ Fetching result for a key on #{self.class} that hasn't been loaded yet (#{key.inspect}, loaded: #{@results.keys})
143
143
 
144
144
  This key should have been loaded already. This is a bug in GraphQL::Dataloader, please report it on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new.
145
145
  ERR
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ # This error is raised when `Types::ISO8601Date` is asked to return a value
4
+ # that cannot be parsed to a Ruby Date.
5
+ #
6
+ # @see GraphQL::Types::ISO8601Date which raises this error
7
+ class DateEncodingError < GraphQL::RuntimeTypeError
8
+ # The value which couldn't be encoded
9
+ attr_reader :date_value
10
+
11
+ def initialize(value)
12
+ @date_value = value
13
+ super("Date cannot be parsed: #{value}. \nDate must be be able to be parsed as a Ruby Date object.")
14
+ end
15
+ end
16
+ end
@@ -167,6 +167,21 @@ ERR
167
167
  # Each symbol in `accepts` will be assigned with `{key}=`.
168
168
  # The last entry in accepts may be a hash of name-proc pairs for custom definitions.
169
169
  def accepts_definitions(*accepts)
170
+ deprecated_caller = caller(0, 1).first
171
+ if deprecated_caller.include?("lib/graphql")
172
+ deprecated_caller = caller(2, 10).find { |c| !c.include?("lib/graphql") }
173
+ end
174
+
175
+ if deprecated_caller
176
+ GraphQL::Deprecation.warn <<-ERR
177
+ #{self}.accepts_definitions will be removed in GraphQL-Ruby 2.0; use a class-based definition instead. See https://graphql-ruby.org/schema/class_based_api.html.
178
+ -> called from #{deprecated_caller}
179
+ ERR
180
+ end
181
+ deprecated_accepts_definitions(*accepts)
182
+ end
183
+
184
+ def deprecated_accepts_definitions(*accepts)
170
185
  new_assignments = if accepts.last.is_a?(Hash)
171
186
  accepts.pop.dup
172
187
  else
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::Directive::DeprecatedDirective = GraphQL::Schema::Directive::Deprecated.graphql_definition
2
+ GraphQL::Directive::DeprecatedDirective = GraphQL::Schema::Directive::Deprecated.graphql_definition(silence_deprecation_warning: true)
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::Directive::IncludeDirective = GraphQL::Schema::Directive::Include.graphql_definition
2
+ GraphQL::Directive::IncludeDirective = GraphQL::Schema::Directive::Include.graphql_definition(silence_deprecation_warning: true)
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::Directive::SkipDirective = GraphQL::Schema::Directive::Skip.graphql_definition
2
+ GraphQL::Directive::SkipDirective = GraphQL::Schema::Directive::Skip.graphql_definition(silence_deprecation_warning: true)
@@ -8,7 +8,7 @@ module GraphQL
8
8
  #
9
9
  class Directive
10
10
  include GraphQL::Define::InstanceDefinable
11
- accepts_definitions :locations, :name, :description, :arguments, :default_directive, argument: GraphQL::Define::AssignArgument
11
+ deprecated_accepts_definitions :locations, :name, :description, :arguments, :default_directive, argument: GraphQL::Define::AssignArgument
12
12
 
13
13
  attr_accessor :locations, :arguments, :name, :description, :arguments_class
14
14
  attr_accessor :ast_node
@@ -4,7 +4,7 @@ module GraphQL
4
4
  class EnumType < GraphQL::BaseType
5
5
  extend Define::InstanceDefinable::DeprecatedDefine
6
6
 
7
- accepts_definitions :values, value: GraphQL::Define::AssignEnumValue
7
+ deprecated_accepts_definitions :values, value: GraphQL::Define::AssignEnumValue
8
8
  ensure_defined(:values, :validate_non_null_input, :coerce_non_null_input, :coerce_result)
9
9
  attr_accessor :ast_node
10
10
 
@@ -72,7 +72,7 @@ module GraphQL
72
72
  class EnumValue
73
73
  include GraphQL::Define::InstanceDefinable
74
74
  ATTRIBUTES = [:name, :description, :deprecation_reason, :value]
75
- accepts_definitions(*ATTRIBUTES)
75
+ deprecated_accepts_definitions(*ATTRIBUTES)
76
76
  attr_accessor(*ATTRIBUTES)
77
77
  attr_accessor :ast_node
78
78
  ensure_defined(*ATTRIBUTES)
@@ -31,8 +31,10 @@ module GraphQL
31
31
  # If any jobs were enqueued, run them now,
32
32
  # since this might have been called outside of execution.
33
33
  # (The jobs are responsible for updating `result` in-place.)
34
- @dataloader.run_isolated do
35
- @storage[ast_node][argument_owner][parent_object]
34
+ if !@storage.key?(ast_node) || !@storage[ast_node].key?(argument_owner)
35
+ @dataloader.run_isolated do
36
+ @storage[ast_node][argument_owner][parent_object]
37
+ end
36
38
  end
37
39
  # Ack, the _hash_ is updated, but the key is eventually
38
40
  # overridden with an immutable arguments instance.
@@ -159,7 +159,8 @@ module GraphQL
159
159
  # Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
160
160
  @runtime_directive_names = []
161
161
  noop_resolve_owner = GraphQL::Schema::Directive.singleton_class
162
- schema.directives.each do |name, dir_defn|
162
+ @schema_directives = schema.directives
163
+ @schema_directives.each do |name, dir_defn|
163
164
  if dir_defn.method(:resolve).owner != noop_resolve_owner
164
165
  @runtime_directive_names << name
165
166
  end
@@ -206,7 +207,7 @@ module GraphQL
206
207
  # Root .authorized? returned false.
207
208
  @response = nil
208
209
  else
209
- resolve_with_directives(object_proxy, root_operation.directives) do # execute query level directives
210
+ call_method_on_directives(:resolve, object_proxy, root_operation.directives) do # execute query level directives
210
211
  gathered_selections = gather_selections(object_proxy, root_type, root_operation.selections)
211
212
  # This is kind of a hack -- `gathered_selections` is an Array if any of the selections
212
213
  # require isolation during execution (because of runtime directives). In that case,
@@ -226,7 +227,7 @@ module GraphQL
226
227
 
227
228
  @dataloader.append_job {
228
229
  set_all_interpreter_context(query.root_value, nil, nil, path)
229
- resolve_with_directives(object_proxy, selections.graphql_directives) do
230
+ call_method_on_directives(:resolve, object_proxy, selections.graphql_directives) do
230
231
  evaluate_selections(
231
232
  path,
232
233
  context.scoped_context,
@@ -399,6 +400,7 @@ module GraphQL
399
400
  raise "Invariant: no field for #{owner_type}.#{field_name}"
400
401
  end
401
402
  end
403
+
402
404
  return_type = field_defn.type
403
405
 
404
406
  next_path = path.dup
@@ -424,18 +426,17 @@ module GraphQL
424
426
  total_args_count = field_defn.arguments(context).size
425
427
  if total_args_count == 0
426
428
  resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
427
- evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
429
+ evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
428
430
  else
429
431
  # TODO remove all arguments(...) usages?
430
432
  @query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
431
- evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
433
+ evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
432
434
  end
433
435
  end
434
436
  end
435
437
 
436
- def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result, parent_object) # rubocop:disable Metrics/ParameterLists
438
+ def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type) # rubocop:disable Metrics/ParameterLists
437
439
  context.scoped_context = scoped_context
438
- return_type = field_defn.type
439
440
  after_lazy(arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
440
441
  if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
441
442
  continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
@@ -502,7 +503,7 @@ module GraphQL
502
503
  }
503
504
  end
504
505
 
505
- field_result = resolve_with_directives(object, directives) do
506
+ field_result = call_method_on_directives(:resolve, object, directives) do
506
507
  # Actually call the field resolver and capture the result
507
508
  app_result = begin
508
509
  query.with_error_handling do
@@ -516,7 +517,7 @@ module GraphQL
516
517
  after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
517
518
  continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
518
519
  if HALT != continue_value
519
- continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments, result_name, selection_result)
520
+ continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
520
521
  end
521
522
  end
522
523
  end
@@ -734,7 +735,7 @@ module GraphQL
734
735
  final_result = nil
735
736
  end
736
737
  set_all_interpreter_context(continue_value, nil, nil, path) # reset this mutable state
737
- resolve_with_directives(continue_value, selections.graphql_directives) do
738
+ call_method_on_directives(:resolve, continue_value, selections.graphql_directives) do
738
739
  evaluate_selections(
739
740
  path,
740
741
  context.scoped_context,
@@ -753,6 +754,8 @@ module GraphQL
753
754
  end
754
755
  when "LIST"
755
756
  inner_type = current_type.of_type
757
+ # This is true for objects, unions, and interfaces
758
+ use_dataloader_job = !inner_type.unwrap.kind.input?
756
759
  response_list = GraphQLResultArray.new(result_name, selection_result)
757
760
  response_list.graphql_non_null_list_items = inner_type.non_null?
758
761
  set_result(selection_result, result_name, response_list)
@@ -767,12 +770,12 @@ module GraphQL
767
770
  this_idx = idx
768
771
  next_path.freeze
769
772
  idx += 1
770
- # This will update `response_list` with the lazy
771
- after_lazy(inner_value, owner: inner_type, path: next_path, ast_node: ast_node, scoped_context: scoped_context, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list) do |inner_inner_value|
772
- continue_value = continue_value(next_path, inner_inner_value, owner_type, field, inner_type.non_null?, ast_node, this_idx, response_list)
773
- if HALT != continue_value
774
- continue_field(next_path, continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
773
+ if use_dataloader_job
774
+ @dataloader.append_job do
775
+ resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
775
776
  end
777
+ else
778
+ resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
776
779
  end
777
780
  end
778
781
  rescue NoMethodError => err
@@ -792,17 +795,30 @@ module GraphQL
792
795
  end
793
796
  end
794
797
 
795
- def resolve_with_directives(object, directives, &block)
798
+ def resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type) # rubocop:disable Metrics/ParameterLists
799
+ set_all_interpreter_context(nil, nil, nil, next_path)
800
+ call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
801
+ # This will update `response_list` with the lazy
802
+ after_lazy(inner_value, owner: inner_type, path: next_path, ast_node: ast_node, scoped_context: scoped_context, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list) do |inner_inner_value|
803
+ continue_value = continue_value(next_path, inner_inner_value, owner_type, field, inner_type.non_null?, ast_node, this_idx, response_list)
804
+ if HALT != continue_value
805
+ continue_field(next_path, continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
806
+ end
807
+ end
808
+ end
809
+ end
810
+
811
+ def call_method_on_directives(method_name, object, directives, &block)
796
812
  return yield if directives.nil? || directives.empty?
797
- run_directive(object, directives, 0, &block)
813
+ run_directive(method_name, object, directives, 0, &block)
798
814
  end
799
815
 
800
- def run_directive(object, directives, idx, &block)
816
+ def run_directive(method_name, object, directives, idx, &block)
801
817
  dir_node = directives[idx]
802
818
  if !dir_node
803
819
  yield
804
820
  else
805
- dir_defn = schema.directives.fetch(dir_node.name)
821
+ dir_defn = @schema_directives.fetch(dir_node.name)
806
822
  if !dir_defn.is_a?(Class)
807
823
  dir_defn = dir_defn.type_class || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
808
824
  end
@@ -821,8 +837,8 @@ module GraphQL
821
837
  if dir_args == HALT
822
838
  nil
823
839
  else
824
- dir_defn.resolve(object, dir_args, context) do
825
- run_directive(object, directives, idx + 1, &block)
840
+ dir_defn.public_send(method_name, object, dir_args, context) do
841
+ run_directive(method_name, object, directives, idx + 1, &block)
826
842
  end
827
843
  end
828
844
  end
@@ -831,7 +847,7 @@ module GraphQL
831
847
  # Check {Schema::Directive.include?} for each directive that's present
832
848
  def directives_include?(node, graphql_object, parent_type)
833
849
  node.directives.each do |dir_node|
834
- dir_defn = schema.directives.fetch(dir_node.name).type_class || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
850
+ dir_defn = @schema_directives.fetch(dir_node.name).type_class || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
835
851
  args = arguments(graphql_object, dir_defn, dir_node)
836
852
  if !dir_defn.include?(graphql_object, args, context)
837
853
  return false
@@ -870,16 +886,20 @@ module GraphQL
870
886
  # but don't wrap the continuation below
871
887
  inner_obj = begin
872
888
  query.with_error_handling do
873
- if trace
874
- query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
889
+ begin
890
+ if trace
891
+ query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
892
+ schema.sync_lazy(lazy_obj)
893
+ end
894
+ else
875
895
  schema.sync_lazy(lazy_obj)
876
896
  end
877
- else
878
- schema.sync_lazy(lazy_obj)
897
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
898
+ err
879
899
  end
880
900
  end
881
- rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
882
- err
901
+ rescue GraphQL::ExecutionError => ex_err
902
+ ex_err
883
903
  end
884
904
  yield(inner_obj)
885
905
  end
@@ -151,6 +151,9 @@ module GraphQL
151
151
 
152
152
  result
153
153
  end
154
+ if query.context.namespace?(:__query_result_extensions__)
155
+ query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
156
+ end
154
157
  end
155
158
 
156
159
  # use the old `query_execution_strategy` etc to run this query
data/lib/graphql/field.rb CHANGED
@@ -5,7 +5,7 @@ module GraphQL
5
5
  # @api deprecated
6
6
  class Field
7
7
  include GraphQL::Define::InstanceDefinable
8
- accepts_definitions :name, :description, :deprecation_reason,
8
+ deprecated_accepts_definitions :name, :description, :deprecation_reason,
9
9
  :resolve, :lazy_resolve,
10
10
  :type, :arguments,
11
11
  :property, :hash_key, :complexity,
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition
2
+ GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition(silence_deprecation_warning: true)
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::ID_TYPE = GraphQL::Types::ID.graphql_definition
2
+ GraphQL::ID_TYPE = GraphQL::Types::ID.graphql_definition(silence_deprecation_warning: true)
@@ -4,7 +4,7 @@ module GraphQL
4
4
  class InputObjectType < GraphQL::BaseType
5
5
  extend Define::InstanceDefinable::DeprecatedDefine
6
6
 
7
- accepts_definitions(
7
+ deprecated_accepts_definitions(
8
8
  :arguments, :mutation,
9
9
  input_field: GraphQL::Define::AssignArgument,
10
10
  argument: GraphQL::Define::AssignArgument
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::INT_TYPE = GraphQL::Types::Int.graphql_definition
2
+ GraphQL::INT_TYPE = GraphQL::Types::Int.graphql_definition(silence_deprecation_warning: true)
@@ -4,7 +4,7 @@ module GraphQL
4
4
  class InterfaceType < GraphQL::BaseType
5
5
  extend Define::InstanceDefinable::DeprecatedDefine
6
6
 
7
- accepts_definitions :fields, :orphan_types, :resolve_type, field: GraphQL::Define::AssignObjectField
7
+ deprecated_accepts_definitions :fields, :orphan_types, :resolve_type, field: GraphQL::Define::AssignObjectField
8
8
 
9
9
  attr_accessor :fields, :orphan_types, :resolve_type_proc
10
10
  attr_writer :type_membership_class
@@ -6,8 +6,8 @@ module GraphQL
6
6
  description "A Directive can be adjacent to many parts of the GraphQL language, "\
7
7
  "a __DirectiveLocation describes one such possible adjacencies."
8
8
 
9
- GraphQL::Directive::LOCATIONS.each do |location|
10
- value(location.to_s, GraphQL::Directive::LOCATION_DESCRIPTIONS[location], value: location)
9
+ GraphQL::Schema::Directive::LOCATIONS.each do |location|
10
+ value(location.to_s, GraphQL::Schema::Directive::LOCATION_DESCRIPTIONS[location], value: location)
11
11
  end
12
12
  introspection true
13
13
  end
@@ -11,14 +11,16 @@ module GraphQL
11
11
  "to the executor."
12
12
  field :name, String, null: false, method: :graphql_name
13
13
  field :description, String
14
- field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
15
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
14
+ field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false, scope: false
15
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
16
16
  argument :include_deprecated, Boolean, required: false, default_value: false
17
17
  end
18
18
  field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
19
19
  field :on_fragment, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_fragment?
20
20
  field :on_field, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_field?
21
21
 
22
+ field :is_repeatable, Boolean, method: :repeatable?
23
+
22
24
  def args(include_deprecated:)
23
25
  args = @context.warden.arguments(@object)
24
26
  args = args.reject(&:deprecation_reason) unless include_deprecated
@@ -7,7 +7,7 @@ module GraphQL
7
7
  "a name, potentially a list of arguments, and a return type."
8
8
  field :name, String, null: false
9
9
  field :description, String
10
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
10
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
11
11
  argument :include_deprecated, Boolean, required: false, default_value: false
12
12
  end
13
13
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
@@ -8,11 +8,16 @@ module GraphQL
8
8
  "available types and directives on the server, as well as the entry points for "\
9
9
  "query, mutation, and subscription operations."
10
10
 
11
- field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false
11
+ field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false, scope: false
12
12
  field :query_type, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
13
13
  field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at."
14
14
  field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at."
15
- field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false
15
+ field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false, scope: false
16
+ field :description, String, resolver_method: :schema_description
17
+
18
+ def schema_description
19
+ context.schema.description
20
+ end
16
21
 
17
22
  def types
18
23
  @context.warden.reachable_types.sort_by(&:graphql_name)
@@ -12,23 +12,29 @@ module GraphQL
12
12
  "possible at runtime. List and NonNull types compose other types."
13
13
 
14
14
  field :kind, GraphQL::Schema::LateBoundType.new("__TypeKind"), null: false
15
- field :name, String
15
+ field :name, String, method: :graphql_name
16
16
  field :description, String
17
- field :fields, [GraphQL::Schema::LateBoundType.new("__Field")] do
17
+ field :fields, [GraphQL::Schema::LateBoundType.new("__Field")], scope: false do
18
18
  argument :include_deprecated, Boolean, required: false, default_value: false
19
19
  end
20
- field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")]
21
- field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")]
22
- field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")] do
20
+ field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
21
+ field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
22
+ field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], scope: false do
23
23
  argument :include_deprecated, Boolean, required: false, default_value: false
24
24
  end
25
- field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")] do
25
+ field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], scope: false do
26
26
  argument :include_deprecated, Boolean, required: false, default_value: false
27
27
  end
28
28
  field :of_type, GraphQL::Schema::LateBoundType.new("__Type")
29
29
 
30
- def name
31
- object.graphql_name
30
+ field :specified_by_url, String
31
+
32
+ def specified_by_url
33
+ if object.kind.scalar?
34
+ object.specified_by_url
35
+ else
36
+ nil
37
+ end
32
38
  end
33
39
 
34
40
  def kind