graphql 1.13.6 → 2.0.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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +0 -7
  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/{templates → install/templates}/base_mutation.erb +0 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
  9. data/lib/generators/graphql/install_generator.rb +1 -1
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  12. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_generator.rb +5 -30
  14. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  15. data/lib/generators/graphql/object_generator.rb +8 -37
  16. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  17. data/lib/generators/graphql/scalar_generator.rb +4 -2
  18. data/lib/generators/graphql/templates/enum.erb +5 -1
  19. data/lib/generators/graphql/templates/input.erb +9 -0
  20. data/lib/generators/graphql/templates/interface.erb +4 -2
  21. data/lib/generators/graphql/templates/mutation.erb +1 -1
  22. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  23. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  24. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  25. data/lib/generators/graphql/templates/object.erb +4 -2
  26. data/lib/generators/graphql/templates/scalar.erb +3 -1
  27. data/lib/generators/graphql/templates/union.erb +4 -2
  28. data/lib/generators/graphql/type_generator.rb +46 -9
  29. data/lib/generators/graphql/union_generator.rb +5 -5
  30. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  31. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  32. data/lib/graphql/analysis/ast/visitor.rb +3 -2
  33. data/lib/graphql/analysis/ast.rb +0 -10
  34. data/lib/graphql/analysis.rb +0 -7
  35. data/lib/graphql/backtrace/table.rb +0 -18
  36. data/lib/graphql/backtrace/tracer.rb +1 -2
  37. data/lib/graphql/backtrace.rb +2 -8
  38. data/lib/graphql/dataloader/source.rb +2 -2
  39. data/lib/graphql/dig.rb +1 -1
  40. data/lib/graphql/execution/errors.rb +1 -9
  41. data/lib/graphql/execution/interpreter/runtime.rb +2 -9
  42. data/lib/graphql/execution/interpreter.rb +0 -22
  43. data/lib/graphql/execution/lazy.rb +1 -1
  44. data/lib/graphql/execution/lookahead.rb +6 -13
  45. data/lib/graphql/execution/multiplex.rb +50 -107
  46. data/lib/graphql/execution.rb +11 -3
  47. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  48. data/lib/graphql/introspection/entry_points.rb +2 -15
  49. data/lib/graphql/introspection.rb +4 -4
  50. data/lib/graphql/language/document_from_schema_definition.rb +0 -17
  51. data/lib/graphql/pagination/connections.rb +2 -28
  52. data/lib/graphql/query/context.rb +1 -185
  53. data/lib/graphql/query/literal_input.rb +8 -13
  54. data/lib/graphql/query/validation_pipeline.rb +8 -37
  55. data/lib/graphql/query/variables.rb +22 -18
  56. data/lib/graphql/query.rb +5 -35
  57. data/lib/graphql/railtie.rb +0 -104
  58. data/lib/graphql/relay.rb +0 -15
  59. data/lib/graphql/rubocop/graphql/default_required_true.rb +4 -4
  60. data/lib/graphql/schema/addition.rb +1 -8
  61. data/lib/graphql/schema/argument.rb +18 -25
  62. data/lib/graphql/schema/build_from_definition.rb +0 -1
  63. data/lib/graphql/schema/directive.rb +4 -21
  64. data/lib/graphql/schema/enum.rb +1 -18
  65. data/lib/graphql/schema/enum_value.rb +0 -22
  66. data/lib/graphql/schema/field.rb +22 -194
  67. data/lib/graphql/schema/input_object.rb +10 -57
  68. data/lib/graphql/schema/interface.rb +0 -25
  69. data/lib/graphql/schema/introspection_system.rb +3 -8
  70. data/lib/graphql/schema/late_bound_type.rb +2 -2
  71. data/lib/graphql/schema/list.rb +0 -6
  72. data/lib/graphql/schema/loader.rb +0 -1
  73. data/lib/graphql/schema/member/base_dsl_methods.rb +0 -5
  74. data/lib/graphql/schema/member/build_type.rb +4 -6
  75. data/lib/graphql/schema/member/has_arguments.rb +14 -18
  76. data/lib/graphql/schema/member/has_fields.rb +2 -2
  77. data/lib/graphql/schema/member/has_interfaces.rb +0 -2
  78. data/lib/graphql/schema/member.rb +0 -6
  79. data/lib/graphql/schema/mutation.rb +0 -9
  80. data/lib/graphql/schema/non_null.rb +1 -7
  81. data/lib/graphql/schema/object.rb +0 -40
  82. data/lib/graphql/schema/relay_classic_mutation.rb +17 -28
  83. data/lib/graphql/schema/scalar.rb +0 -15
  84. data/lib/graphql/schema/union.rb +0 -16
  85. data/lib/graphql/schema/warden.rb +1 -1
  86. data/lib/graphql/schema/wrapper.rb +0 -5
  87. data/lib/graphql/schema.rb +107 -949
  88. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  89. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  90. data/lib/graphql/static_validation/validator.rb +2 -24
  91. data/lib/graphql/static_validation.rb +0 -2
  92. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  93. data/lib/graphql/subscriptions/event.rb +1 -1
  94. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  95. data/lib/graphql/subscriptions.rb +4 -13
  96. data/lib/graphql/tracing/platform_tracing.rb +0 -23
  97. data/lib/graphql/tracing.rb +0 -1
  98. data/lib/graphql/types/iso_8601_date_time.rb +8 -1
  99. data/lib/graphql/types/relay/connection_behaviors.rb +4 -7
  100. data/lib/graphql/types/relay/default_relay.rb +0 -10
  101. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  102. data/lib/graphql/types/relay.rb +0 -2
  103. data/lib/graphql/version.rb +1 -1
  104. data/lib/graphql.rb +12 -65
  105. metadata +15 -129
  106. data/lib/graphql/analysis/analyze_query.rb +0 -98
  107. data/lib/graphql/analysis/field_usage.rb +0 -45
  108. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  109. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  110. data/lib/graphql/analysis/query_complexity.rb +0 -88
  111. data/lib/graphql/analysis/query_depth.rb +0 -43
  112. data/lib/graphql/analysis/reducer_state.rb +0 -48
  113. data/lib/graphql/argument.rb +0 -131
  114. data/lib/graphql/authorization.rb +0 -82
  115. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  116. data/lib/graphql/backwards_compatibility.rb +0 -61
  117. data/lib/graphql/base_type.rb +0 -232
  118. data/lib/graphql/boolean_type.rb +0 -2
  119. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  120. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  121. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  122. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  123. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  124. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  125. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  126. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  127. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  128. data/lib/graphql/compatibility.rb +0 -5
  129. data/lib/graphql/define/assign_argument.rb +0 -12
  130. data/lib/graphql/define/assign_connection.rb +0 -13
  131. data/lib/graphql/define/assign_enum_value.rb +0 -18
  132. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  133. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  134. data/lib/graphql/define/assign_object_field.rb +0 -42
  135. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  136. data/lib/graphql/define/instance_definable.rb +0 -240
  137. data/lib/graphql/define/no_definition_error.rb +0 -7
  138. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  139. data/lib/graphql/define/type_definer.rb +0 -31
  140. data/lib/graphql/define.rb +0 -31
  141. data/lib/graphql/deprecated_dsl.rb +0 -55
  142. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  143. data/lib/graphql/directive/include_directive.rb +0 -2
  144. data/lib/graphql/directive/skip_directive.rb +0 -2
  145. data/lib/graphql/directive.rb +0 -107
  146. data/lib/graphql/enum_type.rb +0 -133
  147. data/lib/graphql/execution/execute.rb +0 -333
  148. data/lib/graphql/execution/flatten.rb +0 -40
  149. data/lib/graphql/execution/typecast.rb +0 -50
  150. data/lib/graphql/field/resolve.rb +0 -59
  151. data/lib/graphql/field.rb +0 -226
  152. data/lib/graphql/float_type.rb +0 -2
  153. data/lib/graphql/function.rb +0 -128
  154. data/lib/graphql/id_type.rb +0 -2
  155. data/lib/graphql/input_object_type.rb +0 -138
  156. data/lib/graphql/int_type.rb +0 -2
  157. data/lib/graphql/interface_type.rb +0 -72
  158. data/lib/graphql/internal_representation/document.rb +0 -27
  159. data/lib/graphql/internal_representation/node.rb +0 -206
  160. data/lib/graphql/internal_representation/print.rb +0 -51
  161. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  162. data/lib/graphql/internal_representation/scope.rb +0 -88
  163. data/lib/graphql/internal_representation/visit.rb +0 -36
  164. data/lib/graphql/internal_representation.rb +0 -7
  165. data/lib/graphql/list_type.rb +0 -80
  166. data/lib/graphql/non_null_type.rb +0 -71
  167. data/lib/graphql/object_type.rb +0 -130
  168. data/lib/graphql/query/arguments.rb +0 -189
  169. data/lib/graphql/query/arguments_cache.rb +0 -24
  170. data/lib/graphql/query/executor.rb +0 -52
  171. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  172. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  173. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  174. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  175. data/lib/graphql/query/serial_execution.rb +0 -40
  176. data/lib/graphql/relay/array_connection.rb +0 -83
  177. data/lib/graphql/relay/base_connection.rb +0 -189
  178. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  179. data/lib/graphql/relay/connection_resolve.rb +0 -43
  180. data/lib/graphql/relay/connection_type.rb +0 -41
  181. data/lib/graphql/relay/edge.rb +0 -27
  182. data/lib/graphql/relay/edge_type.rb +0 -19
  183. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  184. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  185. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  186. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  187. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  188. data/lib/graphql/relay/mutation/result.rb +0 -38
  189. data/lib/graphql/relay/mutation.rb +0 -106
  190. data/lib/graphql/relay/node.rb +0 -39
  191. data/lib/graphql/relay/page_info.rb +0 -7
  192. data/lib/graphql/relay/relation_connection.rb +0 -188
  193. data/lib/graphql/relay/type_extensions.rb +0 -32
  194. data/lib/graphql/scalar_type.rb +0 -91
  195. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  196. data/lib/graphql/schema/default_parse_error.rb +0 -10
  197. data/lib/graphql/schema/default_type_error.rb +0 -17
  198. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  199. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  200. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  201. data/lib/graphql/schema/middleware_chain.rb +0 -82
  202. data/lib/graphql/schema/possible_types.rb +0 -44
  203. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  204. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  205. data/lib/graphql/schema/traversal.rb +0 -228
  206. data/lib/graphql/schema/validation.rb +0 -313
  207. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  208. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  209. data/lib/graphql/string_type.rb +0 -2
  210. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  211. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  212. data/lib/graphql/types/relay/node_field.rb +0 -24
  213. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  214. data/lib/graphql/union_type.rb +0 -115
  215. data/lib/graphql/upgrader/member.rb +0 -937
  216. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -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
@@ -5,7 +5,7 @@ module GraphQL
5
5
  module AST
6
6
  class QueryComplexity < Analyzer
7
7
  # State for the query complexity calculation:
8
- # - `complexities_on_type` holds complexity scores for each type in an IRep node
8
+ # - `complexities_on_type` holds complexity scores for each type
9
9
  def initialize(query)
10
10
  super
11
11
  @complexities_on_type_by_query = {}
@@ -15,7 +15,6 @@ module GraphQL
15
15
  # # In your Schema file:
16
16
  #
17
17
  # class MySchema < GraphQL::Schema
18
- # use GraphQL::Analysis::AST
19
18
  # query_analyzer LogQueryDepth
20
19
  # end
21
20
  #
@@ -43,7 +43,7 @@ module GraphQL
43
43
 
44
44
  # Visit Helpers
45
45
 
46
- # @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
46
+ # @return [GraphQL::Execution::Interpreter::Arguments] Arguments for this node, merging default values, literal values and query variables
47
47
  # @see {GraphQL::Query#arguments_for}
48
48
  def arguments_for(ast_node, field_definition)
49
49
  @query.arguments_for(ast_node, field_definition)
@@ -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
@@ -11,16 +11,6 @@ module GraphQL
11
11
  module Analysis
12
12
  module AST
13
13
  module_function
14
-
15
- def use(schema_class)
16
- if schema_class.analysis_engine == self
17
- definition_line = caller(2, 1).first
18
- GraphQL::Deprecation.warn("GraphQL::Analysis::AST is now the default; remove `use GraphQL::Analysis::AST` from the schema definition (#{definition_line})")
19
- else
20
- schema_class.analysis_engine = self
21
- end
22
- end
23
-
24
14
  # Analyze a multiplex, and all queries within.
25
15
  # Multiplex analyzers are ran for all queries, keeping state.
26
16
  # Query analyzers are ran per query, without carrying state between queries.
@@ -1,9 +1,2 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/analysis/ast"
3
- require "graphql/analysis/max_query_complexity"
4
- require "graphql/analysis/max_query_depth"
5
- require "graphql/analysis/query_complexity"
6
- require "graphql/analysis/query_depth"
7
- require "graphql/analysis/reducer_state"
8
- require "graphql/analysis/analyze_query"
9
- require "graphql/analysis/field_usage"
@@ -97,24 +97,6 @@ module GraphQL
97
97
  else
98
98
  rows
99
99
  end
100
- when GraphQL::Query::Context::FieldResolutionContext
101
- ctx = context_entry
102
- field_name = "#{ctx.irep_node.owner_type.name}.#{ctx.field.name}"
103
- position = "#{ctx.ast_node.line}:#{ctx.ast_node.col}"
104
- field_alias = ctx.ast_node.alias
105
- object = ctx.object
106
- if object.is_a?(GraphQL::Schema::Object)
107
- object = object.object
108
- end
109
- rows << [
110
- "#{position}",
111
- "#{field_name}#{field_alias ? " as #{field_alias}" : ""}",
112
- "#{object.inspect}",
113
- ctx.irep_node.arguments.to_h.inspect,
114
- Backtrace::InspectResult.inspect_result(top && @override_value ? @override_value : ctx.value),
115
- ]
116
-
117
- build_rows(ctx.parent, rows: rows)
118
100
  when GraphQL::Query::Context
119
101
  query = context_entry.query
120
102
  op = query.selected_operation
@@ -23,7 +23,7 @@ module GraphQL
23
23
  push_data = multiplex.queries.first
24
24
  end
25
25
  when "execute_field", "execute_field_lazy"
26
- query = metadata[:query] || raise(ArgumentError, "Add `legacy: true` to use GraphQL::Backtrace without the interpreter runtime.")
26
+ query = metadata[:query]
27
27
  multiplex = query.multiplex
28
28
  push_key = metadata[:path]
29
29
  parent_frame = multiplex.context[:graphql_backtrace_contexts][push_key[0..-2]]
@@ -62,7 +62,6 @@ module GraphQL
62
62
  potential_context = multiplex_context[:last_graphql_backtrace_context]
63
63
 
64
64
  if potential_context.is_a?(GraphQL::Query::Context) ||
65
- potential_context.is_a?(GraphQL::Query::Context::FieldResolutionContext) ||
66
65
  potential_context.is_a?(Backtrace::Frame)
67
66
  raise TracedError.new(err, potential_context)
68
67
  else
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/backtrace/inspect_result"
3
- require "graphql/backtrace/legacy_tracer"
4
3
  require "graphql/backtrace/table"
5
4
  require "graphql/backtrace/traced_error"
6
5
  require "graphql/backtrace/tracer"
@@ -23,13 +22,8 @@ module GraphQL
23
22
 
24
23
  def_delegators :to_a, :each, :[]
25
24
 
26
- def self.use(schema_defn, legacy: false)
27
- tracer = if legacy
28
- self::LegacyTracer
29
- else
30
- self::Tracer
31
- end
32
- schema_defn.tracer(tracer)
25
+ def self.use(schema_defn)
26
+ schema_defn.tracer(self::Tracer)
33
27
  end
34
28
 
35
29
  def initialize(context, value: nil)
@@ -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
data/lib/graphql/dig.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  module GraphQL
3
3
  module Dig
4
4
  # implemented using the old activesupport #dig instead of the ruby built-in
5
- # so we can use some of the magic in Schema::InputObject and Query::Arguments
5
+ # so we can use some of the magic in Schema::InputObject and Interpreter::Arguments
6
6
  # to handle stringified/symbolized keys.
7
7
  #
8
8
  # @param args [Array<[String, Symbol>] Retrieves the value object corresponding to the each key objects repeatedly
@@ -2,14 +2,11 @@
2
2
 
3
3
  module GraphQL
4
4
  module Execution
5
- # A plugin that wraps query execution with error handling.
6
- # Supports class-based schemas and the new {Interpreter} runtime only.
5
+ # A plugin that wraps query execution with error handling. Installed by default.
7
6
  #
8
7
  # @example Handling ActiveRecord::NotFound
9
8
  #
10
9
  # class MySchema < GraphQL::Schema
11
- # use GraphQL::Execution::Errors
12
- #
13
10
  # rescue_from(ActiveRecord::NotFound) do |err, obj, args, ctx, field|
14
11
  # ErrorTracker.log("Not Found: #{err.message}")
15
12
  # nil
@@ -17,11 +14,6 @@ module GraphQL
17
14
  # end
18
15
  #
19
16
  class Errors
20
- def self.use(schema)
21
- definition_line = caller(2, 1).first
22
- GraphQL::Deprecation.warn("GraphQL::Execution::Errors is now installed by default, remove `use GraphQL::Execution::Errors` from #{definition_line}")
23
- end
24
-
25
17
  NEW_HANDLER_HASH = ->(h, k) {
26
18
  h[k] = {
27
19
  class: k,
@@ -472,10 +472,6 @@ module GraphQL
472
472
  # Use this flag to tell Interpreter::Arguments to add itself
473
473
  # to the keyword args hash _before_ freezing everything.
474
474
  extra_args[:argument_details] = :__arguments_add_self
475
- when :irep_node
476
- # This is used by `__typename` in order to support the legacy runtime,
477
- # but it has no use here (and it's always `nil`).
478
- # Stop adding it here to avoid the overhead of `.merge_extras` below.
479
475
  when :parent
480
476
  extra_args[:parent] = parent_object
481
477
  else
@@ -619,7 +615,7 @@ module GraphQL
619
615
  err
620
616
  end
621
617
  continue_value(path, next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
622
- elsif GraphQL::Execution::Execute::SKIP == value
618
+ elsif GraphQL::Execution::SKIP == value
623
619
  # It's possible a lazy was already written here
624
620
  case selection_result
625
621
  when GraphQLResultHash
@@ -819,9 +815,6 @@ module GraphQL
819
815
  yield
820
816
  else
821
817
  dir_defn = @schema_directives.fetch(dir_node.name)
822
- if !dir_defn.is_a?(Class)
823
- dir_defn = dir_defn.type_class || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
824
- end
825
818
  raw_dir_args = arguments(nil, dir_defn, dir_node)
826
819
  dir_args = continue_value(
827
820
  @context[:current_path], # path
@@ -847,7 +840,7 @@ module GraphQL
847
840
  # Check {Schema::Directive.include?} for each directive that's present
848
841
  def directives_include?(node, graphql_object, parent_type)
849
842
  node.directives.each do |dir_node|
850
- dir_defn = @schema_directives.fetch(dir_node.name).type_class || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
843
+ dir_defn = @schema_directives.fetch(dir_node.name)
851
844
  args = arguments(graphql_object, dir_defn, dir_node)
852
845
  if !dir_defn.include?(graphql_object, args, context)
853
846
  return false
@@ -11,28 +11,6 @@ require "graphql/execution/interpreter/handles_raw_value"
11
11
  module GraphQL
12
12
  module Execution
13
13
  class Interpreter
14
- def initialize
15
- end
16
-
17
- # Support `Executor` :S
18
- def execute(_operation, _root_type, query)
19
- runtime = evaluate(query)
20
- sync_lazies(query: query)
21
- runtime.final_result
22
- end
23
-
24
- def self.use(schema_class)
25
- if schema_class.interpreter?
26
- definition_line = caller(2, 1).first
27
- GraphQL::Deprecation.warn("GraphQL::Execution::Interpreter is now the default; remove `use GraphQL::Execution::Interpreter` from the schema definition (#{definition_line})")
28
- else
29
- schema_class.query_execution_strategy(self)
30
- schema_class.mutation_execution_strategy(self)
31
- schema_class.subscription_execution_strategy(self)
32
- schema_class.add_subscription_extension_if_necessary
33
- end
34
- end
35
-
36
14
  def self.begin_multiplex(multiplex)
37
15
  # Since this is basically the batching context,
38
16
  # share it for a whole multiplex
@@ -52,7 +52,7 @@ module GraphQL
52
52
  # (fewer clauses in a hot `case` block), but now it requires special handling here.
53
53
  # I think it's still worth it for the performance win, but if the number of special
54
54
  # cases grows, then maybe it's worth rethinking somehow.
55
- if @value.is_a?(StandardError) && @value != GraphQL::Execution::Execute::SKIP
55
+ if @value.is_a?(StandardError) && @value != GraphQL::Execution::SKIP
56
56
  raise @value
57
57
  else
58
58
  @value
@@ -91,7 +91,7 @@ module GraphQL
91
91
  def selection(field_name, selected_type: @selected_type, arguments: nil)
92
92
  next_field_name = normalize_name(field_name)
93
93
 
94
- next_field_defn = get_class_based_field(selected_type, next_field_name)
94
+ next_field_defn = @query.get_field(selected_type, next_field_name)
95
95
  if next_field_defn
96
96
  next_nodes = []
97
97
  @ast_nodes.each do |ast_node|
@@ -137,7 +137,7 @@ module GraphQL
137
137
 
138
138
  subselections_by_type.each do |type, ast_nodes_by_response_key|
139
139
  ast_nodes_by_response_key.each do |response_key, ast_nodes|
140
- field_defn = get_class_based_field(type, ast_nodes.first.name)
140
+ field_defn = @query.get_field(type, ast_nodes.first.name)
141
141
  lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
142
142
  subselections.push(lookahead)
143
143
  end
@@ -213,17 +213,10 @@ module GraphQL
213
213
  end
214
214
  end
215
215
 
216
- # Wrap get_field and ensure that it returns a GraphQL::Schema::Field.
217
- # Remove this when legacy execution is removed.
218
- def get_class_based_field(type, name)
219
- f = @query.get_field(type, name)
220
- f && f.type_class
221
- end
222
-
223
216
  def skipped_by_directive?(ast_selection)
224
217
  ast_selection.directives.each do |directive|
225
218
  dir_defn = @query.schema.directives.fetch(directive.name)
226
- directive_class = dir_defn.type_class
219
+ directive_class = dir_defn
227
220
  if directive_class
228
221
  dir_args = @query.arguments_for(directive, dir_defn)
229
222
  return true unless directive_class.static_include?(dir_args, @query.context)
@@ -244,7 +237,7 @@ module GraphQL
244
237
  elsif arguments.nil? || arguments.empty?
245
238
  selections_on_type[response_key] = [ast_selection]
246
239
  else
247
- field_defn = get_class_based_field(selected_type, ast_selection.name)
240
+ field_defn = @query.get_field(selected_type, ast_selection.name)
248
241
  if arguments_match?(arguments, field_defn, ast_selection)
249
242
  selections_on_type[response_key] = [ast_selection]
250
243
  end
@@ -254,14 +247,14 @@ module GraphQL
254
247
  subselections_on_type = selections_on_type
255
248
  if (t = ast_selection.type)
256
249
  # Assuming this is valid, that `t` will be found.
257
- on_type = @query.get_type(t.name).type_class
250
+ on_type = @query.get_type(t.name)
258
251
  subselections_on_type = subselections_by_type[on_type] ||= {}
259
252
  end
260
253
  find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
261
254
  when GraphQL::Language::Nodes::FragmentSpread
262
255
  frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
263
256
  # Again, assuming a valid AST
264
- on_type = @query.get_type(frag_defn.type.name).type_class
257
+ on_type = @query.get_type(frag_defn.type.name)
265
258
  subselections_on_type = subselections_by_type[on_type] ||= {}
266
259
  find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
267
260
  else
@@ -45,30 +45,64 @@ module GraphQL
45
45
  end
46
46
 
47
47
  class << self
48
- def run_all(schema, query_options, **kwargs)
49
- queries = query_options.map { |opts| GraphQL::Query.new(schema, nil, **opts) }
50
- run_queries(schema, queries, **kwargs)
51
- end
52
-
53
48
  # @param schema [GraphQL::Schema]
54
- # @param queries [Array<GraphQL::Query>]
49
+ # @param queries [Array<GraphQL::Query, Hash>]
55
50
  # @param context [Hash]
56
51
  # @param max_complexity [Integer, nil]
57
52
  # @return [Array<Hash>] One result per query
58
- def run_queries(schema, queries, context: {}, max_complexity: schema.max_complexity)
53
+ def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
54
+ queries = query_options.map do |opts|
55
+ case opts
56
+ when Hash
57
+ GraphQL::Query.new(schema, nil, **opts)
58
+ when GraphQL::Query
59
+ opts
60
+ else
61
+ raise "Expected Hash or GraphQL::Query, not #{opts.class} (#{opts.inspect})"
62
+ end
63
+ end
64
+
59
65
  multiplex = self.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
60
66
  multiplex.trace("execute_multiplex", { multiplex: multiplex }) do
61
- if supports_multiplexing?(schema)
62
- instrument_and_analyze(multiplex) do
63
- run_as_multiplex(multiplex)
67
+ GraphQL::Execution::Instrumentation.apply_instrumenters(multiplex) do
68
+ schema = multiplex.schema
69
+ multiplex_analyzers = schema.multiplex_analyzers
70
+ if multiplex.max_complexity
71
+ multiplex_analyzers += [GraphQL::Analysis::AST::MaxQueryComplexity]
64
72
  end
65
- else
66
- if queries.length != 1
67
- raise ArgumentError, "Multiplexing doesn't support custom execution strategies, run one query at a time instead"
68
- else
69
- instrument_and_analyze(multiplex) do
70
- [run_one_legacy(schema, queries.first)]
73
+
74
+ schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
75
+
76
+ begin
77
+ multiplex.schema.query_execution_strategy.begin_multiplex(multiplex)
78
+ # Do as much eager evaluation of the query as possible
79
+ results = []
80
+ queries.each_with_index do |query, idx|
81
+ multiplex.dataloader.append_job { begin_query(results, idx, query, multiplex) }
71
82
  end
83
+
84
+ multiplex.dataloader.run
85
+
86
+ # Then, work through lazy results in a breadth-first way
87
+ multiplex.dataloader.append_job {
88
+ multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
89
+ }
90
+ multiplex.dataloader.run
91
+
92
+ # Then, find all errors and assign the result to the query object
93
+ results.each_with_index do |data_result, idx|
94
+ query = queries[idx]
95
+ finish_query(data_result, query, multiplex)
96
+ # Get the Query::Result, not the Hash
97
+ results[idx] = query.result
98
+ end
99
+
100
+ results
101
+ rescue Exception
102
+ # TODO rescue at a higher level so it will catch errors in analysis, too
103
+ # Assign values here so that the query's `@executed` becomes true
104
+ queries.map { |q| q.result_values ||= {} }
105
+ raise
72
106
  end
73
107
  end
74
108
  end
@@ -81,7 +115,6 @@ module GraphQL
81
115
  NO_OPERATION
82
116
  else
83
117
  begin
84
- # These were checked to be the same in `#supports_multiplexing?`
85
118
  query.schema.query_execution_strategy.begin_query(query, multiplex)
86
119
  rescue GraphQL::ExecutionError => err
87
120
  query.context.errors << err
@@ -94,40 +127,6 @@ module GraphQL
94
127
 
95
128
  private
96
129
 
97
- def run_as_multiplex(multiplex)
98
-
99
- multiplex.schema.query_execution_strategy.begin_multiplex(multiplex)
100
- queries = multiplex.queries
101
- # Do as much eager evaluation of the query as possible
102
- results = []
103
- queries.each_with_index do |query, idx|
104
- multiplex.dataloader.append_job { begin_query(results, idx, query, multiplex) }
105
- end
106
-
107
- multiplex.dataloader.run
108
-
109
- # Then, work through lazy results in a breadth-first way
110
- multiplex.dataloader.append_job {
111
- multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
112
- }
113
- multiplex.dataloader.run
114
-
115
- # Then, find all errors and assign the result to the query object
116
- results.each_with_index do |data_result, idx|
117
- query = queries[idx]
118
- finish_query(data_result, query, multiplex)
119
- # Get the Query::Result, not the Hash
120
- results[idx] = query.result
121
- end
122
-
123
- results
124
- rescue Exception
125
- # TODO rescue at a higher level so it will catch errors in analysis, too
126
- # Assign values here so that the query's `@executed` becomes true
127
- queries.map { |q| q.result_values ||= {} }
128
- raise
129
- end
130
-
131
130
  # @param data_result [Hash] The result for the "data" key, if any
132
131
  # @param query [GraphQL::Query] The query which was run
133
132
  # @return [Hash] final result of this query, including all values and errors
@@ -155,62 +154,6 @@ module GraphQL
155
154
  query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
156
155
  end
157
156
  end
158
-
159
- # use the old `query_execution_strategy` etc to run this query
160
- def run_one_legacy(schema, query)
161
- GraphQL::Deprecation.warn "Multiplex.run_one_legacy will be removed from GraphQL-Ruby 2.0, upgrade to the Interpreter to avoid this deprecated codepath: https://graphql-ruby.org/queries/interpreter.html"
162
-
163
- query.result_values = if !query.valid?
164
- all_errors = query.validation_errors + query.analysis_errors + query.context.errors
165
- if all_errors.any?
166
- { "errors" => all_errors.map(&:to_h) }
167
- else
168
- nil
169
- end
170
- else
171
- GraphQL::Query::Executor.new(query).result
172
- end
173
- end
174
-
175
- DEFAULT_STRATEGIES = [
176
- GraphQL::Execution::Execute,
177
- GraphQL::Execution::Interpreter
178
- ]
179
- # @return [Boolean] True if the schema is only using one strategy, and it's one that supports multiplexing.
180
- def supports_multiplexing?(schema)
181
- schema_strategies = [schema.query_execution_strategy, schema.mutation_execution_strategy, schema.subscription_execution_strategy]
182
- schema_strategies.uniq!
183
- schema_strategies.size == 1 && DEFAULT_STRATEGIES.include?(schema_strategies.first)
184
- end
185
-
186
- # Apply multiplex & query instrumentation to `queries`.
187
- #
188
- # It yields when the queries should be executed, then runs teardown.
189
- def instrument_and_analyze(multiplex)
190
- GraphQL::Execution::Instrumentation.apply_instrumenters(multiplex) do
191
- schema = multiplex.schema
192
- if schema.interpreter? && schema.analysis_engine != GraphQL::Analysis::AST
193
- raise <<-ERR
194
- Can't use `GraphQL::Execution::Interpreter` without `GraphQL::Analysis::AST`, please add this plugin to your schema:
195
-
196
- use GraphQL::Analysis::AST
197
-
198
- For information about the new analysis engine: https://graphql-ruby.org/queries/ast_analysis.html
199
- ERR
200
- end
201
- multiplex_analyzers = schema.multiplex_analyzers
202
- if multiplex.max_complexity
203
- multiplex_analyzers += if schema.using_ast_analysis?
204
- [GraphQL::Analysis::AST::MaxQueryComplexity]
205
- else
206
- [GraphQL::Analysis::MaxQueryComplexity.new(multiplex.max_complexity)]
207
- end
208
- end
209
-
210
- schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
211
- yield
212
- end
213
- end
214
157
  end
215
158
  end
216
159
  end
@@ -1,11 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/execution/directive_checks"
3
- require "graphql/execution/execute"
4
- require "graphql/execution/flatten"
5
3
  require "graphql/execution/instrumentation"
6
4
  require "graphql/execution/interpreter"
7
5
  require "graphql/execution/lazy"
8
6
  require "graphql/execution/lookahead"
9
7
  require "graphql/execution/multiplex"
10
- require "graphql/execution/typecast"
11
8
  require "graphql/execution/errors"
9
+
10
+ module GraphQL
11
+ module Execution
12
+ # @api private
13
+ class Skip < GraphQL::Error; end
14
+
15
+ # Just a singleton for implementing {Query::Context#skip}
16
+ # @api private
17
+ SKIP = Skip.new
18
+ end
19
+ end