graphql 1.2.6 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +3 -1
  3. data/lib/graphql/analysis.rb +1 -0
  4. data/lib/graphql/analysis/analyze_query.rb +1 -0
  5. data/lib/graphql/analysis/field_usage.rb +1 -0
  6. data/lib/graphql/analysis/max_query_complexity.rb +1 -0
  7. data/lib/graphql/analysis/max_query_depth.rb +1 -0
  8. data/lib/graphql/analysis/query_complexity.rb +1 -0
  9. data/lib/graphql/analysis/query_depth.rb +1 -0
  10. data/lib/graphql/analysis/reducer_state.rb +1 -0
  11. data/lib/graphql/analysis_error.rb +1 -0
  12. data/lib/graphql/argument.rb +1 -0
  13. data/lib/graphql/base_type.rb +16 -7
  14. data/lib/graphql/boolean_type.rb +1 -0
  15. data/lib/graphql/compatibility.rb +2 -0
  16. data/lib/graphql/compatibility/execution_specification.rb +113 -192
  17. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +53 -0
  18. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +195 -0
  19. data/lib/graphql/compatibility/lazy_execution_specification.rb +186 -0
  20. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +97 -0
  21. data/lib/graphql/compatibility/query_parser_specification.rb +1 -0
  22. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +1 -0
  23. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +1 -0
  24. data/lib/graphql/compatibility/schema_parser_specification.rb +1 -0
  25. data/lib/graphql/define.rb +1 -0
  26. data/lib/graphql/define/assign_argument.rb +1 -0
  27. data/lib/graphql/define/assign_connection.rb +1 -0
  28. data/lib/graphql/define/assign_enum_value.rb +1 -0
  29. data/lib/graphql/define/assign_global_id_field.rb +1 -0
  30. data/lib/graphql/define/assign_object_field.rb +1 -0
  31. data/lib/graphql/define/defined_object_proxy.rb +1 -0
  32. data/lib/graphql/define/instance_definable.rb +11 -12
  33. data/lib/graphql/define/non_null_with_bang.rb +1 -0
  34. data/lib/graphql/define/type_definer.rb +1 -0
  35. data/lib/graphql/directive.rb +1 -0
  36. data/lib/graphql/directive/deprecated_directive.rb +1 -0
  37. data/lib/graphql/directive/include_directive.rb +1 -0
  38. data/lib/graphql/directive/skip_directive.rb +1 -0
  39. data/lib/graphql/enum_type.rb +8 -1
  40. data/lib/graphql/execution.rb +5 -0
  41. data/lib/graphql/execution/directive_checks.rb +1 -0
  42. data/lib/graphql/execution/execute.rb +222 -0
  43. data/lib/graphql/execution/field_result.rb +52 -0
  44. data/lib/graphql/execution/lazy.rb +59 -0
  45. data/lib/graphql/execution/lazy/lazy_method_map.rb +38 -0
  46. data/lib/graphql/execution/lazy/resolve.rb +68 -0
  47. data/lib/graphql/execution/selection_result.rb +84 -0
  48. data/lib/graphql/execution/typecast.rb +4 -4
  49. data/lib/graphql/execution_error.rb +1 -0
  50. data/lib/graphql/field.rb +68 -18
  51. data/lib/graphql/field/resolve.rb +1 -0
  52. data/lib/graphql/float_type.rb +1 -0
  53. data/lib/graphql/id_type.rb +1 -0
  54. data/lib/graphql/input_object_type.rb +6 -0
  55. data/lib/graphql/int_type.rb +1 -0
  56. data/lib/graphql/interface_type.rb +6 -0
  57. data/lib/graphql/internal_representation.rb +2 -1
  58. data/lib/graphql/internal_representation/node.rb +2 -1
  59. data/lib/graphql/internal_representation/rewrite.rb +1 -0
  60. data/lib/graphql/internal_representation/selection.rb +85 -0
  61. data/lib/graphql/introspection.rb +1 -0
  62. data/lib/graphql/introspection/arguments_field.rb +1 -0
  63. data/lib/graphql/introspection/directive_location_enum.rb +1 -0
  64. data/lib/graphql/introspection/directive_type.rb +1 -0
  65. data/lib/graphql/introspection/enum_value_type.rb +1 -0
  66. data/lib/graphql/introspection/enum_values_field.rb +1 -0
  67. data/lib/graphql/introspection/field_type.rb +1 -0
  68. data/lib/graphql/introspection/fields_field.rb +1 -0
  69. data/lib/graphql/introspection/input_fields_field.rb +1 -0
  70. data/lib/graphql/introspection/input_value_type.rb +2 -1
  71. data/lib/graphql/introspection/interfaces_field.rb +1 -0
  72. data/lib/graphql/introspection/introspection_query.rb +1 -0
  73. data/lib/graphql/introspection/of_type_field.rb +1 -0
  74. data/lib/graphql/introspection/possible_types_field.rb +1 -0
  75. data/lib/graphql/introspection/schema_field.rb +1 -0
  76. data/lib/graphql/introspection/schema_type.rb +1 -0
  77. data/lib/graphql/introspection/type_by_name_field.rb +1 -0
  78. data/lib/graphql/introspection/type_kind_enum.rb +1 -0
  79. data/lib/graphql/introspection/type_type.rb +1 -0
  80. data/lib/graphql/introspection/typename_field.rb +1 -0
  81. data/lib/graphql/invalid_null_error.rb +17 -7
  82. data/lib/graphql/language.rb +10 -0
  83. data/lib/graphql/language/comments.rb +2 -1
  84. data/lib/graphql/language/definition_slice.rb +1 -0
  85. data/lib/graphql/language/generation.rb +25 -24
  86. data/lib/graphql/language/nodes.rb +1 -0
  87. data/lib/graphql/language/token.rb +1 -0
  88. data/lib/graphql/language/visitor.rb +1 -0
  89. data/lib/graphql/list_type.rb +1 -0
  90. data/lib/graphql/non_null_type.rb +2 -1
  91. data/lib/graphql/object_type.rb +12 -0
  92. data/lib/graphql/query.rb +40 -43
  93. data/lib/graphql/query/arguments.rb +1 -0
  94. data/lib/graphql/query/context.rb +31 -7
  95. data/lib/graphql/query/executor.rb +8 -1
  96. data/lib/graphql/query/input_validation_result.rb +1 -0
  97. data/lib/graphql/query/literal_input.rb +1 -0
  98. data/lib/graphql/query/serial_execution.rb +3 -4
  99. data/lib/graphql/query/serial_execution/field_resolution.rb +15 -10
  100. data/lib/graphql/query/serial_execution/operation_resolution.rb +3 -5
  101. data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -5
  102. data/lib/graphql/query/serial_execution/value_resolution.rb +26 -11
  103. data/lib/graphql/query/variable_validation_error.rb +1 -0
  104. data/lib/graphql/query/variables.rb +1 -0
  105. data/lib/graphql/relay.rb +1 -0
  106. data/lib/graphql/relay/array_connection.rb +3 -2
  107. data/lib/graphql/relay/base_connection.rb +20 -8
  108. data/lib/graphql/relay/connection_field.rb +1 -0
  109. data/lib/graphql/relay/connection_resolve.rb +14 -1
  110. data/lib/graphql/relay/connection_type.rb +1 -0
  111. data/lib/graphql/relay/edge.rb +1 -0
  112. data/lib/graphql/relay/edge_type.rb +1 -0
  113. data/lib/graphql/relay/global_id_resolve.rb +1 -0
  114. data/lib/graphql/relay/mutation.rb +13 -0
  115. data/lib/graphql/relay/node.rb +1 -0
  116. data/lib/graphql/relay/page_info.rb +1 -0
  117. data/lib/graphql/relay/relation_connection.rb +3 -2
  118. data/lib/graphql/runtime_type_error.rb +4 -0
  119. data/lib/graphql/scalar_type.rb +2 -1
  120. data/lib/graphql/schema.rb +116 -26
  121. data/lib/graphql/schema/base_64_encoder.rb +14 -0
  122. data/lib/graphql/schema/build_from_definition.rb +4 -0
  123. data/lib/graphql/schema/catchall_middleware.rb +1 -0
  124. data/lib/graphql/schema/default_type_error.rb +15 -0
  125. data/lib/graphql/schema/instrumented_field_map.rb +1 -0
  126. data/lib/graphql/schema/invalid_type_error.rb +1 -0
  127. data/lib/graphql/schema/loader.rb +5 -1
  128. data/lib/graphql/schema/middleware_chain.rb +1 -0
  129. data/lib/graphql/schema/possible_types.rb +1 -0
  130. data/lib/graphql/schema/printer.rb +3 -2
  131. data/lib/graphql/schema/reduce_types.rb +1 -0
  132. data/lib/graphql/schema/rescue_middleware.rb +3 -2
  133. data/lib/graphql/schema/timeout_middleware.rb +1 -0
  134. data/lib/graphql/schema/type_expression.rb +1 -0
  135. data/lib/graphql/schema/type_map.rb +1 -0
  136. data/lib/graphql/schema/unique_within_type.rb +1 -0
  137. data/lib/graphql/schema/validation.rb +57 -1
  138. data/lib/graphql/schema/warden.rb +1 -0
  139. data/lib/graphql/static_validation.rb +1 -0
  140. data/lib/graphql/static_validation/all_rules.rb +1 -0
  141. data/lib/graphql/static_validation/arguments_validator.rb +1 -0
  142. data/lib/graphql/static_validation/literal_validator.rb +1 -0
  143. data/lib/graphql/static_validation/message.rb +1 -0
  144. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -0
  145. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -0
  146. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -0
  147. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -0
  148. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -0
  149. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -0
  150. data/lib/graphql/static_validation/rules/fields_will_merge.rb +6 -3
  151. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +1 -0
  152. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -0
  153. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +1 -0
  154. data/lib/graphql/static_validation/rules/fragments_are_named.rb +1 -0
  155. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -0
  156. data/lib/graphql/static_validation/rules/fragments_are_used.rb +1 -0
  157. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -0
  158. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -0
  159. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -0
  160. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -0
  161. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -0
  162. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -0
  163. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -0
  164. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -0
  165. data/lib/graphql/static_validation/type_stack.rb +1 -0
  166. data/lib/graphql/static_validation/validation_context.rb +2 -1
  167. data/lib/graphql/static_validation/validator.rb +2 -1
  168. data/lib/graphql/string_type.rb +1 -0
  169. data/lib/graphql/type_kinds.rb +1 -0
  170. data/lib/graphql/union_type.rb +13 -0
  171. data/lib/graphql/unresolved_type_error.rb +26 -5
  172. data/lib/graphql/version.rb +2 -1
  173. data/readme.md +1 -5
  174. data/spec/graphql/analysis/analyze_query_spec.rb +1 -0
  175. data/spec/graphql/analysis/field_usage_spec.rb +1 -0
  176. data/spec/graphql/analysis/max_query_complexity_spec.rb +1 -0
  177. data/spec/graphql/analysis/max_query_depth_spec.rb +1 -0
  178. data/spec/graphql/analysis/query_complexity_spec.rb +1 -0
  179. data/spec/graphql/analysis/query_depth_spec.rb +1 -0
  180. data/spec/graphql/argument_spec.rb +1 -0
  181. data/spec/graphql/base_type_spec.rb +13 -0
  182. data/spec/graphql/boolean_type_spec.rb +1 -0
  183. data/spec/graphql/compatibility/execution_specification_spec.rb +1 -0
  184. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +4 -0
  185. data/spec/graphql/compatibility/query_parser_specification_spec.rb +1 -0
  186. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +1 -0
  187. data/spec/graphql/define/assign_argument_spec.rb +1 -0
  188. data/spec/graphql/define/instance_definable_spec.rb +1 -0
  189. data/spec/graphql/directive_spec.rb +1 -0
  190. data/spec/graphql/enum_type_spec.rb +10 -0
  191. data/spec/graphql/execution/execute_spec.rb +5 -0
  192. data/spec/graphql/execution/lazy_spec.rb +252 -0
  193. data/spec/graphql/execution/typecast_spec.rb +1 -0
  194. data/spec/graphql/execution_error_spec.rb +1 -0
  195. data/spec/graphql/field_spec.rb +17 -0
  196. data/spec/graphql/float_type_spec.rb +1 -0
  197. data/spec/graphql/id_type_spec.rb +1 -0
  198. data/spec/graphql/input_object_type_spec.rb +10 -0
  199. data/spec/graphql/int_type_spec.rb +1 -0
  200. data/spec/graphql/interface_type_spec.rb +10 -0
  201. data/spec/graphql/internal_representation/rewrite_spec.rb +1 -0
  202. data/spec/graphql/introspection/directive_type_spec.rb +1 -0
  203. data/spec/graphql/introspection/input_value_type_spec.rb +1 -0
  204. data/spec/graphql/introspection/introspection_query_spec.rb +1 -0
  205. data/spec/graphql/introspection/schema_type_spec.rb +1 -0
  206. data/spec/graphql/introspection/type_type_spec.rb +1 -0
  207. data/spec/graphql/language/definition_slice_spec.rb +1 -0
  208. data/spec/graphql/language/equality_spec.rb +1 -0
  209. data/spec/graphql/language/generation_spec.rb +1 -0
  210. data/spec/graphql/language/lexer_spec.rb +1 -0
  211. data/spec/graphql/language/nodes_spec.rb +1 -0
  212. data/spec/graphql/language/parser_spec.rb +1 -0
  213. data/spec/graphql/language/visitor_spec.rb +1 -0
  214. data/spec/graphql/list_type_spec.rb +1 -0
  215. data/spec/graphql/non_null_type_spec.rb +17 -0
  216. data/spec/graphql/object_type_spec.rb +19 -0
  217. data/spec/graphql/query/arguments_spec.rb +1 -0
  218. data/spec/graphql/query/context_spec.rb +1 -0
  219. data/spec/graphql/query/executor_spec.rb +1 -0
  220. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -0
  221. data/spec/graphql/query/variables_spec.rb +1 -0
  222. data/spec/graphql/query_spec.rb +25 -0
  223. data/spec/graphql/relay/array_connection_spec.rb +1 -0
  224. data/spec/graphql/relay/base_connection_spec.rb +33 -4
  225. data/spec/graphql/relay/connection_field_spec.rb +1 -0
  226. data/spec/graphql/relay/connection_type_spec.rb +1 -0
  227. data/spec/graphql/relay/mutation_spec.rb +6 -0
  228. data/spec/graphql/relay/node_spec.rb +1 -0
  229. data/spec/graphql/relay/page_info_spec.rb +1 -0
  230. data/spec/graphql/relay/relation_connection_spec.rb +1 -0
  231. data/spec/graphql/scalar_type_spec.rb +1 -0
  232. data/spec/graphql/schema/build_from_definition_spec.rb +9 -1
  233. data/spec/graphql/schema/catchall_middleware_spec.rb +1 -0
  234. data/spec/graphql/schema/loader_spec.rb +7 -0
  235. data/spec/graphql/schema/middleware_chain_spec.rb +1 -0
  236. data/spec/graphql/schema/printer_spec.rb +1 -0
  237. data/spec/graphql/schema/reduce_types_spec.rb +1 -0
  238. data/spec/graphql/schema/rescue_middleware_spec.rb +1 -0
  239. data/spec/graphql/schema/timeout_middleware_spec.rb +1 -0
  240. data/spec/graphql/schema/type_expression_spec.rb +1 -0
  241. data/spec/graphql/schema/unique_within_type_spec.rb +1 -0
  242. data/spec/graphql/schema/validation_spec.rb +55 -0
  243. data/spec/graphql/schema/warden_spec.rb +1 -0
  244. data/spec/graphql/schema_spec.rb +39 -0
  245. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -0
  246. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +1 -0
  247. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -0
  248. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +1 -0
  249. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +1 -0
  250. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -0
  251. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +515 -31
  252. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +1 -0
  253. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +1 -0
  254. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +1 -0
  255. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +1 -0
  256. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +1 -0
  257. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -0
  258. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +1 -0
  259. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +1 -0
  260. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +1 -0
  261. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +1 -0
  262. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +1 -0
  263. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +1 -0
  264. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +1 -0
  265. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +1 -0
  266. data/spec/graphql/static_validation/type_stack_spec.rb +1 -0
  267. data/spec/graphql/static_validation/validator_spec.rb +1 -0
  268. data/spec/graphql/string_type_spec.rb +1 -0
  269. data/spec/graphql/union_type_spec.rb +11 -0
  270. data/spec/spec_helper.rb +1 -0
  271. data/spec/support/dairy_app.rb +1 -0
  272. data/spec/support/dairy_data.rb +1 -0
  273. data/spec/support/minimum_input_object.rb +1 -0
  274. data/spec/support/star_wars_data.rb +1 -0
  275. data/spec/support/star_wars_schema.rb +30 -7
  276. data/spec/support/static_validation_helpers.rb +1 -0
  277. metadata +24 -5
  278. data/lib/graphql/internal_representation/selections.rb +0 -41
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  module Language
3
4
  module Nodes
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  module Language
3
4
  # Emitted by the lexer and passed to the parser.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  module Language
3
4
  # Depth-first traversal through the tree, calling hooks at each stop.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  # A list type modifies another type.
3
4
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  # A non-null type modifies another type.
3
4
  #
@@ -11,7 +12,7 @@ module GraphQL
11
12
  # # or
12
13
  # field :items, ItemType.to_non_null_type
13
14
  #
14
- # (If the application fails to return a value, {InvalidNullError} will be raised.)
15
+ # (If the application fails to return a value, {InvalidNullError} will be passed to {Schema#type_error}.)
15
16
  #
16
17
  # For input types, it says that the incoming value _must_ be provided by the query.
17
18
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  # This type exposes fields on an object.
3
4
  #
@@ -38,6 +39,13 @@ module GraphQL
38
39
  @dirty_interfaces = []
39
40
  end
40
41
 
42
+ def initialize_copy(other)
43
+ super
44
+ @clean_interfaces = nil
45
+ @dirty_interfaces = other.dirty_interfaces.dup
46
+ @fields = other.fields.dup
47
+ end
48
+
41
49
  # @param new_interfaces [Array<GraphQL::Interface>] interfaces that this type implements
42
50
  def interfaces=(new_interfaces)
43
51
  @clean_interfaces = nil
@@ -68,6 +76,10 @@ module GraphQL
68
76
  interface_fields.merge(self.fields).values
69
77
  end
70
78
 
79
+ protected
80
+
81
+ attr_reader :dirty_interfaces
82
+
71
83
  private
72
84
 
73
85
  # Create a {name => defn} hash for fields inherited from interfaces
data/lib/graphql/query.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "graphql/query/arguments"
2
3
  require "graphql/query/context"
3
4
  require "graphql/query/executor"
@@ -25,7 +26,7 @@ module GraphQL
25
26
  end
26
27
  end
27
28
 
28
- attr_reader :schema, :document, :context, :fragments, :operations, :root_value, :max_depth, :query_string, :warden
29
+ attr_reader :schema, :document, :context, :fragments, :operations, :root_value, :max_depth, :query_string, :warden, :provided_variables
29
30
 
30
31
  # Prepare query `query_string` on `schema`
31
32
  # @param schema [GraphQL::Schema]
@@ -82,22 +83,43 @@ module GraphQL
82
83
  # Trying to execute a document
83
84
  # with no operations returns an empty hash
84
85
  @ast_variables = []
86
+ @mutation = false
85
87
  if @operations.any?
86
88
  @selected_operation = find_operation(@operations, @operation_name)
87
89
  if @selected_operation.nil?
88
90
  @validation_errors << GraphQL::Query::OperationNameMissingError.new(@operations.keys)
89
91
  else
90
92
  @ast_variables = @selected_operation.variables
93
+ @mutation = @selected_operation.operation_type == "mutation"
91
94
  end
92
95
  end
96
+ @result = nil
97
+ @executed = false
93
98
  end
94
99
 
95
100
  # Get the result for this query, executing it once
101
+ # @return [Hash] A GraphQL response, with `"data"` and/or `"errors"` keys
96
102
  def result
97
- @result ||= begin
103
+ if @executed
104
+ @result
105
+ else
106
+ @executed = true
98
107
  instrumenters = @schema.instrumenters[:query]
99
- execution_call = ExecutionCall.new(self, instrumenters)
100
- execution_call.call
108
+ begin
109
+ instrumenters.each { |i| i.before_query(self) }
110
+ @result = if !valid?
111
+ all_errors = validation_errors + analysis_errors
112
+ if all_errors.any?
113
+ { "errors" => all_errors.map(&:to_h) }
114
+ else
115
+ nil
116
+ end
117
+ else
118
+ Executor.new(self).result
119
+ end
120
+ ensure
121
+ instrumenters.each { |i| i.after_query(self) }
122
+ end
101
123
  end
102
124
  end
103
125
 
@@ -132,6 +154,14 @@ module GraphQL
132
154
  @internal_representation
133
155
  end
134
156
 
157
+ def irep_selection
158
+ @selection ||= begin
159
+ irep_root = internal_representation[selected_operation.name]
160
+ GraphQL::InternalRepresentation::Selection.new(query: self, nodes: [irep_root])
161
+ end
162
+ end
163
+
164
+
135
165
  # TODO this should probably contain error instances, not hashes
136
166
  # @return [Array<Hash>] Static validation errors for the query string
137
167
  def validation_errors
@@ -171,17 +201,13 @@ module GraphQL
171
201
  @valid
172
202
  end
173
203
 
174
- def selections(nodes, type)
175
- @selections ||= Hash.new { |h, k| h[k] = GraphQL::InternalRepresentation::Selections.build(self, k) }
176
- @selections[nodes][type]
177
- end
178
-
179
204
  def get_type(type_name)
180
205
  @warden.get_type(type_name)
181
206
  end
182
207
 
183
208
  def get_field(type, name)
184
- @warden.get_field(type, name)
209
+ @fields ||= Hash.new { |h, k| h[k] = Hash.new { |h2, k2| h2[k2] = @warden.get_field(k, k2) } }
210
+ @fields[type][name]
185
211
  end
186
212
 
187
213
  def possible_types(type)
@@ -192,6 +218,10 @@ module GraphQL
192
218
  @schema.resolve_type(type, @context)
193
219
  end
194
220
 
221
+ def mutation?
222
+ @mutation
223
+ end
224
+
195
225
  private
196
226
 
197
227
  # Assert that the passed-in query string is internally consistent
@@ -227,38 +257,5 @@ module GraphQL
227
257
  operations[operation_name]
228
258
  end
229
259
  end
230
-
231
- class ExecutionCall
232
- def initialize(query, instrumenters)
233
- @query = query
234
- @instrumenters = instrumenters
235
- end
236
-
237
- # Check if the query is valid, and if it is,
238
- # execute it, calling instrumenters along the way
239
- # @return [Hash] The GraphQL response
240
- def call
241
- @instrumenters.each { |i| i.before_query(@query) }
242
- result = get_result
243
- ensure
244
- @instrumenters.each { |i| i.after_query(@query) }
245
- result
246
- end
247
-
248
- private
249
-
250
- def get_result
251
- if !@query.valid?
252
- all_errors = @query.validation_errors + @query.analysis_errors
253
- if all_errors.any?
254
- { "errors" => all_errors.map(&:to_h) }
255
- else
256
- nil
257
- end
258
- else
259
- Executor.new(@query).result
260
- end
261
- end
262
- end
263
260
  end
264
261
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  # Read-only access to values, normalizing all keys to strings
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  # Expose some query-specific info to field resolve functions.
@@ -59,33 +60,46 @@ module GraphQL
59
60
  @values[key] = value
60
61
  end
61
62
 
62
- def spawn(path:, irep_node:)
63
- FieldResolutionContext.new(context: self, path: path, irep_node: irep_node)
63
+ def spawn(key:, selection:, parent_type:, field:)
64
+ FieldResolutionContext.new(
65
+ context: self,
66
+ path: path + [key],
67
+ selection: selection,
68
+ parent_type: parent_type,
69
+ field: field,
70
+ )
64
71
  end
65
72
 
66
73
  class FieldResolutionContext
67
74
  extend Forwardable
68
75
 
69
- attr_reader :path, :irep_node
76
+ attr_reader :path, :selection, :field, :parent_type
70
77
 
71
- def initialize(context:, path:, irep_node:)
78
+ def initialize(context:, path:, selection:, field:, parent_type:)
72
79
  @context = context
73
80
  @path = path
74
- @irep_node = irep_node
81
+ @selection = selection
82
+ @field = field
83
+ @parent_type = parent_type
75
84
  end
76
85
 
77
86
  def_delegators :@context, :[], :[]=, :spawn, :query, :schema, :warden, :errors, :execution_strategy, :strategy
78
87
 
79
88
  # @return [GraphQL::Language::Nodes::Field] The AST node for the currently-executing field
80
89
  def ast_node
81
- @irep_node.ast_node
90
+ selection.irep_node.ast_node
91
+ end
92
+
93
+ # @return [GraphQL::InternalRepresentation::Node]
94
+ def irep_node
95
+ selection.irep_node
82
96
  end
83
97
 
84
98
  # Add error to current field resolution.
85
99
  # @param error [GraphQL::ExecutionError] an execution error
86
100
  # @return [void]
87
101
  def add_error(error)
88
- unless error.is_a?(ExecutionError)
102
+ if !error.is_a?(ExecutionError)
89
103
  raise TypeError, "expected error to be a ExecutionError, but was #{error.class}"
90
104
  end
91
105
 
@@ -94,6 +108,16 @@ module GraphQL
94
108
  errors << error
95
109
  nil
96
110
  end
111
+
112
+ def spawn(key:, selection:, parent_type:, field:)
113
+ FieldResolutionContext.new(
114
+ context: @context,
115
+ path: path + [key],
116
+ selection: selection,
117
+ parent_type: parent_type,
118
+ field: field,
119
+ )
120
+ end
97
121
  end
98
122
  end
99
123
  end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class Executor
5
+ class PropagateNull < StandardError; end
6
+
4
7
  # @return [GraphQL::Query] the query being executed
5
8
  attr_reader :query
6
9
 
@@ -30,7 +33,11 @@ module GraphQL
30
33
  execution_strategy = execution_strategy_class.new
31
34
 
32
35
  query.context.execution_strategy = execution_strategy
33
- data_result = execution_strategy.execute(operation, root_type, query)
36
+ data_result = begin
37
+ execution_strategy.execute(operation, root_type, query)
38
+ rescue PropagateNull
39
+ nil
40
+ end
34
41
  result = { "data" => data_result }
35
42
  error_result = query.context.errors.map(&:to_h)
36
43
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class InputValidationResult
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  # Turn query string values into something useful for query execution
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "graphql/query/serial_execution/value_resolution"
2
3
  require "graphql/query/serial_execution/field_resolution"
3
4
  require "graphql/query/serial_execution/operation_resolution"
@@ -12,13 +13,11 @@ module GraphQL
12
13
  #
13
14
  # @param ast_operation [GraphQL::Language::Nodes::OperationDefinition] The operation definition to run
14
15
  # @param root_type [GraphQL::ObjectType] either the query type or the mutation type
15
- # @param query_obj [GraphQL::Query] the query object for this execution
16
+ # @param query_object [GraphQL::Query] the query object for this execution
16
17
  # @return [Hash] a spec-compliant GraphQL result, as a hash
17
18
  def execute(ast_operation, root_type, query_object)
18
- irep_root = query_object.internal_representation[ast_operation.name]
19
-
20
19
  operation_resolution.resolve(
21
- irep_root,
20
+ query_object.irep_selection,
22
21
  root_type,
23
22
  query_object
24
23
  )
@@ -1,17 +1,23 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class SerialExecution
4
5
  class FieldResolution
5
6
  attr_reader :irep_node, :parent_type, :target, :field, :arguments, :query
6
7
 
7
- def initialize(irep_nodes, parent_type, target, query_ctx)
8
- @irep_node = irep_nodes.first
9
- @irep_nodes = irep_nodes
8
+ def initialize(selection, parent_type, target, query_ctx)
9
+ @irep_node = selection.irep_node
10
+ @selection = selection
10
11
  @parent_type = parent_type
11
12
  @target = target
12
- @field_ctx = query_ctx.spawn(path: query_ctx.path + [irep_node.name], irep_node: irep_node)
13
13
  @query = query_ctx.query
14
14
  @field = @query.get_field(parent_type, irep_node.definition_name)
15
+ @field_ctx = query_ctx.spawn(
16
+ key: irep_node.name,
17
+ selection: selection,
18
+ parent_type: parent_type,
19
+ field: field,
20
+ )
15
21
  @arguments = @query.arguments_for(irep_node, @field)
16
22
  end
17
23
 
@@ -33,14 +39,14 @@ module GraphQL
33
39
  def get_finished_value(raw_value)
34
40
  case raw_value
35
41
  when GraphQL::ExecutionError
36
- raw_value.ast_node = irep_node.ast_node
42
+ raw_value.ast_node = @field_ctx.ast_node
37
43
  raw_value.path = @field_ctx.path
38
44
  @query.context.errors.push(raw_value)
39
45
  when Array
40
46
  list_errors = raw_value.each_with_index.select { |value, _| value.is_a?(GraphQL::ExecutionError) }
41
47
  if list_errors.any?
42
48
  list_errors.each do |error, index|
43
- error.ast_node = irep_node.ast_node
49
+ error.ast_node = @field_ctx.ast_node
44
50
  error.path = @field_ctx.path + [index]
45
51
  @query.context.errors.push(error)
46
52
  end
@@ -53,14 +59,13 @@ module GraphQL
53
59
  field,
54
60
  field.type,
55
61
  raw_value,
56
- @irep_nodes,
62
+ @selection,
57
63
  @field_ctx,
58
64
  )
59
- rescue GraphQL::InvalidNullError => err
65
+ rescue GraphQL::Query::Executor::PropagateNull
60
66
  if field.type.kind.non_null?
61
- raise(err)
67
+ raise
62
68
  else
63
- err.parent_error? || @query.context.errors.push(err)
64
69
  nil
65
70
  end
66
71
  end
@@ -1,19 +1,17 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class SerialExecution
4
5
  module OperationResolution
5
- def self.resolve(irep_node, target, query)
6
+ def self.resolve(selection, target, query)
6
7
  result = query.context.execution_strategy.selection_resolution.resolve(
7
8
  query.root_value,
8
9
  target,
9
- [irep_node],
10
+ selection,
10
11
  query.context,
11
12
  )
12
13
 
13
14
  result
14
- rescue GraphQL::InvalidNullError => err
15
- err.parent_error? || query.context.errors.push(err)
16
- nil
17
15
  end
18
16
  end
19
17
  end
@@ -1,15 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class SerialExecution
4
5
  module SelectionResolution
5
- def self.resolve(target, current_type, irep_nodes, query_ctx)
6
- own_selections = query_ctx.query.selections(irep_nodes, current_type)
7
-
6
+ def self.resolve(target, current_type, selection, query_ctx)
8
7
  selection_result = {}
9
8
 
10
- own_selections.each do |name, child_irep_nodes|
9
+ selection.each_selection(type: current_type) do |name, subselection|
11
10
  selection_result.merge!(query_ctx.execution_strategy.field_resolution.new(
12
- child_irep_nodes,
11
+ subselection,
13
12
  current_type,
14
13
  target,
15
14
  query_ctx