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
  class Subscriptions
4
5
  # A subscriptions implementation that sends data
@@ -7,87 +8,100 @@ module GraphQL
7
8
  # Some things to keep in mind:
8
9
  #
9
10
  # - No queueing system; ActiveJob should be added
10
- # - Take care to reload context when re-delivering the subscription. (see {Query#subscription_update?})
11
+ # - Take care to reload context when re-delivering the subscription. (see [Query#subscription_update?](rdoc-ref:Query#subscription_update?))
11
12
  # - Avoid the async ActionCable adapter and use the redis or PostgreSQL adapters instead. Otherwise calling #trigger won't work from background jobs or the Rails console.
12
13
  #
13
- # @example Adding ActionCableSubscriptions to your schema
14
- # class MySchema < GraphQL::Schema
15
- # # ...
16
- # use GraphQL::Subscriptions::ActionCableSubscriptions
17
- # end
14
+ # See [GraphQL::Testing::MockActionCable](rdoc-ref:GraphQL::Testing::MockActionCable) for test helpers
18
15
  #
19
- # @example Implementing a channel for GraphQL Subscriptions
20
- # class GraphqlChannel < ApplicationCable::Channel
21
- # def subscribed
22
- # @subscription_ids = []
23
- # end
16
+ # **Examples**
24
17
  #
25
- # def execute(data)
26
- # query = data["query"]
27
- # variables = ensure_hash(data["variables"])
28
- # operation_name = data["operationName"]
29
- # context = {
30
- # # Re-implement whatever context methods you need
31
- # # in this channel or ApplicationCable::Channel
32
- # # current_user: current_user,
33
- # # Make sure the channel is in the context
34
- # channel: self,
35
- # }
18
+ # **Example: Adding ActionCableSubscriptions to your schema**
36
19
  #
37
- # result = MySchema.execute(
38
- # query,
39
- # context: context,
40
- # variables: variables,
41
- # operation_name: operation_name
42
- # )
20
+ # ```ruby
21
+ # class MySchema < GraphQL::Schema
22
+ # # ...
23
+ # use GraphQL::Subscriptions::ActionCableSubscriptions
24
+ # end
25
+ # ```
43
26
  #
44
- # payload = {
45
- # result: result.to_h,
46
- # more: result.subscription?,
47
- # }
27
+ # **Example: Implementing a channel for GraphQL Subscriptions**
48
28
  #
49
- # # Track the subscription here so we can remove it
50
- # # on unsubscribe.
51
- # if result.context[:subscription_id]
52
- # @subscription_ids << result.context[:subscription_id]
53
- # end
29
+ # ```ruby
30
+ # class GraphqlChannel < ApplicationCable::Channel
31
+ # def subscribed
32
+ # @subscription_ids = []
33
+ # end
54
34
  #
55
- # transmit(payload)
56
- # end
35
+ # def execute(data)
36
+ # query = data["query"]
37
+ # variables = ensure_hash(data["variables"])
38
+ # operation_name = data["operationName"]
39
+ # context = {
40
+ # # Re-implement whatever context methods you need
41
+ # # in this channel or ApplicationCable::Channel
42
+ # # current_user: current_user,
43
+ # # Make sure the channel is in the context
44
+ # channel: self,
45
+ # }
46
+ #
47
+ # result = MySchema.execute(
48
+ # query,
49
+ # context: context,
50
+ # variables: variables,
51
+ # operation_name: operation_name
52
+ # )
57
53
  #
58
- # def unsubscribed
59
- # @subscription_ids.each { |sid|
60
- # MySchema.subscriptions.delete_subscription(sid)
61
- # }
54
+ # payload = {
55
+ # result: result.to_h,
56
+ # more: result.subscription?,
57
+ # }
58
+ #
59
+ # # Track the subscription here so we can remove it
60
+ # # on unsubscribe.
61
+ # if result.context[:subscription_id]
62
+ # @subscription_ids << result.context[:subscription_id]
62
63
  # end
63
64
  #
64
- # private
65
+ # transmit(payload)
66
+ # end
65
67
  #
66
- # def ensure_hash(ambiguous_param)
67
- # case ambiguous_param
68
- # when String
69
- # if ambiguous_param.present?
70
- # ensure_hash(JSON.parse(ambiguous_param))
71
- # else
72
- # {}
73
- # end
74
- # when Hash, ActionController::Parameters
75
- # ambiguous_param
76
- # when nil
77
- # {}
68
+ # def unsubscribed
69
+ # @subscription_ids.each { |sid|
70
+ # MySchema.subscriptions.delete_subscription(sid)
71
+ # }
72
+ # end
73
+ #
74
+ # private
75
+ #
76
+ # def ensure_hash(ambiguous_param)
77
+ # case ambiguous_param
78
+ # when String
79
+ # if ambiguous_param.present?
80
+ # ensure_hash(JSON.parse(ambiguous_param))
78
81
  # else
79
- # raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
82
+ # {}
80
83
  # end
84
+ # when Hash, ActionController::Parameters
85
+ # ambiguous_param
86
+ # when nil
87
+ # {}
88
+ # else
89
+ # raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
81
90
  # end
82
- # end
83
- #
84
- # @see GraphQL::Testing::MockActionCable for test helpers
91
+ # end
92
+ # end
93
+ # ```
85
94
  class ActionCableSubscriptions < GraphQL::Subscriptions
86
95
  SUBSCRIPTION_PREFIX = "graphql-subscription:"
87
96
  EVENT_PREFIX = "graphql-event:"
88
97
 
89
- # @param serializer [<#dump(obj), #load(string)] Used for serializing messages before handing them to `.broadcast(msg)`
90
- # @param namespace [string] Used to namespace events and subscriptions (default: '')
98
+ # **Parameters**
99
+ #
100
+ # - `serializer` (`<#dump(obj), #load(string)>`) — Used for serializing messages before handing them to `.broadcast(msg)`
101
+ # - `namespace` (`string`) — Used to namespace events and subscriptions (default: '')
102
+ #
103
+ # :call-seq:
104
+ # initialize(#dump(obj), #load(string) serializer:, string namespace:, action_cable:, action_cable_coder:, **rest)
91
105
  def initialize(serializer: Serialize, namespace: '', action_cable: ActionCable, action_cable_coder: ActiveSupport::JSON, **rest)
92
106
  # A per-process map of subscriptions to deliver.
93
107
  # This is provided by Rails, so let's use it
@@ -170,7 +184,7 @@ module GraphQL
170
184
  event_stream = stream_event_name(initial_event)
171
185
  channel.stream_from(event_stream, coder: @action_cable_coder) do |message|
172
186
  events_by_fingerprint = @events[topic]
173
- object = nil
187
+ object = nil #: untyped
174
188
  events_by_fingerprint.each do |_fingerprint, events|
175
189
  if !events.empty? && events.first == initial_event
176
190
  # The fingerprint has told us that this response should be shared by all subscribers,
@@ -194,8 +208,14 @@ module GraphQL
194
208
 
195
209
  # This is called to turn an ActionCable-broadcasted string (JSON)
196
210
  # into a query-ready application object.
197
- # @param message [String] n ActionCable-broadcasted string (JSON)
198
- # @param context [GraphQL::Query::Context] the context of the first event for a given subscription fingerprint
211
+ #
212
+ # **Parameters**
213
+ #
214
+ # - `message` (`String`) — n ActionCable-broadcasted string (JSON)
215
+ # - `context` (`GraphQL::Query::Context`) — the context of the first event for a given subscription fingerprint
216
+ #
217
+ # :call-seq:
218
+ # load_action_cable_message(String message, GraphQL::Query::Context context)
199
219
  def load_action_cable_message(message, context)
200
220
  if @serialize_with_context
201
221
  @serializer.load(message, context)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
 
3
4
  module GraphQL
4
5
  class Subscriptions
@@ -7,9 +8,8 @@ module GraphQL
7
8
  # - Is completely broadcastable
8
9
  #
9
10
  # Assign the result to `context.namespace(:subscriptions)[:subscription_broadcastable]`
10
- # @api private
11
- # @see Subscriptions#broadcastable? for a public API
12
- class BroadcastAnalyzer < GraphQL::Analysis::Analyzer
11
+ # See [Subscriptions#broadcastable?](rdoc-ref:Subscriptions#broadcastable?) for a public API
12
+ class BroadcastAnalyzer < GraphQL::Analysis::Analyzer # :nodoc:
13
13
  def initialize(subject)
14
14
  super
15
15
  @default_broadcastable = subject.schema.subscriptions.default_broadcastable
@@ -45,7 +45,13 @@ module GraphQL
45
45
 
46
46
  # Assign the result to context.
47
47
  # (This method is allowed to return an error, but we don't need to)
48
- # @return [void]
48
+ #
49
+ # **Returns**
50
+ #
51
+ # - `void`
52
+ #
53
+ # :call-seq:
54
+ # result() -> void
49
55
  def result
50
56
  query.context.namespace(:subscriptions)[:subscription_broadcastable] = @subscription_broadcastable
51
57
  nil
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  class Subscriptions
4
5
  class DefaultSubscriptionResolveExtension < GraphQL::Schema::FieldExtension
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  class Subscriptions
4
5
  # This thing can be:
@@ -6,16 +7,24 @@ module GraphQL
6
7
  # - Triggered by `MySchema.subscriber.trigger(name, arguments, obj)`
7
8
  #
8
9
  class Event
9
- # @return [String] Corresponds to the Subscription root field name
10
+ # **Returns**
11
+ #
12
+ # - `String` — Corresponds to the Subscription root field name
10
13
  attr_reader :name
11
14
 
12
- # @return [GraphQL::Execution::Interpreter::Arguments]
15
+ # **Returns**
16
+ #
17
+ # - `GraphQL::Execution::Interpreter::Arguments`
13
18
  attr_reader :arguments
14
19
 
15
- # @return [GraphQL::Query::Context]
20
+ # **Returns**
21
+ #
22
+ # - `GraphQL::Query::Context`
16
23
  attr_reader :context
17
24
 
18
- # @return [String] An opaque string which identifies this event, derived from `name` and `arguments`
25
+ # **Returns**
26
+ #
27
+ # - `String` — An opaque string which identifies this event, derived from `name` and `arguments`
19
28
  attr_reader :topic
20
29
 
21
30
  def initialize(name:, arguments:, field: nil, context: nil, scope: nil)
@@ -36,7 +45,12 @@ module GraphQL
36
45
  @topic = self.class.serialize(name, arguments, field, scope: scope_val, context: context)
37
46
  end
38
47
 
39
- # @return [String] an identifier for this unit of subscription
48
+ # **Returns**
49
+ #
50
+ # - `String` — an identifier for this unit of subscription
51
+ #
52
+ # :call-seq:
53
+ # serialize(_name, arguments, field, scope:, context:) -> String
40
54
  def self.serialize(_name, arguments, field, scope:, context: GraphQL::Query::NullContext.instance)
41
55
  subscription = field.resolver || GraphQL::Schema::Subscription
42
56
  arguments = arguments_without_field_extras(field: field, arguments: arguments)
@@ -44,7 +58,12 @@ module GraphQL
44
58
  subscription.topic_for(arguments: normalized_args, field: field, scope: scope)
45
59
  end
46
60
 
47
- # @return [String] a logical identifier for this event. (Stable when the query is broadcastable.)
61
+ # **Returns**
62
+ #
63
+ # - `String` — a logical identifier for this event. (Stable when the query is broadcastable.)
64
+ #
65
+ # :call-seq:
66
+ # fingerprint() -> String
48
67
  def fingerprint
49
68
  @fingerprint ||= begin
50
69
  # When this query has been flagged as broadcastable,
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  require "date"
3
4
  require "set"
4
5
  module GraphQL
5
6
  class Subscriptions
6
7
  # Serialization helpers for passing subscription data around.
7
- # @api private
8
- module Serialize
8
+ module Serialize # :nodoc:
9
9
  GLOBALID_KEY = "__gid__"
10
10
  SYMBOL_KEY = "__sym__"
11
11
  SYMBOL_KEYS_KEY = "__sym_keys__"
@@ -13,27 +13,52 @@ module GraphQL
13
13
  TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%N%z" # eg '2020-01-01 23:59:59.123456789+05:00'
14
14
  TIMESTAMP_CLASS_NAMES = ["Date", "DateTime", "Time"].freeze
15
15
  OPEN_STRUCT_KEY = "__ostruct__"
16
+ HASH_KEY = "__graphql_hash__"
17
+ RESERVED_KEYS = [GLOBALID_KEY, SYMBOL_KEY, SYMBOL_KEYS_KEY, TIMESTAMP_KEY, OPEN_STRUCT_KEY, HASH_KEY].freeze
16
18
 
17
- module_function
18
-
19
- # @param str [String] A serialized object from {.dump}
20
- # @return [Object] An object equivalent to the one passed to {.dump}
21
- def load(str)
19
+ # **Parameters**
20
+ #
21
+ # - `str` (`String`) — A serialized object from [.dump](rdoc-ref:.dump)
22
+ #
23
+ # **Returns**
24
+ #
25
+ # - `Object` — An object equivalent to the one passed to [.dump](rdoc-ref:.dump)
26
+ #
27
+ # :call-seq:
28
+ # load(String str) -> Object
29
+ def self.load(str)
22
30
  parsed_obj = JSON.parse(str)
23
31
  load_value(parsed_obj)
24
32
  end
25
33
 
26
- # @param obj [Object] Some subscription-related data to dump
27
- # @return [String] The stringified object
28
- def dump(obj)
34
+ # **Parameters**
35
+ #
36
+ # - `obj` (`Object`) — Some subscription-related data to dump
37
+ #
38
+ # **Returns**
39
+ #
40
+ # - `String` — The stringified object
41
+ #
42
+ # :call-seq:
43
+ # dump(Object obj) -> String
44
+ def self.dump(obj)
29
45
  JSON.generate(dump_value(obj))
30
46
  end
31
47
 
32
48
  # This is for turning objects into subscription scopes.
33
49
  # It's a one-way transformation, can't reload this :'(
34
- # @param obj [Object]
35
- # @return [String]
36
- def dump_recursive(obj)
50
+ #
51
+ # **Parameters**
52
+ #
53
+ # - `obj` (`Object`)
54
+ #
55
+ # **Returns**
56
+ #
57
+ # - `String`
58
+ #
59
+ # :call-seq:
60
+ # dump_recursive(Object obj) -> String
61
+ def self.dump_recursive(obj)
37
62
  case
38
63
  when obj.is_a?(Array)
39
64
  obj.map { |i| dump_recursive(i) }.join(':')
@@ -53,11 +78,19 @@ module GraphQL
53
78
  class << self
54
79
  private
55
80
 
56
- # @param value [Object] A parsed JSON object
57
- # @return [Object] An object that load Global::Identification recursive
81
+ # **Parameters**
82
+ #
83
+ # - `value` (`Object`) — A parsed JSON object
84
+ #
85
+ # **Returns**
86
+ #
87
+ # - `Object` — An object that load Global::Identification recursive
88
+ #
89
+ # :call-seq:
90
+ # load_value(Object value) -> Object
58
91
  def load_value(value)
59
92
  if value.is_a?(Array)
60
- is_gids = (v1 = value[0]).is_a?(Hash) && v1.size == 1 && v1[GLOBALID_KEY]
93
+ is_gids = !value.empty? && value.all? { |v| v.is_a?(Hash) && v.size == 1 && v[GLOBALID_KEY] }
61
94
  if is_gids
62
95
  # Assume it's an array of global IDs
63
96
  ids = value.map { |v| v[GLOBALID_KEY] }
@@ -91,6 +124,10 @@ module GraphQL
91
124
  when OPEN_STRUCT_KEY
92
125
  ostruct_values = load_value(value[OPEN_STRUCT_KEY])
93
126
  OpenStruct.new(ostruct_values)
127
+ when HASH_KEY
128
+ value[HASH_KEY].each_with_object({}) do |(k, v), loaded_h|
129
+ loaded_h[load_value(k)] = load_value(v)
130
+ end
94
131
  else
95
132
  key = value.keys.first
96
133
  { key => load_value(value[key]) }
@@ -98,15 +135,21 @@ module GraphQL
98
135
  else
99
136
  loaded_h = {}
100
137
  sym_keys = value.fetch(SYMBOL_KEYS_KEY, [])
138
+ symbol_key_values = sym_keys.is_a?(Hash) ? sym_keys : nil
101
139
  value.each do |k, v|
102
140
  if k == SYMBOL_KEYS_KEY
103
141
  next
104
142
  end
105
- if sym_keys.include?(k)
143
+ if !symbol_key_values && sym_keys.include?(k)
106
144
  k = k.to_sym
107
145
  end
108
146
  loaded_h[k] = load_value(v)
109
147
  end
148
+ if symbol_key_values
149
+ symbol_key_values.each do |k, v|
150
+ loaded_h[k.to_sym] = load_value(v)
151
+ end
152
+ end
110
153
  loaded_h
111
154
  end
112
155
  else
@@ -114,22 +157,45 @@ module GraphQL
114
157
  end
115
158
  end
116
159
 
117
- # @param obj [Object] Some subscription-related data to dump
118
- # @return [Object] The object that converted Global::Identification
160
+ # **Parameters**
161
+ #
162
+ # - `obj` (`Object`) — Some subscription-related data to dump
163
+ #
164
+ # **Returns**
165
+ #
166
+ # - `Object` — The object that converted Global::Identification
167
+ #
168
+ # :call-seq:
169
+ # dump_value(Object obj) -> Object
119
170
  def dump_value(obj)
120
171
  if obj.is_a?(Array)
121
172
  obj.map{|item| dump_value(item)}
122
173
  elsif obj.is_a?(Hash)
123
- symbol_keys = nil
174
+ has_colliding_symbol_key = obj.any? { |k, _v| k.is_a?(Symbol) && obj.key?(k.to_s) }
175
+ if obj.any? { |k, _v| RESERVED_KEYS.include?(k.to_s) }
176
+ return {
177
+ HASH_KEY => obj.map { |k, v| [dump_value(k.is_a?(Symbol) ? k : k.to_s), dump_value(v)] },
178
+ }
179
+ end
180
+ symbol_keys = nil #: Set[String]?
181
+ symbol_key_values = nil #: Hash[String, untyped]?
124
182
  dumped_h = {}
125
183
  obj.each do |k, v|
126
- dumped_h[k.to_s] = dump_value(v)
127
- if k.is_a?(Symbol)
184
+ dumped_v = dump_value(v)
185
+ if has_colliding_symbol_key && k.is_a?(Symbol)
186
+ symbol_key_values ||= {}
187
+ symbol_key_values[k.to_s] = dumped_v
188
+ else
189
+ dumped_h[k.to_s] = dumped_v
190
+ end
191
+ if !has_colliding_symbol_key && k.is_a?(Symbol)
128
192
  symbol_keys ||= Set.new
129
193
  symbol_keys << k.to_s
130
194
  end
131
195
  end
132
- if symbol_keys
196
+ if symbol_key_values
197
+ dumped_h[SYMBOL_KEYS_KEY] = symbol_key_values
198
+ elsif symbol_keys
133
199
  dumped_h[SYMBOL_KEYS_KEY] = symbol_keys.to_a
134
200
  end
135
201
  dumped_h