graphql 2.6.11 → 2.6.13

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 +2 -1
  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 +10 -7
  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 +93 -42
  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 +40 -13
  61. data/lib/graphql/execution/finalize.rb +12 -6
  62. data/lib/graphql/execution/input_values.rb +2 -1
  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 +15 -6
  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 +1 -0
  79. data/lib/graphql/execution/resolve_type_step.rb +2 -1
  80. data/lib/graphql/execution/runner.rb +9 -3
  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 +1 -0
  85. data/lib/graphql/float_encoding_error.rb +7 -2
  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 +5 -0
  110. data/lib/graphql/language/nodes.rb +2094 -419
  111. data/lib/graphql/language/parser.rb +24 -17
  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 +13 -7
  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 +20 -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 +123 -22
  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 -15
  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 +1 -0
  137. data/lib/graphql/query/variables.rb +9 -2
  138. data/lib/graphql/query.rb +193 -49
  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 +18 -6
  153. data/lib/graphql/schema/always_visible.rb +1 -0
  154. data/lib/graphql/schema/argument.rb +265 -42
  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 +94 -27
  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 +12 -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 +621 -109
  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 +16 -5
  186. data/lib/graphql/schema/member/graphql_type_names.rb +10 -6
  187. data/lib/graphql/schema/member/has_arguments.rb +115 -48
  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 +38 -10
  193. data/lib/graphql/schema/member/has_fields.rb +151 -70
  194. data/lib/graphql/schema/member/has_interfaces.rb +10 -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 +33 -12
  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 +65 -20
  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 +1046 -300
  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 +295 -134
  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 +58 -19
  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 +12 -5
  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 +1 -0
  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 +37 -9
  380. data/readme.md +1 -1
  381. metadata +89 -5
  382. data/.yardopts +0 -5
@@ -1,27 +1,79 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
5
+ #--
6
+ # @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
4
7
  module VariableUsagesAreAllowed
8
+ # A variable in a fragment. It's checked after the visit, against each operation which uses the fragment.
9
+ # `list_depth` is the number of list literals around the variable.
10
+ FragmentVariableUsage = Struct.new(:argument_owner, :arg_node, :variable_name, :list_depth, :path, :checked_variable_types)
11
+
5
12
  def initialize(*)
6
13
  super
7
14
  # holds { name => ast_node } pairs
8
15
  @declared_variables = {}
16
+ @operation_declared_variables = {}.compare_by_identity #: Hash[GraphQL::Language::Nodes::OperationDefinition, Hash[String, GraphQL::Language::Nodes::VariableDefinition]]
17
+ @variable_usages_fragment_definition = nil
18
+ @fragment_variable_usages = nil #: Hash[GraphQL::Language::Nodes::FragmentDefinition, Array[FragmentVariableUsage]]?
19
+ @reported_fragment_variable_errors = nil #: Hash[GraphQL::Language::Nodes::Argument, Hash[String, bool]]?
20
+ @allow_legacy_invalid_variable_usages = @schema.allow_legacy_invalid_variable_usages
21
+ # The arguments and variables which have an error from the legacy check
22
+ @legacy_errors = nil #: Hash[GraphQL::Language::Nodes::Argument, Hash[String, bool]]?
9
23
  end
10
24
 
11
25
  def on_operation_definition(node, parent)
12
26
  @declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = var }
27
+ @operation_declared_variables[node] = @declared_variables
13
28
  super
14
29
  end
15
30
 
16
- def on_argument(node, parent)
17
- node_values = if node.value.is_a?(Array)
18
- node.value
19
- else
20
- [node.value]
31
+ def on_fragment_definition(node, parent)
32
+ @variable_usages_fragment_definition = node
33
+ super
34
+ @variable_usages_fragment_definition = nil
35
+ end
36
+
37
+ def on_document(node, parent)
38
+ super
39
+ # A fragment can come before the operations which use it, and many operations can use it.
40
+ # So, check its variable usages after the visit, against each operation which uses it.
41
+ fragment_usages = @fragment_variable_usages
42
+ return if fragment_usages.nil?
43
+
44
+ dependencies = context.dependencies
45
+ @operation_declared_variables.each do |definition, declared_variables|
46
+ next if declared_variables.empty?
47
+
48
+ variable_types = {} #: Hash[String, untyped]
49
+ checked_fragments = {}.compare_by_identity
50
+ dependencies[definition].each do |fragment_definition|
51
+ next if checked_fragments.key?(fragment_definition)
52
+ checked_fragments[fragment_definition] = true
53
+ usages = fragment_usages[fragment_definition]
54
+ next if usages.nil?
55
+
56
+ usages.each do |usage|
57
+ var_defn_ast = declared_variables[usage.variable_name]
58
+ # If it's undefined, VariablesAreUsedAndDefined adds an error
59
+ next if var_defn_ast.nil?
60
+ var_type = variable_types.fetch(usage.variable_name) { variable_types[usage.variable_name] = usage_variable_type(var_defn_ast) }
61
+ next if var_type.nil?
62
+ # The result depends only on the usage and the variable type, so check each pair once.
63
+ # (`type_from_ast` returns the same object for the same type.)
64
+ checked = (usage.checked_variable_types ||= {}.compare_by_identity)
65
+ next if checked.key?(var_type)
66
+ checked[var_type] = true
67
+ validate_usage(usage.argument_owner, usage.arg_node, var_defn_ast, usage.list_depth, path: usage.path, var_type: var_type)
68
+ end
69
+ end
21
70
  end
22
- node_values = node_values.select { |value| value.is_a? GraphQL::Language::Nodes::VariableIdentifier }
71
+ end
72
+
73
+ def on_argument(node, parent)
74
+ variables = variables_in_value(node.value, 0, nil)
23
75
 
24
- if !node_values.empty?
76
+ if variables
25
77
  argument_owner = case parent
26
78
  when GraphQL::Language::Nodes::Field
27
79
  context.field_definition
@@ -39,11 +91,38 @@ module GraphQL
39
91
  raise("Unexpected argument parent: #{parent}")
40
92
  end
41
93
 
42
- node_values.each do |node_value|
43
- var_defn_ast = @declared_variables[node_value.name]
44
- # Might be undefined :(
45
- # VariablesAreUsedAndDefined can't finalize its search until the end of the document.
46
- var_defn_ast && argument_owner && validate_usage(argument_owner, node, var_defn_ast)
94
+ if (fragment_definition = @variable_usages_fragment_definition)
95
+ if argument_owner
96
+ usages = ((@fragment_variable_usages ||= {}.compare_by_identity)[fragment_definition] ||= [])
97
+ path = context.path
98
+ variables.each do |(variable, list_depth)|
99
+ usages << FragmentVariableUsage.new(argument_owner, node, variable.name, list_depth, path)
100
+ # Previous versions checked a fragment against the last operation before it
101
+ if @allow_legacy_invalid_variable_usages != false && (var_defn_ast = @declared_variables[variable.name])
102
+ add_legacy_error(argument_owner, node, var_defn_ast, list_depth)
103
+ end
104
+ end
105
+ end
106
+ elsif argument_owner
107
+ variables.each do |(variable, list_depth)|
108
+ var_defn_ast = @declared_variables[variable.name]
109
+ # Might be undefined :(
110
+ # VariablesAreUsedAndDefined can't finalize its search until the end of the document.
111
+ next if var_defn_ast.nil?
112
+
113
+ legacy_reported = false
114
+ if @allow_legacy_invalid_variable_usages != false
115
+ # The legacy check is the same, except for a `= null` default or a variable in a nested or mixed list
116
+ if var_defn_ast.default_value.is_a?(GraphQL::Language::Nodes::NullValue) ||
117
+ list_depth > 1 ||
118
+ (list_depth == 1 && depth_of_array(node.value) != 1)
119
+ add_legacy_error(argument_owner, node, var_defn_ast, list_depth)
120
+ else
121
+ legacy_reported = true
122
+ end
123
+ end
124
+ validate_usage(argument_owner, node, var_defn_ast, list_depth, legacy_reported: legacy_reported)
125
+ end
47
126
  end
48
127
  end
49
128
  super
@@ -51,21 +130,76 @@ module GraphQL
51
130
 
52
131
  private
53
132
 
54
- def validate_usage(argument_owner, arg_node, ast_var)
55
- var_type = context.schema.type_from_ast(ast_var.type, context: context)
56
- if var_type.nil?
57
- return
133
+ # Variables inside input objects are found when their own arguments are visited.
134
+ #: (untyped value, Integer list_depth, Array[[GraphQL::Language::Nodes::VariableIdentifier, Integer]]? variables) -> Array[[GraphQL::Language::Nodes::VariableIdentifier, Integer]]?
135
+ def variables_in_value(value, list_depth, variables)
136
+ case value
137
+ when GraphQL::Language::Nodes::VariableIdentifier
138
+ (variables ||= []) << [value, list_depth]
139
+ when Array
140
+ value.each { |item| variables = variables_in_value(item, list_depth + 1, variables) }
58
141
  end
59
- if !ast_var.default_value.nil?
142
+ variables
143
+ end
144
+
145
+ #: (GraphQL::Language::Nodes::VariableDefinition ast_var, ?legacy: bool) -> untyped
146
+ def usage_variable_type(ast_var, legacy: false)
147
+ var_type = context.schema.type_from_ast(ast_var.type, context: context)
148
+ return nil if var_type.nil?
149
+ default_value = ast_var.default_value
150
+ # An explicit `= null` default doesn't make the variable non-null (but previous versions treated it as non-null)
151
+ if !default_value.nil? && (legacy || !default_value.is_a?(GraphQL::Language::Nodes::NullValue))
60
152
  unless var_type.kind.non_null?
61
153
  # If the value is required, but the argument is not,
62
- # and yet there's a non-nil default, then we impliclty
154
+ # and yet there's a non-null default, then we impliclty
63
155
  # make the argument also a required type.
64
156
  var_type = var_type.to_non_null_type
65
157
  end
66
158
  end
159
+ var_type
160
+ end
161
+
162
+ # `legacy_reported:` is true when the legacy check has the same result, so an error isn't a legacy invalid usage.
163
+ #: (untyped argument_owner, GraphQL::Language::Nodes::Argument arg_node, GraphQL::Language::Nodes::VariableDefinition ast_var, Integer list_depth, ?path: Array[String]?, ?var_type: untyped, ?legacy_reported: bool) -> void
164
+ def validate_usage(argument_owner, arg_node, ast_var, list_depth, path: nil, var_type: usage_variable_type(ast_var), legacy_reported: false)
165
+ return if var_type.nil?
67
166
 
68
167
  arg_defn = @types.argument(argument_owner, arg_node.name)
168
+ error_message = usage_error(arg_defn, var_type, list_depth)
169
+ return if error_message.nil?
170
+
171
+ message_override = nil
172
+ if @allow_legacy_invalid_variable_usages != false && !legacy_reported
173
+ # The legacy check already added its error for this argument and variable
174
+ return if @legacy_errors&.dig(arg_node, ast_var.name)
175
+
176
+ if @allow_legacy_invalid_variable_usages == true
177
+ legacy_handling = @schema.legacy_invalid_variable_usages(context.query, ast_var, arg_node)
178
+ case legacy_handling
179
+ when nil
180
+ return
181
+ when :return_validation_error
182
+ # Add the error below
183
+ when String
184
+ message_override = legacy_handling
185
+ else
186
+ raise GraphQL::Error, "#{@schema}.legacy_invalid_variable_usages returned unexpected value: #{legacy_handling.inspect}. Expected `nil`, String, or `:return_validation_error`."
187
+ end
188
+ else
189
+ context.query.logger.warn <<~WARN
190
+ GraphQL-Ruby encountered an invalid variable usage in this query: `$#{ast_var.name}` (at #{ast_var.line}:#{ast_var.col}) for argument `#{arg_node.name}` (at #{arg_node.line}:#{arg_node.col}).
191
+ This will return an error in future GraphQL-Ruby versions, as per the GraphQL specification
192
+ Learn about migrating here: https://graphql-ruby.org/api-doc/#{GraphQL::VERSION}/GraphQL/Schema.html#allow_legacy_invalid_variable_usages-class_method
193
+ WARN
194
+ return
195
+ end
196
+ end
197
+
198
+ create_error(error_message, wrap_var_type_in_lists(var_type, list_depth), ast_var, arg_defn, arg_node, path, message_override)
199
+ end
200
+
201
+ #: (untyped arg_defn, untyped var_type, Integer list_depth) -> String?
202
+ def usage_error(arg_defn, var_type, list_depth)
69
203
  arg_defn_type = arg_defn.type
70
204
 
71
205
  # If the argument is non-null, but it was given a default value,
@@ -77,52 +211,43 @@ module GraphQL
77
211
  var_inner_type = var_type.unwrap
78
212
  arg_inner_type = arg_defn_type.unwrap
79
213
 
80
- var_type = wrap_var_type_with_depth_of_arg(var_type, arg_node)
214
+ var_type = wrap_var_type_in_lists(var_type, list_depth)
81
215
 
82
216
  if var_inner_type != arg_inner_type
83
- create_error("Type mismatch", var_type, ast_var, arg_defn, arg_node)
217
+ "Type mismatch"
84
218
  elsif list_dimension(var_type) != list_dimension(arg_defn_type)
85
- create_error("List dimension mismatch", var_type, ast_var, arg_defn, arg_node)
219
+ "List dimension mismatch"
86
220
  elsif !non_null_levels_match(arg_defn_type, var_type)
87
- create_error("Nullability mismatch", var_type, ast_var, arg_defn, arg_node)
221
+ "Nullability mismatch"
88
222
  end
89
223
  end
90
224
 
91
- def create_error(error_message, var_type, ast_var, arg_defn, arg_node)
92
- add_error(GraphQL::StaticValidation::VariableUsagesAreAllowedError.new(
93
- "#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_type_signature} / #{arg_defn.type.to_type_signature})",
94
- nodes: arg_node,
95
- name: ast_var.name,
96
- type: var_type.to_type_signature,
97
- argument: arg_node.name,
98
- error: error_message
99
- ))
100
- end
101
-
102
- def wrap_var_type_with_depth_of_arg(var_type, arg_node)
103
- arg_node_value = arg_node.value
104
- return var_type unless arg_node_value.is_a?(Array)
105
- new_var_type = var_type
225
+ # Add the error which previous versions added for this usage, if any, so that the legacy behavior rejects the same documents.
226
+ # They didn't check variables in nested lists, used the depth of the whole list value for each variable in it,
227
+ # and treated a `= null` default as non-null.
228
+ #: (untyped argument_owner, GraphQL::Language::Nodes::Argument arg_node, GraphQL::Language::Nodes::VariableDefinition ast_var, Integer list_depth) -> void
229
+ def add_legacy_error(argument_owner, arg_node, ast_var, list_depth)
230
+ return if list_depth > 1
231
+ var_type = usage_variable_type(ast_var, legacy: true)
232
+ return if var_type.nil?
106
233
 
107
- depth_of_array(arg_node_value).times do
108
- # Since the array _is_ present, treat it like a non-null type
109
- # (It satisfies a non-null requirement AND a nullable requirement)
110
- new_var_type = new_var_type.to_list_type.to_non_null_type
111
- end
234
+ list_depth = depth_of_array(arg_node.value) if list_depth == 1
235
+ arg_defn = @types.argument(argument_owner, arg_node.name)
236
+ error_message = usage_error(arg_defn, var_type, list_depth)
237
+ return if error_message.nil?
112
238
 
113
- new_var_type
239
+ ((@legacy_errors ||= {}.compare_by_identity)[arg_node] ||= {})[ast_var.name] = true
240
+ create_error(error_message, wrap_var_type_in_lists(var_type, list_depth), ast_var, arg_defn, arg_node, nil, nil)
114
241
  end
115
242
 
116
- # @return [Integer] Returns the max depth of `array`, or `0` if it isn't an array at all
117
- def depth_of_array(array)
118
- case array
119
- when Array
243
+ # The maximum depth of list literals in `value`
244
+ #: (untyped value) -> Integer
245
+ def depth_of_array(value)
246
+ if value.is_a?(Array)
120
247
  max_child_depth = 0
121
- array.each do |item|
248
+ value.each do |item|
122
249
  item_depth = depth_of_array(item)
123
- if item_depth > max_child_depth
124
- max_child_depth = item_depth
125
- end
250
+ max_child_depth = item_depth if item_depth > max_child_depth
126
251
  end
127
252
  1 + max_child_depth
128
253
  else
@@ -130,6 +255,37 @@ module GraphQL
130
255
  end
131
256
  end
132
257
 
258
+ #: (String error_message, untyped var_type, GraphQL::Language::Nodes::VariableDefinition ast_var, untyped arg_defn, GraphQL::Language::Nodes::Argument arg_node, Array[String]? path, String? message_override) -> void
259
+ def create_error(error_message, var_type, ast_var, arg_defn, arg_node, path, message_override)
260
+ message = "#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_type_signature} / #{arg_defn.type.to_type_signature})"
261
+ if path
262
+ # Many operations can use one fragment, so add each error only once.
263
+ reported = (@reported_fragment_variable_errors ||= {}.compare_by_identity)[arg_node] ||= {}
264
+ return if reported.key?(message)
265
+ reported[message] = true
266
+ end
267
+
268
+ add_error(GraphQL::StaticValidation::VariableUsagesAreAllowedError.new(
269
+ message_override || message,
270
+ nodes: arg_node,
271
+ name: ast_var.name,
272
+ type: var_type.to_type_signature,
273
+ argument: arg_node.name,
274
+ error: error_message
275
+ ), path: path)
276
+ end
277
+
278
+ # A variable in list literals is used as a list item, so wrap its type in one list for each list literal.
279
+ #: (untyped var_type, Integer list_depth) -> untyped
280
+ def wrap_var_type_in_lists(var_type, list_depth)
281
+ list_depth.times do
282
+ # Since the array _is_ present, treat it like a non-null type
283
+ # (It satisfies a non-null requirement AND a nullable requirement)
284
+ var_type = var_type.to_list_type.to_non_null_type
285
+ end
286
+ var_type
287
+ end
288
+
133
289
  def list_dimension(type)
134
290
  if type.kind.list?
135
291
  1 + list_dimension(type.of_type)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
4
5
  class VariableUsagesAreAllowedError < StaticValidation::Error
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
5
+ #--
6
+ # @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
4
7
  module VariablesAreInputTypes
5
8
  def on_variable_definition(node, parent)
6
9
  type_name = get_type_name(node.type)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
4
5
  class VariablesAreInputTypesError < StaticValidation::Error
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
4
5
  # The problem is
@@ -11,6 +12,8 @@ module GraphQL
11
12
  # - re-visiting the AST for each validator
12
13
  # - allowing validators to say `followSpreads: true`
13
14
  #
15
+ #--
16
+ # @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
14
17
  module VariablesAreUsedAndDefined
15
18
  class VariableUsage
16
19
  attr_accessor :ast_node, :used_by, :declared_by, :path
@@ -89,13 +92,13 @@ module GraphQL
89
92
  private
90
93
 
91
94
  # Follow spreads in `node`, looking them up from `spreads_for_context` and finding their match in `fragment_definitions`.
92
- # Use those fragments to update {VariableUsage}s in `parent_variables`.
95
+ # Use those fragments to update [VariableUsage](rdoc-ref:VariableUsage)s in `parent_variables`.
93
96
  # Avoid infinite loops by skipping anything in `visited_fragments`.
94
97
  def follow_spreads(node, parent_variables, spreads_for_context, fragment_definitions, visited_fragments)
95
98
  spreads = spreads_for_context[node] - visited_fragments
96
99
  spreads.each do |spread_name|
97
- def_node = nil
98
- variables = nil
100
+ def_node = nil #: untyped
101
+ variables = nil #: untyped
99
102
  # Implement `.find` by hand to avoid Ruby's internal allocations
100
103
  fragment_definitions.each do |frag_def_node, vars|
101
104
  if frag_def_node.name == spread_name
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
4
5
  class VariablesAreUsedAndDefinedError < StaticValidation::Error
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
4
5
  # The validation context gets passed to each validator.
5
6
  #
6
- # It exposes a {GraphQL::Language::Visitor} where validators may add hooks. ({Language::Visitor#visit} is called in {Validator#validate})
7
+ # It exposes a [GraphQL::Language::Visitor](rdoc-ref:GraphQL::Language::Visitor) where validators may add hooks. ([Language::Visitor#visit](rdoc-ref:Language::Visitor#visit) is called in [Validator#validate](rdoc-ref:Validator#validate))
7
8
  #
8
9
  # It provides access to the schema & fragments which validators may read from.
9
10
  #
@@ -52,7 +53,7 @@ module GraphQL
52
53
 
53
54
  def did_you_mean_suggestion(name, options)
54
55
  if did_you_mean = schema.did_you_mean
55
- suggestions = did_you_mean::SpellChecker.new(dictionary: options).correct(name)
56
+ suggestions = did_you_mean.const_get(:SpellChecker).new(dictionary: options).correct(name)
56
57
  case suggestions.size
57
58
  when 0
58
59
  ""
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module StaticValidation
4
5
  class ValidationTimeoutError < StaticValidation::Error
@@ -1,33 +1,52 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  require "timeout"
3
4
 
4
5
  module GraphQL
5
6
  module StaticValidation
6
- # Initialized with a {GraphQL::Schema}, then it can validate {GraphQL::Language::Nodes::Documents}s based on that schema.
7
+ # Initialized with a [GraphQL::Schema](rdoc-ref:GraphQL::Schema), then it can validate [GraphQL::Language::Nodes::Document](rdoc-ref:GraphQL::Language::Nodes::Document) nodes based on that schema.
7
8
  #
8
- # By default, it's used by {GraphQL::Query}
9
+ # By default, it's used by [GraphQL::Query](rdoc-ref:GraphQL::Query)
9
10
  #
10
- # @example Validate a query
11
- # validator = GraphQL::StaticValidation::Validator.new(schema: MySchema)
12
- # query = GraphQL::Query.new(MySchema, query_string)
13
- # errors = validator.validate(query)[:errors]
11
+ # **Examples**
14
12
  #
13
+ # **Example: Validate a query**
14
+ #
15
+ # ```ruby
16
+ # validator = GraphQL::StaticValidation::Validator.new(schema: MySchema)
17
+ # query = GraphQL::Query.new(MySchema, query_string)
18
+ # errors = validator.validate(query)[:errors]
19
+ # ```
15
20
  class Validator
16
- # @param schema [GraphQL::Schema]
17
- # @param rules [Array<#validate(context)>] a list of rules to use when validating
21
+ # **Parameters**
22
+ #
23
+ # - `schema` (`GraphQL::Schema`)
24
+ # - `rules` (`Array<#validate(context)>`) — a list of rules to use when validating
25
+ #
26
+ # :call-seq:
27
+ # initialize(GraphQL::Schema schema:, Array[#validate(context)] rules:)
18
28
  def initialize(schema:, rules: GraphQL::StaticValidation::ALL_RULES)
19
29
  @schema = schema
20
30
  @rules = rules
21
31
  end
22
32
 
23
33
  # Validate `query` against the schema. Returns an array of message hashes.
24
- # @param query [GraphQL::Query]
25
- # @param validate [Boolean]
26
- # @param timeout [Float] Number of seconds to wait before aborting validation. Any positive number may be used, including Floats to specify fractional seconds.
27
- # @param max_errors [Integer] Maximum number of errors before aborting validation. Any positive number will limit the number of errors. Defaults to nil for no limit.
28
- # @return [Array<Hash>]
34
+ #
35
+ # **Parameters**
36
+ #
37
+ # - `query` (`GraphQL::Query`)
38
+ # - `validate` (`Boolean`)
39
+ # - `timeout` (`Float`) — Number of seconds to wait before aborting validation. Any positive number may be used, including Floats to specify fractional seconds.
40
+ # - `max_errors` (`Integer`) — Maximum number of errors before aborting validation. Any positive number will limit the number of errors. Defaults to nil for no limit.
41
+ #
42
+ # **Returns**
43
+ #
44
+ # - `Array<Hash>`
45
+ #
46
+ # :call-seq:
47
+ # validate(GraphQL::Query query, bool validate:, Float timeout:, Integer max_errors:) -> Array[Hash]
29
48
  def validate(query, validate: true, timeout: nil, max_errors: nil)
30
- errors = nil
49
+ errors = nil #: untyped
31
50
  query.current_trace.begin_validate(query, validate)
32
51
  query.current_trace.validate(validate: validate, query: query) do
33
52
  begin_t = Time.now
@@ -70,8 +89,14 @@ module GraphQL
70
89
  end
71
90
 
72
91
  # Invoked when static validation times out.
73
- # @param query [GraphQL::Query]
74
- # @param context [GraphQL::StaticValidation::ValidationContext]
92
+ #
93
+ # **Parameters**
94
+ #
95
+ # - `query` (`GraphQL::Query`)
96
+ # - `context` (`GraphQL::StaticValidation::ValidationContext`)
97
+ #
98
+ # :call-seq:
99
+ # handle_timeout(GraphQL::Query query, GraphQL::StaticValidation::ValidationContext context)
75
100
  def handle_timeout(query, context)
76
101
  context.errors << GraphQL::StaticValidation::ValidationTimeoutError.new(
77
102
  "Timeout on validation of query"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  require "graphql/static_validation/error"
3
4
  require "graphql/static_validation/definition_dependencies"
4
5
  require "graphql/static_validation/validator"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  class StringEncodingError < GraphQL::RuntimeTypeError
4
5
  attr_reader :string, :field, :path