graphql 2.6.9 → 2.6.14

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 (382) hide show
  1. checksums.yaml +4 -4
  2. data/.rdoc_options +4 -0
  3. data/lib/generators/graphql/core.rb +1 -0
  4. data/lib/generators/graphql/detailed_trace_generator.rb +1 -0
  5. data/lib/generators/graphql/enum_generator.rb +1 -0
  6. data/lib/generators/graphql/field_extractor.rb +1 -0
  7. data/lib/generators/graphql/input_generator.rb +1 -0
  8. data/lib/generators/graphql/install/mutation_root_generator.rb +1 -0
  9. data/lib/generators/graphql/install_generator.rb +1 -0
  10. data/lib/generators/graphql/interface_generator.rb +1 -0
  11. data/lib/generators/graphql/loader_generator.rb +8 -2
  12. data/lib/generators/graphql/mutation_create_generator.rb +8 -2
  13. data/lib/generators/graphql/mutation_delete_generator.rb +8 -2
  14. data/lib/generators/graphql/mutation_generator.rb +8 -2
  15. data/lib/generators/graphql/mutation_update_generator.rb +8 -2
  16. data/lib/generators/graphql/object_generator.rb +1 -0
  17. data/lib/generators/graphql/orm_mutations_base.rb +8 -2
  18. data/lib/generators/graphql/relay.rb +1 -0
  19. data/lib/generators/graphql/relay_generator.rb +1 -0
  20. data/lib/generators/graphql/scalar_generator.rb +1 -0
  21. data/lib/generators/graphql/type_generator.rb +38 -8
  22. data/lib/generators/graphql/union_generator.rb +1 -0
  23. data/lib/graphql/analysis/analyzer.rb +35 -9
  24. data/lib/graphql/analysis/field_usage.rb +1 -0
  25. data/lib/graphql/analysis/max_query_complexity.rb +3 -2
  26. data/lib/graphql/analysis/max_query_depth.rb +1 -0
  27. data/lib/graphql/analysis/query_complexity.rb +57 -20
  28. data/lib/graphql/analysis/query_depth.rb +17 -12
  29. data/lib/graphql/analysis/visitor.rb +79 -16
  30. data/lib/graphql/analysis.rb +23 -6
  31. data/lib/graphql/analysis_error.rb +1 -0
  32. data/lib/graphql/autoload.rb +30 -7
  33. data/lib/graphql/backtrace/table.rb +21 -5
  34. data/lib/graphql/backtrace/traced_error.rb +8 -3
  35. data/lib/graphql/backtrace.rb +14 -9
  36. data/lib/graphql/coercion_error.rb +1 -0
  37. data/lib/graphql/current.rb +44 -19
  38. data/lib/graphql/dashboard/application_controller.rb +1 -0
  39. data/lib/graphql/dashboard/detailed_traces.rb +1 -0
  40. data/lib/graphql/dashboard/installable.rb +1 -0
  41. data/lib/graphql/dashboard/landings_controller.rb +1 -0
  42. data/lib/graphql/dashboard/limiters.rb +1 -0
  43. data/lib/graphql/dashboard/operation_store.rb +1 -0
  44. data/lib/graphql/dashboard/statics_controller.rb +1 -0
  45. data/lib/graphql/dashboard/subscriptions.rb +1 -0
  46. data/lib/graphql/dashboard.rb +36 -22
  47. data/lib/graphql/dataloader/active_record_association_source.rb +1 -0
  48. data/lib/graphql/dataloader/active_record_source.rb +1 -0
  49. data/lib/graphql/dataloader/async_dataloader.rb +45 -16
  50. data/lib/graphql/dataloader/null_dataloader.rb +4 -3
  51. data/lib/graphql/dataloader/request.rb +8 -2
  52. data/lib/graphql/dataloader/request_all.rb +8 -2
  53. data/lib/graphql/dataloader/source.rb +127 -35
  54. data/lib/graphql/dataloader.rb +98 -44
  55. data/lib/graphql/date_encoding_error.rb +2 -1
  56. data/lib/graphql/dig.rb +12 -3
  57. data/lib/graphql/duration_encoding_error.rb +2 -1
  58. data/lib/graphql/execution/directive_checks.rb +8 -3
  59. data/lib/graphql/execution/errors.rb +20 -6
  60. data/lib/graphql/execution/field_resolve_step.rb +288 -168
  61. data/lib/graphql/execution/finalize.rb +12 -6
  62. data/lib/graphql/execution/input_values.rb +5 -2
  63. data/lib/graphql/execution/interpreter/argument_value.rb +17 -5
  64. data/lib/graphql/execution/interpreter/arguments.rb +24 -9
  65. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -1
  66. data/lib/graphql/execution/interpreter/execution_errors.rb +1 -0
  67. data/lib/graphql/execution/interpreter/handles_raw_value.rb +1 -0
  68. data/lib/graphql/execution/interpreter/resolve.rb +18 -8
  69. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +4 -1
  70. data/lib/graphql/execution/interpreter/runtime.rb +72 -25
  71. data/lib/graphql/execution/interpreter.rb +18 -7
  72. data/lib/graphql/execution/lazy/lazy_method_map.rb +21 -8
  73. data/lib/graphql/execution/lazy.rb +34 -10
  74. data/lib/graphql/execution/load_argument_step.rb +1 -0
  75. data/lib/graphql/execution/lookahead.rb +137 -54
  76. data/lib/graphql/execution/multiplex.rb +4 -4
  77. data/lib/graphql/execution/next.rb +7 -0
  78. data/lib/graphql/execution/prepare_object_step.rb +38 -13
  79. data/lib/graphql/execution/resolve_type_step.rb +2 -1
  80. data/lib/graphql/execution/runner.rb +32 -15
  81. data/lib/graphql/execution/selections_step.rb +3 -2
  82. data/lib/graphql/execution.rb +2 -2
  83. data/lib/graphql/execution_error.rb +19 -10
  84. data/lib/graphql/float_decoding_error.rb +14 -0
  85. data/lib/graphql/float_encoding_error.rb +33 -0
  86. data/lib/graphql/integer_decoding_error.rb +2 -1
  87. data/lib/graphql/integer_encoding_error.rb +8 -3
  88. data/lib/graphql/introspection/base_object.rb +3 -1
  89. data/lib/graphql/introspection/directive_location_enum.rb +1 -0
  90. data/lib/graphql/introspection/directive_type.rb +1 -0
  91. data/lib/graphql/introspection/dynamic_fields.rb +1 -0
  92. data/lib/graphql/introspection/entry_points.rb +1 -0
  93. data/lib/graphql/introspection/enum_value_type.rb +1 -0
  94. data/lib/graphql/introspection/field_type.rb +1 -0
  95. data/lib/graphql/introspection/input_value_type.rb +1 -0
  96. data/lib/graphql/introspection/introspection_query.rb +1 -0
  97. data/lib/graphql/introspection/schema_type.rb +1 -0
  98. data/lib/graphql/introspection/type_kind_enum.rb +1 -0
  99. data/lib/graphql/introspection/type_type.rb +1 -0
  100. data/lib/graphql/introspection.rb +1 -0
  101. data/lib/graphql/invalid_name_error.rb +1 -0
  102. data/lib/graphql/invalid_null_error.rb +19 -6
  103. data/lib/graphql/language/block_string.rb +2 -1
  104. data/lib/graphql/language/cache.rb +10 -4
  105. data/lib/graphql/language/comment.rb +1 -0
  106. data/lib/graphql/language/definition_slice.rb +1 -0
  107. data/lib/graphql/language/document_from_schema_definition.rb +9 -10
  108. data/lib/graphql/language/generation.rb +23 -9
  109. data/lib/graphql/language/lexer.rb +16 -8
  110. data/lib/graphql/language/nodes.rb +2094 -419
  111. data/lib/graphql/language/parser.rb +29 -18
  112. data/lib/graphql/language/printer.rb +31 -16
  113. data/lib/graphql/language/sanitized_printer.rb +16 -5
  114. data/lib/graphql/language/static_visitor.rb +19 -4
  115. data/lib/graphql/language/visitor.rb +51 -29
  116. data/lib/graphql/language.rb +15 -9
  117. data/lib/graphql/load_application_object_failed_error.rb +14 -5
  118. data/lib/graphql/name_validator.rb +1 -0
  119. data/lib/graphql/pagination/active_record_relation_connection.rb +1 -0
  120. data/lib/graphql/pagination/array_connection.rb +24 -6
  121. data/lib/graphql/pagination/connection.rb +178 -48
  122. data/lib/graphql/pagination/connections.rb +21 -14
  123. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -0
  124. data/lib/graphql/pagination/relation_connection.rb +164 -27
  125. data/lib/graphql/pagination/sequel_dataset_connection.rb +1 -0
  126. data/lib/graphql/pagination.rb +1 -0
  127. data/lib/graphql/parse_error.rb +1 -0
  128. data/lib/graphql/query/context/scoped_context.rb +2 -1
  129. data/lib/graphql/query/context.rb +106 -35
  130. data/lib/graphql/query/fingerprint.rb +15 -7
  131. data/lib/graphql/query/input_validation_result.rb +1 -0
  132. data/lib/graphql/query/null_context.rb +1 -0
  133. data/lib/graphql/query/partial.rb +28 -16
  134. data/lib/graphql/query/result.rb +15 -5
  135. data/lib/graphql/query/validation_pipeline.rb +16 -6
  136. data/lib/graphql/query/variable_validation_error.rb +17 -1
  137. data/lib/graphql/query/variables.rb +9 -2
  138. data/lib/graphql/query.rb +195 -50
  139. data/lib/graphql/railtie.rb +7 -3
  140. data/lib/graphql/rake_task/validate.rb +72 -17
  141. data/lib/graphql/rake_task.rb +55 -23
  142. data/lib/graphql/relay/range_add.rb +32 -21
  143. data/lib/graphql/relay.rb +1 -0
  144. data/lib/graphql/rubocop/graphql/base_cop.rb +1 -0
  145. data/lib/graphql/rubocop/graphql/default_null_true.rb +9 -6
  146. data/lib/graphql/rubocop/graphql/default_required_true.rb +9 -6
  147. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +12 -8
  148. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +9 -5
  149. data/lib/graphql/rubocop.rb +1 -0
  150. data/lib/graphql/runtime_error.rb +1 -0
  151. data/lib/graphql/runtime_type_error.rb +1 -0
  152. data/lib/graphql/schema/addition.rb +69 -50
  153. data/lib/graphql/schema/always_visible.rb +1 -0
  154. data/lib/graphql/schema/argument.rb +279 -45
  155. data/lib/graphql/schema/base_64_encoder.rb +2 -2
  156. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -0
  157. data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
  158. data/lib/graphql/schema/build_from_definition.rb +507 -178
  159. data/lib/graphql/schema/built_in_types.rb +1 -0
  160. data/lib/graphql/schema/directive/deprecated.rb +1 -0
  161. data/lib/graphql/schema/directive/feature.rb +39 -22
  162. data/lib/graphql/schema/directive/flagged.rb +6 -1
  163. data/lib/graphql/schema/directive/include.rb +1 -0
  164. data/lib/graphql/schema/directive/one_of.rb +1 -0
  165. data/lib/graphql/schema/directive/skip.rb +1 -0
  166. data/lib/graphql/schema/directive/specified_by.rb +1 -0
  167. data/lib/graphql/schema/directive/transform.rb +17 -8
  168. data/lib/graphql/schema/directive.rb +33 -7
  169. data/lib/graphql/schema/enum.rb +99 -38
  170. data/lib/graphql/schema/enum_value.rb +21 -13
  171. data/lib/graphql/schema/field/connection_extension.rb +10 -2
  172. data/lib/graphql/schema/field/scope_extension.rb +1 -0
  173. data/lib/graphql/schema/field.rb +622 -110
  174. data/lib/graphql/schema/field_extension.rb +89 -34
  175. data/lib/graphql/schema/find_inherited_value.rb +5 -3
  176. data/lib/graphql/schema/finder.rb +22 -8
  177. data/lib/graphql/schema/has_single_input_argument.rb +39 -6
  178. data/lib/graphql/schema/input_object.rb +40 -13
  179. data/lib/graphql/schema/interface.rb +33 -17
  180. data/lib/graphql/schema/introspection_system.rb +7 -3
  181. data/lib/graphql/schema/late_bound_type.rb +2 -2
  182. data/lib/graphql/schema/list.rb +15 -4
  183. data/lib/graphql/schema/loader.rb +23 -12
  184. data/lib/graphql/schema/member/base_dsl_methods.rb +58 -12
  185. data/lib/graphql/schema/member/build_type.rb +21 -7
  186. data/lib/graphql/schema/member/graphql_type_names.rb +10 -6
  187. data/lib/graphql/schema/member/has_arguments.rb +112 -49
  188. data/lib/graphql/schema/member/has_ast_node.rb +1 -0
  189. data/lib/graphql/schema/member/has_authorization.rb +5 -0
  190. data/lib/graphql/schema/member/has_dataloader.rb +91 -34
  191. data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -2
  192. data/lib/graphql/schema/member/has_directives.rb +45 -11
  193. data/lib/graphql/schema/member/has_fields.rb +151 -70
  194. data/lib/graphql/schema/member/has_interfaces.rb +8 -2
  195. data/lib/graphql/schema/member/has_path.rb +14 -5
  196. data/lib/graphql/schema/member/has_unresolved_type_error.rb +1 -0
  197. data/lib/graphql/schema/member/has_validators.rb +19 -4
  198. data/lib/graphql/schema/member/relay_shortcuts.rb +10 -2
  199. data/lib/graphql/schema/member/scoped.rb +14 -3
  200. data/lib/graphql/schema/member/type_system_helpers.rb +36 -6
  201. data/lib/graphql/schema/member/validates_input.rb +1 -0
  202. data/lib/graphql/schema/member.rb +9 -2
  203. data/lib/graphql/schema/mutation.rb +50 -46
  204. data/lib/graphql/schema/non_null.rb +21 -5
  205. data/lib/graphql/schema/object.rb +44 -15
  206. data/lib/graphql/schema/printer.rb +52 -31
  207. data/lib/graphql/schema/ractor_shareable.rb +6 -2
  208. data/lib/graphql/schema/relay_classic_mutation.rb +3 -3
  209. data/lib/graphql/schema/resolver/has_payload_type.rb +29 -7
  210. data/lib/graphql/schema/resolver.rb +156 -45
  211. data/lib/graphql/schema/scalar.rb +1 -0
  212. data/lib/graphql/schema/subscription.rb +67 -28
  213. data/lib/graphql/schema/timeout.rb +65 -25
  214. data/lib/graphql/schema/type_expression.rb +14 -5
  215. data/lib/graphql/schema/type_membership.rb +29 -10
  216. data/lib/graphql/schema/union.rb +4 -2
  217. data/lib/graphql/schema/unique_within_type.rb +24 -5
  218. data/lib/graphql/schema/validator/all_validator.rb +17 -9
  219. data/lib/graphql/schema/validator/allow_blank_validator.rb +8 -2
  220. data/lib/graphql/schema/validator/allow_null_validator.rb +8 -2
  221. data/lib/graphql/schema/validator/exclusion_validator.rb +14 -5
  222. data/lib/graphql/schema/validator/format_validator.rb +21 -10
  223. data/lib/graphql/schema/validator/inclusion_validator.rb +15 -6
  224. data/lib/graphql/schema/validator/length_validator.rb +23 -12
  225. data/lib/graphql/schema/validator/numericality_validator.rb +29 -16
  226. data/lib/graphql/schema/validator/required_validator.rb +45 -31
  227. data/lib/graphql/schema/validator.rb +89 -25
  228. data/lib/graphql/schema/visibility/migration.rb +14 -7
  229. data/lib/graphql/schema/visibility/profile.rb +73 -19
  230. data/lib/graphql/schema/visibility/visit.rb +12 -10
  231. data/lib/graphql/schema/visibility.rb +24 -20
  232. data/lib/graphql/schema/warden.rb +117 -31
  233. data/lib/graphql/schema/wrapper.rb +4 -1
  234. data/lib/graphql/schema.rb +1052 -304
  235. data/lib/graphql/static_validation/all_rules.rb +2 -1
  236. data/lib/graphql/static_validation/base_visitor.rb +59 -9
  237. data/lib/graphql/static_validation/definition_dependencies.rb +27 -7
  238. data/lib/graphql/static_validation/error.rb +3 -0
  239. data/lib/graphql/static_validation/interpreter_visitor.rb +1 -0
  240. data/lib/graphql/static_validation/literal_validator.rb +1 -0
  241. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -0
  242. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +1 -0
  243. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +3 -0
  244. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +1 -0
  245. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -0
  246. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +1 -0
  247. data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -0
  248. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +1 -0
  249. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +3 -0
  250. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +1 -0
  251. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +3 -0
  252. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +1 -0
  253. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +9 -1
  254. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +1 -0
  255. data/lib/graphql/static_validation/rules/fields_will_merge.rb +355 -157
  256. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +14 -2
  257. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +3 -0
  258. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +1 -0
  259. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -0
  260. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +1 -0
  261. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +3 -0
  262. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +1 -0
  263. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +3 -0
  264. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +1 -0
  265. data/lib/graphql/static_validation/rules/fragments_are_named.rb +3 -0
  266. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +1 -0
  267. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +3 -0
  268. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +1 -0
  269. data/lib/graphql/static_validation/rules/fragments_are_used.rb +3 -0
  270. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +1 -0
  271. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +3 -0
  272. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +1 -0
  273. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +3 -0
  274. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +1 -0
  275. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +3 -0
  276. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +1 -0
  277. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +1 -0
  278. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +4 -0
  279. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +1 -0
  280. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +3 -0
  281. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +1 -0
  282. data/lib/graphql/static_validation/rules/query_root_exists.rb +3 -0
  283. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +1 -0
  284. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -1
  285. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +1 -0
  286. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -0
  287. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +1 -0
  288. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +43 -5
  289. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +1 -0
  290. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +3 -0
  291. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +1 -0
  292. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -0
  293. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +1 -0
  294. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +3 -0
  295. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +1 -0
  296. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +207 -51
  297. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +1 -0
  298. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +3 -0
  299. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +1 -0
  300. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +6 -3
  301. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +1 -0
  302. data/lib/graphql/static_validation/validation_context.rb +3 -2
  303. data/lib/graphql/static_validation/validation_timeout_error.rb +1 -0
  304. data/lib/graphql/static_validation/validator.rb +41 -16
  305. data/lib/graphql/static_validation.rb +1 -0
  306. data/lib/graphql/string_encoding_error.rb +1 -0
  307. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +85 -65
  308. data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
  309. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +1 -0
  310. data/lib/graphql/subscriptions/event.rb +25 -6
  311. data/lib/graphql/subscriptions/serialize.rb +89 -23
  312. data/lib/graphql/subscriptions.rb +172 -46
  313. data/lib/graphql/testing/helpers.rb +17 -4
  314. data/lib/graphql/testing/mock_action_cable.rb +55 -33
  315. data/lib/graphql/testing.rb +1 -0
  316. data/lib/graphql/tracing/active_support_notifications_trace.rb +17 -9
  317. data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
  318. data/lib/graphql/tracing/appoptics_trace.rb +2 -1
  319. data/lib/graphql/tracing/appoptics_tracing.rb +2 -1
  320. data/lib/graphql/tracing/appsignal_trace.rb +16 -7
  321. data/lib/graphql/tracing/appsignal_tracing.rb +7 -3
  322. data/lib/graphql/tracing/call_legacy_tracers.rb +1 -0
  323. data/lib/graphql/tracing/data_dog_trace.rb +17 -6
  324. data/lib/graphql/tracing/data_dog_tracing.rb +10 -3
  325. data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +1 -0
  326. data/lib/graphql/tracing/detailed_trace/memory_backend.rb +1 -0
  327. data/lib/graphql/tracing/detailed_trace/redis_backend.rb +1 -0
  328. data/lib/graphql/tracing/detailed_trace.rb +105 -42
  329. data/lib/graphql/tracing/legacy_hooks_trace.rb +5 -0
  330. data/lib/graphql/tracing/legacy_trace.rb +1 -0
  331. data/lib/graphql/tracing/monitor_trace.rb +17 -11
  332. data/lib/graphql/tracing/new_relic_trace.rb +17 -8
  333. data/lib/graphql/tracing/new_relic_tracing.rb +7 -3
  334. data/lib/graphql/tracing/notifications_trace.rb +11 -8
  335. data/lib/graphql/tracing/notifications_tracing.rb +23 -7
  336. data/lib/graphql/tracing/null_trace.rb +1 -0
  337. data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +1 -0
  338. data/lib/graphql/tracing/perfetto_trace.rb +41 -19
  339. data/lib/graphql/tracing/platform_trace.rb +3 -1
  340. data/lib/graphql/tracing/platform_tracing.rb +16 -7
  341. data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +1 -0
  342. data/lib/graphql/tracing/prometheus_trace.rb +22 -13
  343. data/lib/graphql/tracing/prometheus_tracing.rb +1 -0
  344. data/lib/graphql/tracing/scout_trace.rb +10 -4
  345. data/lib/graphql/tracing/scout_tracing.rb +7 -3
  346. data/lib/graphql/tracing/sentry_trace.rb +25 -6
  347. data/lib/graphql/tracing/statsd_trace.rb +12 -6
  348. data/lib/graphql/tracing/statsd_tracing.rb +7 -1
  349. data/lib/graphql/tracing/trace.rb +231 -58
  350. data/lib/graphql/tracing.rb +25 -9
  351. data/lib/graphql/type_kinds.rb +2 -1
  352. data/lib/graphql/types/big_int.rb +1 -0
  353. data/lib/graphql/types/boolean.rb +1 -0
  354. data/lib/graphql/types/float.rb +19 -4
  355. data/lib/graphql/types/id.rb +1 -0
  356. data/lib/graphql/types/int.rb +2 -1
  357. data/lib/graphql/types/iso_8601_date.rb +21 -4
  358. data/lib/graphql/types/iso_8601_date_time.rb +33 -6
  359. data/lib/graphql/types/iso_8601_duration.rb +42 -9
  360. data/lib/graphql/types/json.rb +1 -0
  361. data/lib/graphql/types/relay/base_connection.rb +38 -32
  362. data/lib/graphql/types/relay/base_edge.rb +15 -9
  363. data/lib/graphql/types/relay/connection_behaviors.rb +19 -3
  364. data/lib/graphql/types/relay/edge_behaviors.rb +17 -4
  365. data/lib/graphql/types/relay/has_node_field.rb +6 -1
  366. data/lib/graphql/types/relay/has_nodes_field.rb +6 -1
  367. data/lib/graphql/types/relay/node.rb +1 -0
  368. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  369. data/lib/graphql/types/relay/page_info.rb +1 -0
  370. data/lib/graphql/types/relay/page_info_behaviors.rb +1 -0
  371. data/lib/graphql/types/relay.rb +4 -3
  372. data/lib/graphql/types/string.rb +1 -0
  373. data/lib/graphql/types.rb +1 -0
  374. data/lib/graphql/unauthorized_enum_value_error.rb +4 -1
  375. data/lib/graphql/unauthorized_error.rb +11 -4
  376. data/lib/graphql/unauthorized_field_error.rb +4 -1
  377. data/lib/graphql/unresolved_type_error.rb +16 -5
  378. data/lib/graphql/version.rb +2 -1
  379. data/lib/graphql.rb +39 -9
  380. data/readme.md +1 -1
  381. metadata +91 -5
  382. data/.yardopts +0 -5
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  # Lookahead creates a uniform interface to inspect the forthcoming selections.
@@ -9,28 +10,38 @@ module GraphQL
9
10
  # A field may get access to its lookahead by adding `extras: [:lookahead]`
10
11
  # to its configuration.
11
12
  #
12
- # @example looking ahead in a field
13
- # field :articles, [Types::Article], null: false,
14
- # extras: [:lookahead]
13
+ # **Examples**
15
14
  #
16
- # # For example, imagine a faster database call
17
- # # may be issued when only some fields are requested.
18
- # #
19
- # # Imagine that _full_ fetch must be made to satisfy `fullContent`,
20
- # # we can look ahead to see if we need that field. If we do,
21
- # # we make the expensive database call instead of the cheap one.
22
- # def articles(lookahead:)
23
- # if lookahead.selects?(:full_content)
24
- # fetch_full_articles(object)
25
- # else
26
- # fetch_preview_articles(object)
27
- # end
15
+ # **Example: looking ahead in a field**
16
+ #
17
+ # ```ruby
18
+ # field :articles, [Types::Article], null: false,
19
+ # extras: [:lookahead]
20
+ #
21
+ # # For example, imagine a faster database call
22
+ # # may be issued when only some fields are requested.
23
+ # #
24
+ # # Imagine that _full_ fetch must be made to satisfy `fullContent`,
25
+ # # we can look ahead to see if we need that field. If we do,
26
+ # # we make the expensive database call instead of the cheap one.
27
+ # def articles(lookahead:)
28
+ # if lookahead.selects?(:full_content)
29
+ # fetch_full_articles(object)
30
+ # else
31
+ # fetch_preview_articles(object)
28
32
  # end
33
+ # end
34
+ # ```
29
35
  class Lookahead
30
- # @param query [GraphQL::Query]
31
- # @param ast_nodes [Array<GraphQL::Language::Nodes::Field>, Array<GraphQL::Language::Nodes::OperationDefinition>]
32
- # @param field [GraphQL::Schema::Field] if `ast_nodes` are fields, this is the field definition matching those nodes
33
- # @param root_type [Class] if `ast_nodes` are operation definition, this is the root type for that operation
36
+ # **Parameters**
37
+ #
38
+ # - `query` (`GraphQL::Query`)
39
+ # - `ast_nodes` (`Array<GraphQL::Language::Nodes::Field>, Array<GraphQL::Language::Nodes::OperationDefinition>`)
40
+ # - `field` (`GraphQL::Schema::Field`) — if `ast_nodes` are fields, this is the field definition matching those nodes
41
+ # - `root_type` (`Class`) — if `ast_nodes` are operation definition, this is the root type for that operation
42
+ #
43
+ # :call-seq:
44
+ # initialize(GraphQL::Query query:, Array[GraphQL::Language::Nodes::Field] | Array[GraphQL::Language::Nodes::OperationDefinition] ast_nodes:, GraphQL::Schema::Field field:, Class root_type:, owner_type:)
34
45
  def initialize(query:, ast_nodes:, field: nil, root_type: nil, owner_type: nil)
35
46
  @ast_nodes = ast_nodes.freeze
36
47
  @field = field
@@ -40,16 +51,27 @@ module GraphQL
40
51
  @owner_type = owner_type
41
52
  end
42
53
 
43
- # @return [Array<GraphQL::Language::Nodes::Field>]
54
+ # **Returns**
55
+ #
56
+ # - `Array<GraphQL::Language::Nodes::Field>`
44
57
  attr_reader :ast_nodes
45
58
 
46
- # @return [GraphQL::Schema::Field]
59
+ # **Returns**
60
+ #
61
+ # - `GraphQL::Schema::Field`
47
62
  attr_reader :field
48
63
 
49
- # @return [GraphQL::Schema::Object, GraphQL::Schema::Union, GraphQL::Schema::Interface]
64
+ # **Returns**
65
+ #
66
+ # - `GraphQL::Schema::Object, GraphQL::Schema::Union, GraphQL::Schema::Interface`
50
67
  attr_reader :owner_type
51
68
 
52
- # @return [Hash<Symbol, Object>]
69
+ # **Returns**
70
+ #
71
+ # - `Hash<Symbol, Object>`
72
+ #
73
+ # :call-seq:
74
+ # arguments() -> Hash[Symbol, Object]
53
75
  def arguments
54
76
  if defined?(@arguments)
55
77
  @arguments
@@ -80,9 +102,18 @@ module GraphQL
80
102
  # against the arguments in the next selection. This method will return false
81
103
  # if any of the given `arguments:` are not present and matching in the next selection.
82
104
  # (But, the next selection may contain _more_ than the given arguments.)
83
- # @param field_name [String, Symbol]
84
- # @param arguments [Hash] Arguments which must match in the selection
85
- # @return [Boolean]
105
+ #
106
+ # **Parameters**
107
+ #
108
+ # - `field_name` (`String, Symbol`)
109
+ # - `arguments` (`Hash`) — Arguments which must match in the selection
110
+ #
111
+ # **Returns**
112
+ #
113
+ # - `Boolean`
114
+ #
115
+ # :call-seq:
116
+ # selects?(String | Symbol field_name, selected_type:, Hash arguments:) -> bool
86
117
  def selects?(field_name, selected_type: @selected_type, arguments: nil)
87
118
  selection(field_name, selected_type: selected_type, arguments: arguments).selected?
88
119
  end
@@ -96,22 +127,45 @@ module GraphQL
96
127
  # against the arguments in the next selection. This method will return false
97
128
  # if any of the given `arguments:` are not present and matching in the next selection.
98
129
  # (But, the next selection may contain _more_ than the given arguments.)
99
- # @param alias_name [String, Symbol]
100
- # @param arguments [Hash] Arguments which must match in the selection
101
- # @return [Boolean]
130
+ #
131
+ # **Parameters**
132
+ #
133
+ # - `alias_name` (`String, Symbol`)
134
+ # - `arguments` (`Hash`) — Arguments which must match in the selection
135
+ #
136
+ # **Returns**
137
+ #
138
+ # - `Boolean`
139
+ #
140
+ # :call-seq:
141
+ # selects_alias?(String | Symbol alias_name, Hash arguments:) -> bool
102
142
  def selects_alias?(alias_name, arguments: nil)
103
143
  alias_selection(alias_name, arguments: arguments).selected?
104
144
  end
105
145
 
106
- # @return [Boolean] True if this lookahead represents a field that was requested
146
+ # **Returns**
147
+ #
148
+ # - `Boolean` — True if this lookahead represents a field that was requested
149
+ #
150
+ # :call-seq:
151
+ # selected?() -> bool
107
152
  def selected?
108
153
  true
109
154
  end
110
155
 
111
- # Like {#selects?}, but can be used for chaining.
112
- # It returns a null object (check with {#selected?})
113
- # @param field_name [String, Symbol]
114
- # @return [GraphQL::Execution::Lookahead]
156
+ # Like [selects?](rdoc-ref:#selects?), but can be used for chaining.
157
+ # It returns a null object (check with [selected?](rdoc-ref:#selected?))
158
+ #
159
+ # **Parameters**
160
+ #
161
+ # - `field_name` (`String, Symbol`)
162
+ #
163
+ # **Returns**
164
+ #
165
+ # - `GraphQL::Execution::Lookahead`
166
+ #
167
+ # :call-seq:
168
+ # selection(String | Symbol field_name, selected_type:, arguments:) -> GraphQL::Execution::Lookahead
115
169
  def selection(field_name, selected_type: @selected_type, arguments: nil)
116
170
  next_field_defn = case field_name
117
171
  when String
@@ -141,12 +195,18 @@ module GraphQL
141
195
  lookahead_for_selection(next_field_defn, selected_type, arguments)
142
196
  end
143
197
 
144
- # Like {#selection}, but for aliases.
145
- # It returns a null object (check with {#selected?})
146
- # @return [GraphQL::Execution::Lookahead]
198
+ # Like [selection](rdoc-ref:#selection), but for aliases.
199
+ # It returns a null object (check with [selected?](rdoc-ref:#selected?))
200
+ #
201
+ # **Returns**
202
+ #
203
+ # - `GraphQL::Execution::Lookahead`
204
+ #
205
+ # :call-seq:
206
+ # alias_selection(alias_name, selected_type:, arguments:) -> GraphQL::Execution::Lookahead
147
207
  def alias_selection(alias_name, selected_type: @selected_type, arguments: nil)
148
- alias_cache_key = [alias_name, arguments]
149
- return alias_selections[key] if alias_selections.key?(alias_name)
208
+ alias_cache_key = [alias_name, selected_type, arguments]
209
+ return alias_selections[alias_cache_key] if alias_selections.key?(alias_cache_key)
150
210
 
151
211
  alias_node = lookup_alias_node(ast_nodes, alias_name)
152
212
  return NULL_LOOKAHEAD unless alias_node
@@ -163,21 +223,34 @@ module GraphQL
163
223
  alias_selections[alias_cache_key] = lookahead_for_selection(next_field_defn, selected_type, alias_arguments, alias_name)
164
224
  end
165
225
 
166
- # Like {#selection}, but for all nodes.
226
+ # Like [selection](rdoc-ref:#selection), but for all nodes.
167
227
  # It returns a list of Lookaheads for all Selections
168
228
  #
169
229
  # If `arguments:` is provided, each provided key/value will be matched
170
230
  # against the arguments in each selection. This method will filter the selections
171
231
  # if any of the given `arguments:` do not match the given selection.
172
232
  #
173
- # @example getting the name of a selection
174
- # def articles(lookahead:)
175
- # next_lookaheads = lookahead.selections # => [#<GraphQL::Execution::Lookahead ...>, ...]
176
- # next_lookaheads.map(&:name) #=> [:full_content, :title]
177
- # end
233
+ # **Examples**
234
+ #
235
+ # **Example: getting the name of a selection**
178
236
  #
179
- # @param arguments [Hash] Arguments which must match in the selection
180
- # @return [Array<GraphQL::Execution::Lookahead>]
237
+ # ```ruby
238
+ # def articles(lookahead:)
239
+ # next_lookaheads = lookahead.selections # => [#<GraphQL::Execution::Lookahead ...>, ...]
240
+ # next_lookaheads.map(&:name) #=> [:full_content, :title]
241
+ # end
242
+ # ```
243
+ #
244
+ # **Parameters**
245
+ #
246
+ # - `arguments` (`Hash`) — Arguments which must match in the selection
247
+ #
248
+ # **Returns**
249
+ #
250
+ # - `Array<GraphQL::Execution::Lookahead>`
251
+ #
252
+ # :call-seq:
253
+ # selections(Hash arguments:) -> Array[GraphQL::Execution::Lookahead]
181
254
  def selections(arguments: nil)
182
255
  subselections_by_type = {}
183
256
  subselections_on_type = subselections_by_type[@selected_type] = {}
@@ -202,13 +275,23 @@ module GraphQL
202
275
  # The method name of the field.
203
276
  # It returns the method_sym of the Lookahead's field.
204
277
  #
205
- # @example getting the name of a selection
206
- # def articles(lookahead:)
207
- # article.selection(:full_content).name # => :full_content
208
- # # ...
209
- # end
278
+ # **Examples**
279
+ #
280
+ # **Example: getting the name of a selection**
281
+ #
282
+ # ```ruby
283
+ # def articles(lookahead:)
284
+ # article.selection(:full_content).name # => :full_content
285
+ # # ...
286
+ # end
287
+ # ```
288
+ #
289
+ # **Returns**
290
+ #
291
+ # - `Symbol`
210
292
  #
211
- # @return [Symbol]
293
+ # :call-seq:
294
+ # name() -> Symbol
212
295
  def name
213
296
  @field && @field.original_name
214
297
  end
@@ -217,7 +300,7 @@ module GraphQL
217
300
  "#<GraphQL::Execution::Lookahead #{@field ? "@field=#{@field.path.inspect}": "@root_type=#{@root_type}"} @ast_nodes.size=#{@ast_nodes.size}>"
218
301
  end
219
302
 
220
- # This is returned for {Lookahead#selection} when a non-existent field is passed
303
+ # This is returned for [Lookahead#selection](rdoc-ref:Lookahead#selection) when a non-existent field is passed
221
304
  class NullLookahead < Lookahead
222
305
  # No inputs required here.
223
306
  def initialize
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  # Execute multiple queries under the same multiplex "umbrella".
@@ -17,12 +18,11 @@ module GraphQL
17
18
  #
18
19
  # If one query raises an application error, all queries will be in undefined states.
19
20
  #
20
- # Validation errors and {GraphQL::ExecutionError}s are handled in isolation:
21
+ # Validation errors and [GraphQL::ExecutionError](rdoc-ref:GraphQL::ExecutionError)s are handled in isolation:
21
22
  # one of these errors in one query will not affect the other queries.
22
23
  #
23
- # @see {Schema#multiplex} for public API
24
- # @api private
25
- class Multiplex
24
+ # See [Schema.multiplex](rdoc-ref:GraphQL::Schema::multiplex) for the public API
25
+ class Multiplex # :nodoc:
26
26
  include Tracing::Traceable
27
27
 
28
28
  attr_reader :context, :queries, :schema, :max_complexity, :dataloader, :current_trace
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  require "graphql/execution/prepare_object_step"
3
4
  require "graphql/execution/input_values"
4
5
  require "graphql/execution/field_resolve_step"
@@ -9,6 +10,8 @@ require "graphql/execution/runner"
9
10
  require "graphql/execution/selections_step"
10
11
  module GraphQL
11
12
  module Execution
13
+ #--
14
+ # @requires_ancestor: Kernel
12
15
  module Finalizer
13
16
  attr_accessor :path
14
17
 
@@ -30,6 +33,8 @@ module GraphQL
30
33
  module HaltExecution
31
34
  end
32
35
 
36
+ #--
37
+ # @requires_ancestor: Kernel
33
38
  module PostProcessor
34
39
  def after_resolve(field_results)
35
40
  raise RequiredImplementationMissingError, "#{self.class}#after_resolve should handle `field_results` and return a new value to use"
@@ -37,6 +42,8 @@ module GraphQL
37
42
  end
38
43
 
39
44
  module Next
45
+ #--
46
+ # @requires_ancestor: singleton(GraphQL::Schema)
40
47
  module SchemaExtension
41
48
  def execute_next(query_str = nil, query: nil, subscription_topic: nil, context: nil, document: nil, operation_name: nil, variables: nil, warden: nil, root_value: nil, validate: true, visibility_profile: nil)
42
49
  multiplex_context = if context
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class PrepareObjectStep
@@ -13,6 +14,7 @@ module GraphQL
13
14
  @resolved_type = nil
14
15
  @authorized_value = nil
15
16
  @authorization_error = nil
17
+ @execution_error = nil
16
18
  @key = key
17
19
  @next_step = :resolve_type
18
20
  @is_from_array = is_from_array
@@ -23,7 +25,12 @@ module GraphQL
23
25
  if @authorized_value
24
26
  query = @field_resolve_step.selections_step.query
25
27
  query.current_trace.begin_authorized(@resolved_type, @object, query.context)
26
- @authorized_value = @field_resolve_step.sync(@authorized_value)
28
+ begin
29
+ @authorized_value = @runner.schema.sync_lazy(@authorized_value)
30
+ rescue StandardError => err
31
+ @authorized_value = nil
32
+ handle_authorization_error(err, query)
33
+ end
27
34
  query.current_trace.end_authorized(@resolved_type, @object, query.context, @authorized_value)
28
35
  elsif @resolved_type
29
36
  ctx = @field_resolve_step.selections_step.query.context
@@ -89,8 +96,9 @@ module GraphQL
89
96
  query.current_trace.begin_authorized(@resolved_type, @object, query.context)
90
97
  @authorized_value = @resolved_type.authorized?(@object, query.context)
91
98
  query.current_trace.end_authorized(@resolved_type, @object, query.context, @authorized_value)
92
- rescue GraphQL::UnauthorizedError => auth_err
93
- @authorization_error = auth_err
99
+ rescue StandardError => err
100
+ @authorized_value = nil
101
+ handle_authorization_error(err, query)
94
102
  end
95
103
 
96
104
  if @runner.resolves_lazies && @runner.lazy?(@authorized_value)
@@ -99,19 +107,14 @@ module GraphQL
99
107
  else
100
108
  create_result
101
109
  end
102
- rescue GraphQL::RuntimeError => err
103
- @graphql_result[@key] = add_field_error(err)
104
- rescue StandardError => err
105
- query ||= @field_resolve_step.selections_step.query
106
- begin
107
- query.handle_or_reraise(err, field: @field_resolve_step.field_definition, arguments: @field_resolve_step.arguments, object: @object) # rubocop:disable Development/ContextIsPassedCop
108
- rescue GraphQL::RuntimeError => err
109
- @graphql_result[@key] = add_field_error(err)
110
- end
111
110
  end
112
111
 
113
112
  def create_result
114
- if !@authorized_value
113
+ if @execution_error
114
+ # `.authorized?` raised (or its lazy value raised) an error other than UnauthorizedError:
115
+ # it isn't an authorization decision, so don't call `unauthorized_object`.
116
+ @graphql_result[@key] = add_field_error(@execution_error)
117
+ elsif !@authorized_value
115
118
  @authorization_error ||= GraphQL::UnauthorizedError.new(object: @object, type: @resolved_type, context: @field_resolve_step.selections_step.query.context)
116
119
  end
117
120
 
@@ -146,6 +149,28 @@ module GraphQL
146
149
 
147
150
  @field_resolve_step.authorized_finished(self)
148
151
  end
152
+
153
+ private
154
+
155
+ # Errors raised by `.authorized?` (or by syncing its lazy return value):
156
+ #
157
+ # - `UnauthorizedError` is equivalent to returning `false`, so it goes to `unauthorized_object`
158
+ # - Other `GraphQL::RuntimeError`s are added to the response for this field
159
+ # - Other errors go to `rescue_from` handlers, which might return a `GraphQL::RuntimeError`, or else re-raise
160
+ def handle_authorization_error(err, query)
161
+ case err
162
+ when GraphQL::UnauthorizedError
163
+ @authorization_error = err
164
+ when GraphQL::RuntimeError
165
+ @execution_error = err
166
+ else
167
+ begin
168
+ @authorized_value = query.handle_or_reraise(err, field: @field_resolve_step.field_definition, arguments: @field_resolve_step.arguments, object: @object) # rubocop:disable Development/ContextIsPassedCop
169
+ rescue GraphQL::RuntimeError => runtime_err
170
+ handle_authorization_error(runtime_err, query)
171
+ end
172
+ end
173
+ end
149
174
  end
150
175
  end
151
176
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class ResolveTypeStep
@@ -17,7 +18,7 @@ module GraphQL
17
18
  def self.assert_valid_resolved_type(abstract_type, resolved_type, object, field_resolution_step, query: field_resolution_step.selections_step.query)
18
19
  possible_types = query.types.possible_types(abstract_type)
19
20
  if !possible_types.include?(resolved_type)
20
- err_class = abstract_type::UnresolvedTypeError
21
+ err_class = abstract_type.const_get(:UnresolvedTypeError)
21
22
  type_error = err_class.new(object, field_resolution_step.field_definition, abstract_type, resolved_type, possible_types)
22
23
  query.schema.type_error(type_error, query.context)
23
24
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class Runner
@@ -15,7 +16,7 @@ module GraphQL
15
16
  h[query] = InputValues.new(query, self)
16
17
  end.compare_by_identity
17
18
 
18
- @runtime_directives = nil
19
+ @runtime_directives = nil #: Hash[String, singleton(GraphQL::Schema::Directive)]?
19
20
  @schema.directives.each do |name, dir_class|
20
21
  if dir_class.runtime? && name != "include" && name != "skip"
21
22
  @runtime_directives ||= {}
@@ -54,7 +55,12 @@ module GraphQL
54
55
 
55
56
  attr_reader :schema, :variables, :dataloader, :resolves_lazies, :authorizes, :static_type_at, :runtime_type_at, :finalizers, :input_values
56
57
 
57
- # @return [void]
58
+ # **Returns**
59
+ #
60
+ # - `void`
61
+ #
62
+ # :call-seq:
63
+ # add_finalizer(query, result_value, key, finalizer) -> void
58
64
  def add_finalizer(query, result_value, key, finalizer)
59
65
  @finalizers ||= {}.compare_by_identity
60
66
  f_for_query = @finalizers[query] ||= {}.compare_by_identity
@@ -72,6 +78,7 @@ module GraphQL
72
78
  end
73
79
 
74
80
  def execute
81
+ previous_multiplex = Fiber[:__graphql_current_multiplex]
75
82
  Fiber[:__graphql_current_multiplex] = @multiplex
76
83
  isolated_steps = [[]]
77
84
  trace = @multiplex.current_trace
@@ -86,10 +93,10 @@ module GraphQL
86
93
  @schema.analysis_engine.analyze_multiplex(@multiplex, multiplex_analyzers)
87
94
  trace.end_analyze_multiplex(@multiplex, multiplex_analyzers)
88
95
 
89
- results = []
96
+ results = {}.compare_by_identity
90
97
  queries.each do |query|
91
98
  if query.validate && !query.valid?
92
- results << {
99
+ results[query] = {
93
100
  "errors" => query.static_errors.map(&:to_h)
94
101
  }
95
102
  next
@@ -124,8 +131,8 @@ module GraphQL
124
131
  end
125
132
  end
126
133
 
127
- queries.each_with_index.map do |query, idx|
128
- result = results[idx]
134
+ queries.map do |query|
135
+ result = results[query]
129
136
 
130
137
  fin_result = if (!@finalizers&.key?(query) && query.context.errors.empty?) || !query.valid?
131
138
  result
@@ -154,9 +161,19 @@ module GraphQL
154
161
  end
155
162
  query.result
156
163
  end
164
+ rescue SystemStackError => err
165
+ queries.map do |query|
166
+ @schema.query_stack_error(query, err)
167
+ query.result_values ||= { "errors" => query.context.errors.map(&:to_h) }
168
+ query.result
169
+ end
170
+ rescue Exception
171
+ # Assign values here so that the query's `@executed` becomes true
172
+ queries.map { |q| q.result_values ||= {} }
173
+ raise
157
174
  end
158
175
  ensure
159
- Fiber[:__graphql_current_multiplex] = nil
176
+ Fiber[:__graphql_current_multiplex] = previous_multiplex
160
177
  end
161
178
 
162
179
  def gather_selections(type_defn, ast_selections, selections_step, query, all_selections, prototype_result, into:)
@@ -255,17 +272,17 @@ module GraphQL
255
272
  end
256
273
 
257
274
  if !auth_check
258
- results << {}
275
+ results[query] = {}
259
276
  return
260
277
  end
261
278
  end
262
279
 
263
- results << { "data" => data }
280
+ results[query] = { "data" => data }
264
281
  objects = [root_value]
265
282
  query.current_trace.objects(root_type, objects, query.context)
266
283
 
267
284
  if query.is_a?(GraphQL::Query) && uses_runtime_directives && (query_dirs = selected_operation.directives).any? # rubocop:disable Development/NoneWithoutBlockCop
268
- continue_execution = true
285
+ continue_execution = true #: bool
269
286
  query_dirs.each do |dir_node|
270
287
  dir_defn = runtime_directives[dir_node.name] || raise(GraphQL::Error, "No directive definition found for: #{dir_node.name.inspect}")
271
288
  dir_args, errors = input_values[query].argument_values(dir_defn, dir_node.arguments, nil) # rubocop:disable Development/ContextIsPassedCop
@@ -354,7 +371,7 @@ module GraphQL
354
371
  objects = [root_value]
355
372
  query.current_trace.objects(resolved_type, objects, query.context)
356
373
  runtime_type_at[data] = resolved_type
357
- results << { "data" => data }
374
+ results[query] = { "data" => data }
358
375
  isolated_steps[0] << SelectionsStep.new(
359
376
  parent_type: resolved_type,
360
377
  field_resolve_step: nil,
@@ -369,10 +386,10 @@ module GraphQL
369
386
  inner_type = root_type.unwrap
370
387
  case inner_type.kind.name
371
388
  when "SCALAR", "ENUM"
372
- results << run_isolated_scalar(root_type, query)
389
+ results[query] = run_isolated_scalar(root_type, query)
373
390
  else
374
391
  list_result = Array.new(root_value.size) { Hash.new.compare_by_identity }
375
- results << { "data" => list_result }
392
+ results[query] = { "data" => list_result }
376
393
  isolated_steps[0] << SelectionsStep.new(
377
394
  parent_type: inner_type,
378
395
  field_resolve_step: nil,
@@ -385,7 +402,7 @@ module GraphQL
385
402
  )
386
403
  end
387
404
  when "SCALAR", "ENUM"
388
- results << run_isolated_scalar(root_type, query)
405
+ results[query] = run_isolated_scalar(root_type, query)
389
406
  else
390
407
  raise "Unhandled root type kind: #{root_type.kind.name.inspect}"
391
408
  end
@@ -418,7 +435,7 @@ module GraphQL
418
435
  key = dummy_path.pop
419
436
  is_from_array = key.is_a?(Integer)
420
437
 
421
- if lazy?(value)
438
+ if resolves_lazies && lazy?(value)
422
439
  value = @schema.sync_lazy(value)
423
440
  end
424
441
  selections = partial.ast_nodes
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class SelectionsStep
@@ -35,10 +36,10 @@ module GraphQL
35
36
  l = @all_selections.length
36
37
  while i < l
37
38
  grouped_selections = @all_selections[i]
38
- selections_prototype_result = @all_selections[i + 1]
39
+ selections_prototype_result = @all_selections[i + 1] #: as !nil
39
40
  if (directives_owner = grouped_selections.delete(:__node))
40
41
  directives = directives_owner.directives
41
- continue_execution = true
42
+ continue_execution = true #: bool
42
43
  directives.each do |dir_node|
43
44
  dir_defn = @runner.runtime_directives[dir_node.name]
44
45
  if dir_defn # not present for `skip` or `include`
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  require "graphql/execution/directive_checks"
3
4
  require "graphql/execution/next"
4
5
  require "graphql/execution/interpreter"
@@ -9,8 +10,7 @@ require "graphql/execution/errors"
9
10
 
10
11
  module GraphQL
11
12
  module Execution
12
- # @api private
13
- class Skip < GraphQL::RuntimeError
13
+ class Skip < GraphQL::RuntimeError # :nodoc:
14
14
  attr_accessor :path
15
15
  def ast_nodes=(_ignored); end
16
16
 
@@ -1,21 +1,25 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
- # If a field's resolve function returns a {ExecutionError},
4
+ # If a field's resolve function returns an [ExecutionError](rdoc-ref:GraphQL::ExecutionError),
4
5
  # the error will be inserted into the response's `"errors"` key
5
6
  # and the field will resolve to `nil`.
6
7
  class ExecutionError < GraphQL::RuntimeError
7
- # @return [String] an array describing the JSON-path into the execution
8
- # response which corresponds to this error.
8
+ # **Returns**
9
+ #
10
+ # - `String` — an array describing the JSON-path into the execution response which corresponds to this error.
9
11
  attr_accessor :path
10
12
 
11
- # @return [Hash] Optional data for error objects
12
- # @deprecated Use `extensions` instead of `options`. The GraphQL spec
13
- # recommends that any custom entries in an error be under the
14
- # `extensions` key.
13
+ # **Deprecated:** Use `extensions` instead of `options`. The GraphQL spec recommends that any custom entries in an error be under the `extensions` key.
14
+ #
15
+ # **Returns**
16
+ #
17
+ # - `Hash` — Optional data for error objects
15
18
  attr_accessor :options
16
19
 
17
- # @return [Hash] Optional custom data for error objects which will be added
18
- # under the `extensions` key.
20
+ # **Returns**
21
+ #
22
+ # - `Hash` — Optional custom data for error objects which will be added under the `extensions` key.
19
23
  attr_accessor :extensions
20
24
 
21
25
  def initialize(message, ast_node: nil, ast_nodes: nil, options: nil, extensions: nil)
@@ -38,7 +42,12 @@ module GraphQL
38
42
  end
39
43
  end
40
44
 
41
- # @return [Hash] An entry for the response's "errors" key
45
+ # **Returns**
46
+ #
47
+ # - `Hash` — An entry for the response's "errors" key
48
+ #
49
+ # :call-seq:
50
+ # to_h() -> Hash
42
51
  def to_h
43
52
  hash = {
44
53
  "message" => message,