graphql 1.9.5 → 1.13.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (659) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/core.rb +21 -9
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +48 -8
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +63 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +7 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +3 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +4 -0
  28. data/lib/generators/graphql/templates/base_object.erb +3 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +21 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +23 -28
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/analyze_query.rb +7 -0
  49. data/lib/graphql/analysis/ast/analyzer.rb +34 -12
  50. data/lib/graphql/analysis/ast/field_usage.rb +29 -2
  51. data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
  52. data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
  53. data/lib/graphql/analysis/ast/query_complexity.rb +179 -64
  54. data/lib/graphql/analysis/ast/query_depth.rb +16 -26
  55. data/lib/graphql/analysis/ast/visitor.rb +46 -32
  56. data/lib/graphql/analysis/ast.rb +23 -14
  57. data/lib/graphql/analysis/query_depth.rb +4 -17
  58. data/lib/graphql/argument.rb +16 -38
  59. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  60. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  61. data/lib/graphql/backtrace/table.rb +44 -5
  62. data/lib/graphql/backtrace/traced_error.rb +0 -1
  63. data/lib/graphql/backtrace/tracer.rb +40 -9
  64. data/lib/graphql/backtrace.rb +28 -19
  65. data/lib/graphql/backwards_compatibility.rb +2 -1
  66. data/lib/graphql/base_type.rb +11 -5
  67. data/lib/graphql/boolean_type.rb +1 -1
  68. data/lib/graphql/coercion_error.rb +8 -0
  69. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  70. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  71. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
  72. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  73. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  74. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  75. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  76. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  77. data/lib/graphql/dataloader/request.rb +19 -0
  78. data/lib/graphql/dataloader/request_all.rb +19 -0
  79. data/lib/graphql/dataloader/source.rb +155 -0
  80. data/lib/graphql/dataloader.rb +308 -0
  81. data/lib/graphql/date_encoding_error.rb +16 -0
  82. data/lib/graphql/define/assign_enum_value.rb +1 -1
  83. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  84. data/lib/graphql/define/assign_object_field.rb +3 -3
  85. data/lib/graphql/define/defined_object_proxy.rb +3 -0
  86. data/lib/graphql/define/instance_definable.rb +65 -110
  87. data/lib/graphql/define/type_definer.rb +5 -5
  88. data/lib/graphql/deprecated_dsl.rb +18 -5
  89. data/lib/graphql/deprecation.rb +9 -0
  90. data/lib/graphql/directive/deprecated_directive.rb +1 -12
  91. data/lib/graphql/directive/include_directive.rb +1 -1
  92. data/lib/graphql/directive/skip_directive.rb +1 -1
  93. data/lib/graphql/directive.rb +9 -6
  94. data/lib/graphql/enum_type.rb +14 -74
  95. data/lib/graphql/execution/directive_checks.rb +2 -2
  96. data/lib/graphql/execution/errors.rb +163 -0
  97. data/lib/graphql/execution/execute.rb +10 -3
  98. data/lib/graphql/execution/instrumentation.rb +1 -1
  99. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  100. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  101. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  102. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  103. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  104. data/lib/graphql/execution/interpreter/runtime.rb +737 -376
  105. data/lib/graphql/execution/interpreter.rb +42 -19
  106. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  107. data/lib/graphql/execution/lazy.rb +5 -1
  108. data/lib/graphql/execution/lookahead.rb +39 -114
  109. data/lib/graphql/execution/multiplex.rb +58 -29
  110. data/lib/graphql/execution.rb +1 -0
  111. data/lib/graphql/execution_error.rb +3 -2
  112. data/lib/graphql/field.rb +15 -119
  113. data/lib/graphql/filter.rb +1 -1
  114. data/lib/graphql/float_type.rb +1 -1
  115. data/lib/graphql/function.rb +6 -31
  116. data/lib/graphql/id_type.rb +1 -1
  117. data/lib/graphql/input_object_type.rb +11 -26
  118. data/lib/graphql/int_type.rb +1 -1
  119. data/lib/graphql/integer_decoding_error.rb +17 -0
  120. data/lib/graphql/integer_encoding_error.rb +18 -2
  121. data/lib/graphql/interface_type.rb +10 -24
  122. data/lib/graphql/internal_representation/document.rb +2 -2
  123. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  124. data/lib/graphql/internal_representation/scope.rb +2 -2
  125. data/lib/graphql/internal_representation/visit.rb +2 -2
  126. data/lib/graphql/introspection/base_object.rb +2 -5
  127. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  128. data/lib/graphql/introspection/directive_type.rb +12 -6
  129. data/lib/graphql/introspection/entry_points.rb +9 -8
  130. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  131. data/lib/graphql/introspection/field_type.rb +9 -5
  132. data/lib/graphql/introspection/input_value_type.rb +41 -11
  133. data/lib/graphql/introspection/introspection_query.rb +6 -92
  134. data/lib/graphql/introspection/schema_type.rb +13 -12
  135. data/lib/graphql/introspection/type_type.rb +27 -17
  136. data/lib/graphql/introspection.rb +99 -0
  137. data/lib/graphql/invalid_null_error.rb +18 -0
  138. data/lib/graphql/language/block_string.rb +22 -7
  139. data/lib/graphql/language/cache.rb +37 -0
  140. data/lib/graphql/language/definition_slice.rb +21 -10
  141. data/lib/graphql/language/document_from_schema_definition.rb +126 -67
  142. data/lib/graphql/language/lexer.rb +180 -141
  143. data/lib/graphql/language/lexer.rl +75 -51
  144. data/lib/graphql/language/nodes.rb +92 -108
  145. data/lib/graphql/language/parser.rb +933 -897
  146. data/lib/graphql/language/parser.y +129 -103
  147. data/lib/graphql/language/printer.rb +11 -2
  148. data/lib/graphql/language/sanitized_printer.rb +222 -0
  149. data/lib/graphql/language/token.rb +1 -1
  150. data/lib/graphql/language/visitor.rb +11 -8
  151. data/lib/graphql/language.rb +3 -1
  152. data/lib/graphql/name_validator.rb +2 -7
  153. data/lib/graphql/non_null_type.rb +0 -10
  154. data/lib/graphql/object_type.rb +47 -58
  155. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  156. data/lib/graphql/pagination/array_connection.rb +77 -0
  157. data/lib/graphql/pagination/connection.rb +226 -0
  158. data/lib/graphql/pagination/connections.rb +160 -0
  159. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  160. data/lib/graphql/pagination/relation_connection.rb +226 -0
  161. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  162. data/lib/graphql/pagination.rb +6 -0
  163. data/lib/graphql/parse_error.rb +0 -1
  164. data/lib/graphql/query/arguments.rb +29 -19
  165. data/lib/graphql/query/arguments_cache.rb +1 -2
  166. data/lib/graphql/query/context.rb +81 -14
  167. data/lib/graphql/query/executor.rb +0 -1
  168. data/lib/graphql/query/fingerprint.rb +26 -0
  169. data/lib/graphql/query/input_validation_result.rb +32 -6
  170. data/lib/graphql/query/literal_input.rb +31 -10
  171. data/lib/graphql/query/null_context.rb +28 -8
  172. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  173. data/lib/graphql/query/serial_execution.rb +1 -0
  174. data/lib/graphql/query/validation_pipeline.rb +6 -4
  175. data/lib/graphql/query/variable_validation_error.rb +3 -3
  176. data/lib/graphql/query/variables.rb +51 -9
  177. data/lib/graphql/query.rb +97 -23
  178. data/lib/graphql/railtie.rb +9 -1
  179. data/lib/graphql/rake_task/validate.rb +3 -0
  180. data/lib/graphql/rake_task.rb +12 -9
  181. data/lib/graphql/relay/array_connection.rb +11 -13
  182. data/lib/graphql/relay/base_connection.rb +33 -16
  183. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  184. data/lib/graphql/relay/connection_type.rb +18 -4
  185. data/lib/graphql/relay/edge_type.rb +1 -0
  186. data/lib/graphql/relay/edges_instrumentation.rb +1 -2
  187. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  188. data/lib/graphql/relay/mutation.rb +3 -87
  189. data/lib/graphql/relay/node.rb +5 -2
  190. data/lib/graphql/relay/page_info.rb +1 -1
  191. data/lib/graphql/relay/range_add.rb +27 -9
  192. data/lib/graphql/relay/relation_connection.rb +17 -15
  193. data/lib/graphql/relay/type_extensions.rb +2 -0
  194. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  195. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  196. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  197. data/lib/graphql/rubocop.rb +4 -0
  198. data/lib/graphql/scalar_type.rb +18 -62
  199. data/lib/graphql/schema/addition.rb +247 -0
  200. data/lib/graphql/schema/argument.rb +289 -11
  201. data/lib/graphql/schema/base_64_bp.rb +3 -2
  202. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  203. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  204. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  205. data/lib/graphql/schema/build_from_definition.rb +323 -203
  206. data/lib/graphql/schema/built_in_types.rb +5 -5
  207. data/lib/graphql/schema/default_type_error.rb +2 -0
  208. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  209. data/lib/graphql/schema/directive/feature.rb +2 -2
  210. data/lib/graphql/schema/directive/flagged.rb +57 -0
  211. data/lib/graphql/schema/directive/include.rb +2 -2
  212. data/lib/graphql/schema/directive/skip.rb +2 -2
  213. data/lib/graphql/schema/directive/transform.rb +14 -2
  214. data/lib/graphql/schema/directive.rb +136 -6
  215. data/lib/graphql/schema/enum.rb +121 -12
  216. data/lib/graphql/schema/enum_value.rb +23 -6
  217. data/lib/graphql/schema/field/connection_extension.rb +46 -20
  218. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  219. data/lib/graphql/schema/field.rb +515 -191
  220. data/lib/graphql/schema/field_extension.rb +89 -2
  221. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  222. data/lib/graphql/schema/finder.rb +16 -14
  223. data/lib/graphql/schema/input_object.rb +178 -34
  224. data/lib/graphql/schema/interface.rb +35 -25
  225. data/lib/graphql/schema/introspection_system.rb +111 -35
  226. data/lib/graphql/schema/late_bound_type.rb +3 -2
  227. data/lib/graphql/schema/list.rb +65 -1
  228. data/lib/graphql/schema/loader.rb +147 -97
  229. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  230. data/lib/graphql/schema/member/base_dsl_methods.rb +40 -45
  231. data/lib/graphql/schema/member/build_type.rb +19 -8
  232. data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
  233. data/lib/graphql/schema/member/has_arguments.rb +212 -22
  234. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  235. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  236. data/lib/graphql/schema/member/has_directives.rb +98 -0
  237. data/lib/graphql/schema/member/has_fields.rb +113 -28
  238. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  239. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  240. data/lib/graphql/schema/member/has_validators.rb +31 -0
  241. data/lib/graphql/schema/member/instrumentation.rb +6 -2
  242. data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
  243. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  244. data/lib/graphql/schema/member/validates_input.rb +33 -0
  245. data/lib/graphql/schema/member.rb +11 -0
  246. data/lib/graphql/schema/middleware_chain.rb +1 -1
  247. data/lib/graphql/schema/mutation.rb +5 -1
  248. data/lib/graphql/schema/non_null.rb +37 -1
  249. data/lib/graphql/schema/object.rb +52 -37
  250. data/lib/graphql/schema/possible_types.rb +12 -7
  251. data/lib/graphql/schema/printer.rb +17 -34
  252. data/lib/graphql/schema/relay_classic_mutation.rb +51 -7
  253. data/lib/graphql/schema/resolver/has_payload_type.rb +36 -5
  254. data/lib/graphql/schema/resolver.rb +159 -59
  255. data/lib/graphql/schema/scalar.rb +43 -3
  256. data/lib/graphql/schema/subscription.rb +83 -25
  257. data/lib/graphql/schema/timeout.rb +123 -0
  258. data/lib/graphql/schema/timeout_middleware.rb +6 -3
  259. data/lib/graphql/schema/traversal.rb +2 -2
  260. data/lib/graphql/schema/type_expression.rb +21 -13
  261. data/lib/graphql/schema/type_membership.rb +48 -0
  262. data/lib/graphql/schema/union.rb +67 -6
  263. data/lib/graphql/schema/unique_within_type.rb +1 -2
  264. data/lib/graphql/schema/validation.rb +30 -8
  265. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  266. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  267. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  268. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  269. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  270. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  271. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  272. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  273. data/lib/graphql/schema/validator.rb +171 -0
  274. data/lib/graphql/schema/warden.rb +263 -30
  275. data/lib/graphql/schema/wrapper.rb +1 -1
  276. data/lib/graphql/schema.rb +1016 -256
  277. data/lib/graphql/static_validation/all_rules.rb +2 -0
  278. data/lib/graphql/static_validation/base_visitor.rb +17 -10
  279. data/lib/graphql/static_validation/definition_dependencies.rb +21 -13
  280. data/lib/graphql/static_validation/error.rb +3 -1
  281. data/lib/graphql/static_validation/literal_validator.rb +52 -27
  282. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
  283. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
  284. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  285. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  286. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  287. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
  288. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  289. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  290. data/lib/graphql/static_validation/rules/fields_will_merge.rb +105 -55
  291. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  292. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  293. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  294. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  295. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  296. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  297. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  298. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -3
  299. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  300. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  301. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  302. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  303. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  304. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  305. data/lib/graphql/static_validation/type_stack.rb +2 -2
  306. data/lib/graphql/static_validation/validation_context.rb +13 -3
  307. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  308. data/lib/graphql/static_validation/validator.rb +43 -9
  309. data/lib/graphql/static_validation.rb +1 -0
  310. data/lib/graphql/string_encoding_error.rb +13 -3
  311. data/lib/graphql/string_type.rb +1 -1
  312. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
  313. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  314. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  315. data/lib/graphql/subscriptions/event.rb +94 -26
  316. data/lib/graphql/subscriptions/instrumentation.rb +10 -6
  317. data/lib/graphql/subscriptions/serialize.rb +53 -6
  318. data/lib/graphql/subscriptions/subscription_root.rb +15 -5
  319. data/lib/graphql/subscriptions.rb +122 -54
  320. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  321. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  322. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  323. data/lib/graphql/tracing/data_dog_tracing.rb +32 -2
  324. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  325. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  326. data/lib/graphql/tracing/platform_tracing.rb +66 -7
  327. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  328. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  329. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  330. data/lib/graphql/tracing/skylight_tracing.rb +9 -0
  331. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  332. data/lib/graphql/tracing.rb +15 -35
  333. data/lib/graphql/types/big_int.rb +5 -1
  334. data/lib/graphql/types/int.rb +10 -3
  335. data/lib/graphql/types/iso_8601_date.rb +42 -0
  336. data/lib/graphql/types/iso_8601_date_time.rb +32 -8
  337. data/lib/graphql/types/relay/base_connection.rb +6 -88
  338. data/lib/graphql/types/relay/base_edge.rb +2 -37
  339. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  340. data/lib/graphql/types/relay/default_relay.rb +31 -0
  341. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  342. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  343. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  344. data/lib/graphql/types/relay/node.rb +2 -4
  345. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  346. data/lib/graphql/types/relay/node_field.rb +4 -23
  347. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  348. data/lib/graphql/types/relay/page_info.rb +2 -14
  349. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  350. data/lib/graphql/types/relay.rb +11 -3
  351. data/lib/graphql/types/string.rb +8 -2
  352. data/lib/graphql/types.rb +1 -0
  353. data/lib/graphql/unauthorized_error.rb +2 -2
  354. data/lib/graphql/union_type.rb +61 -46
  355. data/lib/graphql/unresolved_type_error.rb +2 -2
  356. data/lib/graphql/upgrader/member.rb +150 -112
  357. data/lib/graphql/upgrader/schema.rb +1 -0
  358. data/lib/graphql/version.rb +1 -1
  359. data/lib/graphql.rb +89 -18
  360. data/readme.md +4 -7
  361. metadata +115 -703
  362. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  363. data/lib/graphql/literal_validation_error.rb +0 -6
  364. data/lib/graphql/types/relay/base_field.rb +0 -22
  365. data/lib/graphql/types/relay/base_interface.rb +0 -29
  366. data/lib/graphql/types/relay/base_object.rb +0 -26
  367. data/spec/dummy/Gemfile +0 -12
  368. data/spec/dummy/Gemfile.lock +0 -157
  369. data/spec/dummy/README.md +0 -24
  370. data/spec/dummy/Rakefile +0 -7
  371. data/spec/dummy/app/assets/config/manifest.js +0 -1
  372. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  373. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  374. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  375. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  376. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  377. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  378. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  379. data/spec/dummy/app/jobs/application_job.rb +0 -3
  380. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  381. data/spec/dummy/app/views/pages/show.html +0 -16
  382. data/spec/dummy/bin/bundle +0 -4
  383. data/spec/dummy/bin/rails +0 -5
  384. data/spec/dummy/bin/rake +0 -5
  385. data/spec/dummy/bin/setup +0 -31
  386. data/spec/dummy/bin/update +0 -27
  387. data/spec/dummy/bin/yarn +0 -12
  388. data/spec/dummy/config/application.rb +0 -30
  389. data/spec/dummy/config/boot.rb +0 -4
  390. data/spec/dummy/config/cable.yml +0 -10
  391. data/spec/dummy/config/environment.rb +0 -6
  392. data/spec/dummy/config/environments/development.rb +0 -40
  393. data/spec/dummy/config/environments/production.rb +0 -76
  394. data/spec/dummy/config/environments/test.rb +0 -37
  395. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  396. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  397. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  398. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  399. data/spec/dummy/config/initializers/inflections.rb +0 -17
  400. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  401. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  402. data/spec/dummy/config/locales/en.yml +0 -33
  403. data/spec/dummy/config/puma.rb +0 -57
  404. data/spec/dummy/config/routes.rb +0 -4
  405. data/spec/dummy/config/secrets.yml +0 -32
  406. data/spec/dummy/config.ru +0 -6
  407. data/spec/dummy/log/test.log +0 -199
  408. data/spec/dummy/package.json +0 -5
  409. data/spec/dummy/public/404.html +0 -67
  410. data/spec/dummy/public/422.html +0 -67
  411. data/spec/dummy/public/500.html +0 -66
  412. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  413. data/spec/dummy/public/apple-touch-icon.png +0 -0
  414. data/spec/dummy/public/favicon.ico +0 -0
  415. data/spec/dummy/public/robots.txt +0 -1
  416. data/spec/dummy/test/application_system_test_case.rb +0 -6
  417. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  418. data/spec/dummy/test/test_helper.rb +0 -4
  419. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  420. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
  421. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
  422. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
  423. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
  424. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  425. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
  426. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
  427. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  428. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  429. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
  430. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  431. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
  432. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
  433. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
  434. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
  435. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  436. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
  437. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  438. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  439. data/spec/fixtures/upgrader/account.original.rb +0 -19
  440. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  441. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  442. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  443. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  444. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  445. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  446. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  447. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  448. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  449. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  450. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  451. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  452. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  453. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  454. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  455. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  456. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  457. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  458. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  459. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  460. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  461. data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
  462. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  463. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  464. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
  465. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  466. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  467. data/spec/graphql/analysis/ast_spec.rb +0 -269
  468. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  469. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  470. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
  471. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  472. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  473. data/spec/graphql/argument_spec.rb +0 -159
  474. data/spec/graphql/authorization_spec.rb +0 -974
  475. data/spec/graphql/backtrace_spec.rb +0 -206
  476. data/spec/graphql/base_type_spec.rb +0 -171
  477. data/spec/graphql/boolean_type_spec.rb +0 -21
  478. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  479. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  480. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  481. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  482. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  483. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  484. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  485. data/spec/graphql/directive_spec.rb +0 -295
  486. data/spec/graphql/enum_type_spec.rb +0 -158
  487. data/spec/graphql/execution/execute_spec.rb +0 -303
  488. data/spec/graphql/execution/instrumentation_spec.rb +0 -184
  489. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  490. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  491. data/spec/graphql/execution/lazy_spec.rb +0 -247
  492. data/spec/graphql/execution/lookahead_spec.rb +0 -390
  493. data/spec/graphql/execution/multiplex_spec.rb +0 -211
  494. data/spec/graphql/execution/typecast_spec.rb +0 -47
  495. data/spec/graphql/execution_error_spec.rb +0 -325
  496. data/spec/graphql/field_spec.rb +0 -246
  497. data/spec/graphql/float_type_spec.rb +0 -16
  498. data/spec/graphql/function_spec.rb +0 -152
  499. data/spec/graphql/id_type_spec.rb +0 -33
  500. data/spec/graphql/input_object_type_spec.rb +0 -25
  501. data/spec/graphql/int_type_spec.rb +0 -35
  502. data/spec/graphql/interface_type_spec.rb +0 -196
  503. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  504. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
  505. data/spec/graphql/introspection/directive_type_spec.rb +0 -61
  506. data/spec/graphql/introspection/input_value_type_spec.rb +0 -144
  507. data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
  508. data/spec/graphql/introspection/schema_type_spec.rb +0 -56
  509. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  510. data/spec/graphql/language/block_string_spec.rb +0 -70
  511. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  512. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  513. data/spec/graphql/language/equality_spec.rb +0 -84
  514. data/spec/graphql/language/generation_spec.rb +0 -38
  515. data/spec/graphql/language/lexer_spec.rb +0 -135
  516. data/spec/graphql/language/nodes_spec.rb +0 -67
  517. data/spec/graphql/language/parser_spec.rb +0 -183
  518. data/spec/graphql/language/printer_spec.rb +0 -215
  519. data/spec/graphql/language/visitor_spec.rb +0 -419
  520. data/spec/graphql/list_type_spec.rb +0 -57
  521. data/spec/graphql/non_null_type_spec.rb +0 -48
  522. data/spec/graphql/object_type_spec.rb +0 -197
  523. data/spec/graphql/query/arguments_spec.rb +0 -346
  524. data/spec/graphql/query/context_spec.rb +0 -292
  525. data/spec/graphql/query/executor_spec.rb +0 -341
  526. data/spec/graphql/query/literal_input_spec.rb +0 -91
  527. data/spec/graphql/query/result_spec.rb +0 -29
  528. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  529. data/spec/graphql/query_spec.rb +0 -800
  530. data/spec/graphql/rake_task_spec.rb +0 -59
  531. data/spec/graphql/scalar_type_spec.rb +0 -66
  532. data/spec/graphql/schema/argument_spec.rb +0 -152
  533. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
  534. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
  535. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  536. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  537. data/spec/graphql/schema/enum_spec.rb +0 -83
  538. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  539. data/spec/graphql/schema/field_extension_spec.rb +0 -137
  540. data/spec/graphql/schema/field_spec.rb +0 -301
  541. data/spec/graphql/schema/finder_spec.rb +0 -135
  542. data/spec/graphql/schema/input_object_spec.rb +0 -347
  543. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  544. data/spec/graphql/schema/interface_spec.rb +0 -215
  545. data/spec/graphql/schema/introspection_system_spec.rb +0 -56
  546. data/spec/graphql/schema/list_spec.rb +0 -46
  547. data/spec/graphql/schema/loader_spec.rb +0 -286
  548. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  549. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  550. data/spec/graphql/schema/member/scoped_spec.rb +0 -217
  551. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  552. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  553. data/spec/graphql/schema/mutation_spec.rb +0 -150
  554. data/spec/graphql/schema/non_null_spec.rb +0 -46
  555. data/spec/graphql/schema/object_spec.rb +0 -315
  556. data/spec/graphql/schema/printer_spec.rb +0 -869
  557. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -252
  558. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -88
  559. data/spec/graphql/schema/resolver_spec.rb +0 -714
  560. data/spec/graphql/schema/scalar_spec.rb +0 -101
  561. data/spec/graphql/schema/subscription_spec.rb +0 -440
  562. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  563. data/spec/graphql/schema/traversal_spec.rb +0 -222
  564. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  565. data/spec/graphql/schema/union_spec.rb +0 -72
  566. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  567. data/spec/graphql/schema/validation_spec.rb +0 -355
  568. data/spec/graphql/schema/warden_spec.rb +0 -926
  569. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
  570. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  571. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  572. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  573. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  574. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  575. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  576. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  577. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  578. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  579. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  580. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  581. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  582. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  583. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  584. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  585. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  586. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  587. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
  588. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -86
  589. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  590. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  591. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  592. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  593. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  594. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  595. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  596. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  597. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  598. data/spec/graphql/string_type_spec.rb +0 -80
  599. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  600. data/spec/graphql/subscriptions_spec.rb +0 -540
  601. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -84
  602. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -141
  603. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  604. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  605. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  606. data/spec/graphql/tracing_spec.rb +0 -52
  607. data/spec/graphql/types/big_int_spec.rb +0 -24
  608. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  609. data/spec/graphql/types/relay/base_edge_spec.rb +0 -33
  610. data/spec/graphql/union_type_spec.rb +0 -211
  611. data/spec/graphql/upgrader/member_spec.rb +0 -583
  612. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  613. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  614. data/spec/integration/mongoid/spec_helper.rb +0 -2
  615. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  616. data/spec/integration/mongoid/star_trek/schema.rb +0 -425
  617. data/spec/integration/rails/data.rb +0 -110
  618. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  619. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  620. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
  621. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  622. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  623. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  624. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  625. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  626. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  627. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  628. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  629. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
  630. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  631. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  632. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  633. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  634. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  635. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  636. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  637. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  638. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  639. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  640. data/spec/integration/rails/graphql/schema_spec.rb +0 -489
  641. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  642. data/spec/integration/rails/spec_helper.rb +0 -25
  643. data/spec/integration/tmp/app/graphql/types/bird_type.rb +0 -7
  644. data/spec/spec_helper.rb +0 -116
  645. data/spec/support/dummy/data.rb +0 -45
  646. data/spec/support/dummy/schema.rb +0 -511
  647. data/spec/support/error_bubbling_helpers.rb +0 -23
  648. data/spec/support/global_id.rb +0 -23
  649. data/spec/support/jazz.rb +0 -772
  650. data/spec/support/lazy_helpers.rb +0 -192
  651. data/spec/support/magic_cards/schema.graphql +0 -33
  652. data/spec/support/minimum_input_object.rb +0 -21
  653. data/spec/support/new_relic.rb +0 -27
  654. data/spec/support/parser/filename_example.graphql +0 -5
  655. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  656. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  657. data/spec/support/skylight.rb +0 -39
  658. data/spec/support/star_wars/schema.rb +0 -465
  659. data/spec/support/static_validation_helpers.rb +0 -32
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/schema/addition"
2
3
  require "graphql/schema/base_64_encoder"
3
4
  require "graphql/schema/catchall_middleware"
4
5
  require "graphql/schema/default_parse_error"
5
6
  require "graphql/schema/default_type_error"
7
+ require "graphql/schema/find_inherited_value"
6
8
  require "graphql/schema/finder"
7
9
  require "graphql/schema/invalid_type_error"
8
10
  require "graphql/schema/introspection_system"
@@ -11,6 +13,7 @@ require "graphql/schema/middleware_chain"
11
13
  require "graphql/schema/null_mask"
12
14
  require "graphql/schema/possible_types"
13
15
  require "graphql/schema/rescue_middleware"
16
+ require "graphql/schema/timeout"
14
17
  require "graphql/schema/timeout_middleware"
15
18
  require "graphql/schema/traversal"
16
19
  require "graphql/schema/type_expression"
@@ -19,6 +22,7 @@ require "graphql/schema/validation"
19
22
  require "graphql/schema/warden"
20
23
  require "graphql/schema/build_from_definition"
21
24
 
25
+ require "graphql/schema/validator"
22
26
  require "graphql/schema/member"
23
27
  require "graphql/schema/wrapper"
24
28
  require "graphql/schema/list"
@@ -34,10 +38,13 @@ require "graphql/schema/scalar"
34
38
  require "graphql/schema/object"
35
39
  require "graphql/schema/union"
36
40
  require "graphql/schema/directive"
41
+ require "graphql/schema/directive/deprecated"
37
42
  require "graphql/schema/directive/include"
38
43
  require "graphql/schema/directive/skip"
39
44
  require "graphql/schema/directive/feature"
45
+ require "graphql/schema/directive/flagged"
40
46
  require "graphql/schema/directive/transform"
47
+ require "graphql/schema/type_membership"
41
48
 
42
49
  require "graphql/schema/resolver"
43
50
  require "graphql/schema/mutation"
@@ -52,7 +59,6 @@ module GraphQL
52
59
  # - types for exposing your application
53
60
  # - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
54
61
  # - execution strategies for running incoming queries
55
- # - middleware for interacting with execution
56
62
  #
57
63
  # Schemas start with root types, {Schema#query}, {Schema#mutation} and {Schema#subscription}.
58
64
  # The schema will traverse the tree of fields & types, using those as starting points.
@@ -64,14 +70,10 @@ module GraphQL
64
70
  # Schemas can specify how queries should be executed against them.
65
71
  # `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
66
72
  # each apply to corresponding root types.
67
- #
68
- # A schema accepts a `Relay::GlobalNodeIdentification` instance for use with Relay IDs.
69
- #
73
+ # #
70
74
  # @example defining a schema
71
- # MySchema = GraphQL::Schema.define do
75
+ # class MySchema < GraphQL::Schema
72
76
  # query QueryType
73
- # middleware PermissionMiddleware
74
- # rescue_from(ActiveRecord::RecordNotFound) { "Not found" }
75
77
  # # If types are only connected by way of interfaces, they must be added here
76
78
  # orphan_types ImageType, AudioType
77
79
  # end
@@ -79,18 +81,103 @@ module GraphQL
79
81
  class Schema
80
82
  extend Forwardable
81
83
  extend GraphQL::Schema::Member::AcceptsDefinition
84
+ extend GraphQL::Schema::Member::HasAstNode
82
85
  include GraphQL::Define::InstanceDefinable
83
- accepts_definitions \
84
- :query, :mutation, :subscription,
86
+ extend GraphQL::Define::InstanceDefinable::DeprecatedDefine
87
+ extend GraphQL::Schema::FindInheritedValue
88
+
89
+ class DuplicateTypeNamesError < GraphQL::Error
90
+ def initialize(type_name:, first_definition:, second_definition:, path:)
91
+ super("Multiple definitions for `#{type_name}`. Previously found #{first_definition.inspect} (#{first_definition.class}), then found #{second_definition.inspect} (#{second_definition.class}) at #{path.join(".")}")
92
+ end
93
+ end
94
+
95
+ class DuplicateNamesError < GraphQL::Error; end
96
+
97
+ class UnresolvedLateBoundTypeError < GraphQL::Error
98
+ attr_reader :type
99
+ def initialize(type:)
100
+ @type = type
101
+ super("Late bound type was never found: #{type.inspect}")
102
+ end
103
+ end
104
+
105
+ module LazyHandlingMethods
106
+ # Call the given block at the right time, either:
107
+ # - Right away, if `value` is not registered with `lazy_resolve`
108
+ # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
109
+ # @api private
110
+ def after_lazy(value, &block)
111
+ if lazy?(value)
112
+ GraphQL::Execution::Lazy.new do
113
+ result = sync_lazy(value)
114
+ # The returned result might also be lazy, so check it, too
115
+ after_lazy(result, &block)
116
+ end
117
+ else
118
+ yield(value) if block_given?
119
+ end
120
+ end
121
+
122
+ # Override this method to handle lazy objects in a custom way.
123
+ # @param value [Object] an instance of a class registered with {.lazy_resolve}
124
+ # @return [Object] A GraphQL-ready (non-lazy) object
125
+ # @api private
126
+ def sync_lazy(value)
127
+ lazy_method = lazy_method_name(value)
128
+ if lazy_method
129
+ synced_value = value.public_send(lazy_method)
130
+ sync_lazy(synced_value)
131
+ else
132
+ value
133
+ end
134
+ end
135
+
136
+ # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
137
+ def lazy_method_name(obj)
138
+ lazy_methods.get(obj)
139
+ end
140
+
141
+ # @return [Boolean] True if this object should be lazily resolved
142
+ def lazy?(obj)
143
+ !!lazy_method_name(obj)
144
+ end
145
+
146
+ # Return a lazy if any of `maybe_lazies` are lazy,
147
+ # otherwise, call the block eagerly and return the result.
148
+ # @param maybe_lazies [Array]
149
+ # @api private
150
+ def after_any_lazies(maybe_lazies)
151
+ if maybe_lazies.any? { |l| lazy?(l) }
152
+ GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
153
+ yield result
154
+ end
155
+ else
156
+ yield maybe_lazies
157
+ end
158
+ end
159
+ end
160
+
161
+ include LazyHandlingMethods
162
+ extend LazyHandlingMethods
163
+
164
+ deprecated_accepts_definitions \
85
165
  :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
86
- :max_depth, :max_complexity, :default_max_page_size,
166
+ :validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
87
167
  :orphan_types, :resolve_type, :type_error, :parse_error,
88
168
  :error_bubbling,
89
169
  :raise_definition_error,
90
170
  :object_from_id, :id_from_object,
91
171
  :default_mask,
92
172
  :cursor_encoder,
93
- directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m } },
173
+ # If these are given as classes, normalize them. Accept `nil` when building from string.
174
+ query: ->(schema, t) { schema.query = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
175
+ mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
176
+ subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
177
+ disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
178
+ disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
179
+ disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
180
+ directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.graphql_name] = d; m } },
94
181
  directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
95
182
  instrument: ->(schema, type, instrumenter, after_built_ins: false) {
96
183
  if type == :field && after_built_ins
@@ -100,7 +187,7 @@ module GraphQL
100
187
  },
101
188
  query_analyzer: ->(schema, analyzer) {
102
189
  if analyzer == GraphQL::Authorization::Analyzer
103
- warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
190
+ GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
104
191
  end
105
192
  schema.query_analyzers << analyzer
106
193
  },
@@ -110,10 +197,12 @@ module GraphQL
110
197
  rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
111
198
  tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
112
199
 
200
+ ensure_defined :introspection_system
201
+
113
202
  attr_accessor \
114
203
  :query, :mutation, :subscription,
115
204
  :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
116
- :max_depth, :max_complexity, :default_max_page_size,
205
+ :validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
117
206
  :orphan_types, :directives,
118
207
  :query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
119
208
  :cursor_encoder,
@@ -140,6 +229,27 @@ module GraphQL
140
229
  # @return [Class] Instantiated for each query
141
230
  attr_accessor :context_class
142
231
 
232
+ # [Boolean] True if this object disables the introspection entry point fields
233
+ attr_accessor :disable_introspection_entry_points
234
+
235
+ def disable_introspection_entry_points?
236
+ !!@disable_introspection_entry_points
237
+ end
238
+
239
+ # [Boolean] True if this object disables the __schema introspection entry point field
240
+ attr_accessor :disable_schema_introspection_entry_point
241
+
242
+ def disable_schema_introspection_entry_point?
243
+ !!@disable_schema_introspection_entry_point
244
+ end
245
+
246
+ # [Boolean] True if this object disables the __type introspection entry point field
247
+ attr_accessor :disable_type_introspection_entry_point
248
+
249
+ def disable_type_introspection_entry_point?
250
+ !!@disable_type_introspection_entry_point
251
+ end
252
+
143
253
  class << self
144
254
  attr_writer :default_execution_strategy
145
255
  end
@@ -152,7 +262,7 @@ module GraphQL
152
262
  # @see {Query#tracers} for query-specific tracers
153
263
  attr_reader :tracers
154
264
 
155
- DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
265
+ DYNAMIC_FIELDS = ["__type", "__typename", "__schema"].freeze
156
266
 
157
267
  attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
158
268
 
@@ -160,7 +270,10 @@ module GraphQL
160
270
  @tracers = []
161
271
  @definition_error = nil
162
272
  @orphan_types = []
163
- @directives = self.class.default_directives
273
+ @directives = {}
274
+ self.class.default_directives.each do |name, dir|
275
+ @directives[name] = dir.graphql_definition
276
+ end
164
277
  @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
165
278
  @middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
166
279
  @query_analyzers = []
@@ -174,11 +287,11 @@ module GraphQL
174
287
  @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
175
288
  @lazy_methods.set(GraphQL::Execution::Lazy, :value)
176
289
  @cursor_encoder = Base64Encoder
177
- # Default to the built-in execution strategy:
290
+ # For schema instances, default to legacy runtime modules
178
291
  @analysis_engine = GraphQL::Analysis
179
- @query_execution_strategy = self.class.default_execution_strategy
180
- @mutation_execution_strategy = self.class.default_execution_strategy
181
- @subscription_execution_strategy = self.class.default_execution_strategy
292
+ @query_execution_strategy = GraphQL::Execution::Execute
293
+ @mutation_execution_strategy = GraphQL::Execution::Execute
294
+ @subscription_execution_strategy = GraphQL::Execution::Execute
182
295
  @default_mask = GraphQL::Schema::NullMask
183
296
  @rebuilding_artifacts = false
184
297
  @context_class = GraphQL::Query::Context
@@ -186,16 +299,18 @@ module GraphQL
186
299
  @introspection_system = nil
187
300
  @interpreter = false
188
301
  @error_bubbling = false
302
+ @disable_introspection_entry_points = false
303
+ @disable_schema_introspection_entry_point = false
304
+ @disable_type_introspection_entry_point = false
189
305
  end
190
306
 
191
307
  # @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
192
308
  def interpreter?
193
- @interpreter
309
+ query_execution_strategy == GraphQL::Execution::Interpreter &&
310
+ mutation_execution_strategy == GraphQL::Execution::Interpreter &&
311
+ subscription_execution_strategy == GraphQL::Execution::Interpreter
194
312
  end
195
313
 
196
- # @api private
197
- attr_writer :interpreter
198
-
199
314
  def inspect
200
315
  "#<#{self.class.name} ...>"
201
316
  end
@@ -243,35 +358,18 @@ module GraphQL
243
358
  # For forwards-compatibility with Schema classes
244
359
  alias :graphql_definition :itself
245
360
 
246
- # Validate a query string according to this schema.
247
- # @param string_or_document [String, GraphQL::Language::Nodes::Document]
248
- # @return [Array<GraphQL::StaticValidation::Error >]
249
- def validate(string_or_document, rules: nil, context: nil)
250
- doc = if string_or_document.is_a?(String)
251
- GraphQL.parse(string_or_document)
252
- else
253
- string_or_document
254
- end
255
- query = GraphQL::Query.new(self, document: doc, context: context)
256
- validator_opts = { schema: self }
257
- rules && (validator_opts[:rules] = rules)
258
- validator = GraphQL::StaticValidation::Validator.new(validator_opts)
259
- res = validator.validate(query)
260
- res[:errors]
261
- end
262
-
263
- def define(**kwargs, &block)
361
+ def deprecated_define(**kwargs, &block)
264
362
  super
265
363
  ensure_defined
266
364
  # Assert that all necessary configs are present:
267
365
  validation_error = Validation.validate(self)
268
- validation_error && raise(NotImplementedError, validation_error)
366
+ validation_error && raise(GraphQL::RequiredImplementationMissingError, validation_error)
269
367
  rebuild_artifacts
270
368
 
271
369
  @definition_error = nil
272
370
  nil
273
371
  rescue StandardError => err
274
- if @raise_definition_error || err.is_a?(CyclicalDefinitionError)
372
+ if @raise_definition_error || err.is_a?(CyclicalDefinitionError) || err.is_a?(GraphQL::RequiredImplementationMissingError)
275
373
  raise
276
374
  else
277
375
  # Raise this error _later_ to avoid messing with Rails constant loading
@@ -308,6 +406,10 @@ module GraphQL
308
406
  end
309
407
  end
310
408
 
409
+ def get_type(type_name)
410
+ @types[type_name]
411
+ end
412
+
311
413
  # @api private
312
414
  def introspection_system
313
415
  @introspection_system ||= begin
@@ -319,9 +421,13 @@ module GraphQL
319
421
  # Returns a list of Arguments and Fields referencing a certain type
320
422
  # @param type_name [String]
321
423
  # @return [Hash]
322
- def references_to(type_name)
424
+ def references_to(type_name = nil)
323
425
  rebuild_artifacts unless defined?(@type_reference_map)
324
- @type_reference_map.fetch(type_name, [])
426
+ if type_name
427
+ @type_reference_map.fetch(type_name, [])
428
+ else
429
+ @type_reference_map
430
+ end
325
431
  end
326
432
 
327
433
  # Returns a list of Union types in which a type is a member
@@ -399,8 +505,8 @@ module GraphQL
399
505
  def get_field(parent_type, field_name)
400
506
  with_definition_error_check do
401
507
  parent_type_name = case parent_type
402
- when GraphQL::BaseType
403
- parent_type.name
508
+ when GraphQL::BaseType, Class, Module
509
+ parent_type.graphql_name
404
510
  when String
405
511
  parent_type
406
512
  else
@@ -426,19 +532,29 @@ module GraphQL
426
532
  @instrumented_field_map[type.graphql_name]
427
533
  end
428
534
 
429
- def type_from_ast(ast_node)
430
- GraphQL::Schema::TypeExpression.build_type(self.types, ast_node)
535
+ def type_from_ast(ast_node, context:)
536
+ GraphQL::Schema::TypeExpression.build_type(self, ast_node)
431
537
  end
432
538
 
433
539
  # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
434
540
  # @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
541
+ # @param context [GraphQL::Query::Context] The context for the current query
435
542
  # @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
436
- def possible_types(type_defn)
437
- @possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
438
- @possible_types.possible_types(type_defn)
543
+ def possible_types(type_defn, context = GraphQL::Query::NullContext)
544
+ if context == GraphQL::Query::NullContext
545
+ @possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
546
+ @possible_types.possible_types(type_defn, context)
547
+ else
548
+ # Use the incoming context to cache this instance --
549
+ # if it were cached on the schema, we'd have a memory leak
550
+ # https://github.com/rmosolgo/graphql-ruby/issues/2878
551
+ ns = context.namespace(:possible_types)
552
+ per_query_possible_types = ns[:possible_types] ||= GraphQL::Schema::PossibleTypes.new(self)
553
+ per_query_possible_types.possible_types(type_defn, context)
554
+ end
439
555
  end
440
556
 
441
- # @see [GraphQL::Schema::Warden] Resticted access to root types
557
+ # @see [GraphQL::Schema::Warden] Restricted access to root types
442
558
  # @return [GraphQL::ObjectType, nil]
443
559
  def root_type_for_operation(operation)
444
560
  case operation
@@ -476,7 +592,7 @@ module GraphQL
476
592
  def resolve_type(type, object, ctx = :__undefined__)
477
593
  check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
478
594
  if @resolve_type_proc.nil?
479
- raise(NotImplementedError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
595
+ raise(GraphQL::RequiredImplementationMissingError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
480
596
  end
481
597
  @resolve_type_proc.call(ok_type, ok_object, ok_ctx)
482
598
  end
@@ -537,7 +653,7 @@ module GraphQL
537
653
  # @return [Any] The application object identified by `id`
538
654
  def object_from_id(id, ctx)
539
655
  if @object_from_id_proc.nil?
540
- raise(NotImplementedError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
656
+ raise(GraphQL::RequiredImplementationMissingError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
541
657
  else
542
658
  @object_from_id_proc.call(id, ctx)
543
659
  end
@@ -579,8 +695,41 @@ module GraphQL
579
695
 
580
696
  # Can't delegate to `class`
581
697
  alias :_schema_class :class
582
- def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :unauthorized_field, :inaccessible_fields
698
+ def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
583
699
  def_delegators :_schema_class, :directive
700
+ def_delegators :_schema_class, :error_handler
701
+ def_delegators :_schema_class, :validate
702
+
703
+
704
+ # Given this schema member, find the class-based definition object
705
+ # whose `method_name` should be treated as an application hook
706
+ # @see {.visible?}
707
+ # @see {.accessible?}
708
+ def call_on_type_class(member, method_name, context, default:)
709
+ member = if member.respond_to?(:type_class)
710
+ member.type_class
711
+ else
712
+ member
713
+ end
714
+
715
+ if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
716
+ member = t
717
+ end
718
+
719
+ if member.respond_to?(method_name)
720
+ member.public_send(method_name, context)
721
+ else
722
+ default
723
+ end
724
+ end
725
+
726
+ def visible?(member, context)
727
+ call_on_type_class(member, :visible?, context, default: true)
728
+ end
729
+
730
+ def accessible?(member, context)
731
+ call_on_type_class(member, :accessible?, context, default: true)
732
+ end
584
733
 
585
734
  # A function to call when {#execute} receives an invalid query string
586
735
  #
@@ -604,7 +753,7 @@ module GraphQL
604
753
  # @return [String] a unique identifier for `object` which clients can use to refetch it
605
754
  def id_from_object(object, type, ctx)
606
755
  if @id_from_object_proc.nil?
607
- raise(NotImplementedError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
756
+ raise(GraphQL::RequiredImplementationMissingError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
608
757
  else
609
758
  @id_from_object_proc.call(object, type, ctx)
610
759
  end
@@ -626,30 +775,30 @@ module GraphQL
626
775
  # @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
627
776
  # @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
628
777
  # @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
629
- # @return [GraphQL::Schema] the schema described by `document`
630
- def self.from_definition(definition_or_path, default_resolve: BuildFromDefinition::DefaultResolve, parser: BuildFromDefinition::DefaultParser)
778
+ # @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
779
+ # @return [Class] the schema described by `document`
780
+ def self.from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
631
781
  # If the file ends in `.graphql`, treat it like a filepath
632
- definition = if definition_or_path.end_with?(".graphql")
633
- File.read(definition_or_path)
782
+ if definition_or_path.end_with?(".graphql")
783
+ GraphQL::Schema::BuildFromDefinition.from_definition_path(
784
+ definition_or_path,
785
+ default_resolve: default_resolve,
786
+ parser: parser,
787
+ using: using,
788
+ )
634
789
  else
635
- definition_or_path
790
+ GraphQL::Schema::BuildFromDefinition.from_definition(
791
+ definition_or_path,
792
+ default_resolve: default_resolve,
793
+ parser: parser,
794
+ using: using,
795
+ )
636
796
  end
637
- GraphQL::Schema::BuildFromDefinition.from_definition(definition, default_resolve: default_resolve, parser: parser)
638
797
  end
639
798
 
640
799
  # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
641
800
  class InvalidDocumentError < Error; end;
642
801
 
643
- # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
644
- def lazy_method_name(obj)
645
- @lazy_methods.get(obj)
646
- end
647
-
648
- # @return [Boolean] True if this object should be lazily resolved
649
- def lazy?(obj)
650
- !!lazy_method_name(obj)
651
- end
652
-
653
802
  # Return the GraphQL IDL for the schema
654
803
  # @param context [Hash]
655
804
  # @param only [<#call(member, ctx)>]
@@ -660,9 +809,12 @@ module GraphQL
660
809
  end
661
810
 
662
811
  # Return the GraphQL::Language::Document IDL AST for the schema
812
+ # @param context [Hash]
813
+ # @param only [<#call(member, ctx)>]
814
+ # @param except [<#call(member, ctx)>]
663
815
  # @return [GraphQL::Language::Document]
664
- def to_document
665
- GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
816
+ def to_document(only: nil, except: nil, context: {})
817
+ GraphQL::Language::DocumentFromSchemaDefinition.new(self, only: only, except: except, context: context).document
666
818
  end
667
819
 
668
820
  # Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
@@ -671,7 +823,7 @@ module GraphQL
671
823
  # @param except [<#call(member, ctx)>]
672
824
  # @return [Hash] GraphQL result
673
825
  def as_json(only: nil, except: nil, context: {})
674
- execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
826
+ execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
675
827
  end
676
828
 
677
829
  # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
@@ -681,62 +833,141 @@ module GraphQL
681
833
  JSON.pretty_generate(as_json(*args))
682
834
  end
683
835
 
836
+ def new_connections?
837
+ !!connections
838
+ end
839
+
840
+ attr_accessor :connections
841
+
684
842
  class << self
685
843
  extend Forwardable
686
844
  # For compatibility, these methods all:
687
845
  # - Cause the Schema instance to be created, if it hasn't been created yet
688
846
  # - Delegate to that instance
689
847
  # Eventually, the methods will be moved into this class, removing the need for the singleton.
690
- def_delegators :graphql_definition,
691
- # Schema structure
692
- :as_json, :to_json, :to_document, :to_definition,
848
+ def_delegators :deprecated_graphql_definition,
693
849
  # Execution
694
- :execute, :multiplex,
695
- :static_validator, :introspection_system,
696
- :query_analyzers, :tracers, :instrumenters,
697
850
  :execution_strategy_for_operation,
698
- :validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy, :sync_lazy,
699
851
  # Configuration
700
- :analysis_engine, :analysis_engine=, :using_ast_analysis?, :interpreter?,
701
- :max_complexity=, :max_depth=,
702
- :error_bubbling=,
703
- :metadata,
704
- :default_mask,
705
- :default_filter, :redefine,
852
+ :metadata, :redefine,
706
853
  :id_from_object_proc, :object_from_id_proc,
707
854
  :id_from_object=, :object_from_id=,
708
- :remove_handler,
709
- # Members
710
- :types, :get_fields, :find,
711
- :root_type_for_operation,
712
- :subscriptions,
713
- :union_memberships,
714
- :get_field, :root_types, :references_to, :type_from_ast,
715
- :possible_types
855
+ :remove_handler
856
+
857
+ def deprecated_graphql_definition
858
+ graphql_definition(silence_deprecation_warning: true)
859
+ end
860
+
861
+ # @return [GraphQL::Subscriptions]
862
+ attr_accessor :subscriptions
863
+
864
+ # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
865
+ # @see {#as_json}
866
+ # @return [String]
867
+ def to_json(**args)
868
+ JSON.pretty_generate(as_json(**args))
869
+ end
870
+
871
+ # Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
872
+ # @param context [Hash]
873
+ # @param only [<#call(member, ctx)>]
874
+ # @param except [<#call(member, ctx)>]
875
+ # @return [Hash] GraphQL result
876
+ def as_json(only: nil, except: nil, context: {})
877
+ execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
878
+ end
879
+
880
+ # Return the GraphQL IDL for the schema
881
+ # @param context [Hash]
882
+ # @param only [<#call(member, ctx)>]
883
+ # @param except [<#call(member, ctx)>]
884
+ # @return [String]
885
+ def to_definition(only: nil, except: nil, context: {})
886
+ GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
887
+ end
716
888
 
717
- def graphql_definition
718
- @graphql_definition ||= to_graphql
889
+ # Return the GraphQL::Language::Document IDL AST for the schema
890
+ # @return [GraphQL::Language::Document]
891
+ def to_document
892
+ GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
719
893
  end
720
894
 
721
- def use(plugin, options = {})
722
- plugins << [plugin, options]
895
+ # @return [String, nil]
896
+ def description(new_description = nil)
897
+ if new_description
898
+ @description = new_description
899
+ elsif defined?(@description)
900
+ @description
901
+ else
902
+ find_inherited_value(:description, nil)
903
+ end
904
+ end
905
+
906
+ def find(path)
907
+ if !@finder
908
+ @find_cache = {}
909
+ @finder ||= GraphQL::Schema::Finder.new(self)
910
+ end
911
+ @find_cache[path] ||= @finder.find(path)
912
+ end
913
+
914
+ def graphql_definition(silence_deprecation_warning: false)
915
+ @graphql_definition ||= begin
916
+ unless silence_deprecation_warning
917
+ message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Use a class-based definition instead."
918
+ caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
919
+ GraphQL::Deprecation.warn(message + caller_message)
920
+ end
921
+ to_graphql(silence_deprecation_warning: silence_deprecation_warning)
922
+ end
923
+ end
924
+
925
+ def default_filter
926
+ GraphQL::Filter.new(except: default_mask)
927
+ end
928
+
929
+ def default_mask(new_mask = nil)
930
+ if new_mask
931
+ @own_default_mask = new_mask
932
+ else
933
+ @own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
934
+ end
935
+ end
936
+
937
+ def static_validator
938
+ GraphQL::StaticValidation::Validator.new(schema: self)
939
+ end
940
+
941
+ def use(plugin, **kwargs)
942
+ if kwargs.any?
943
+ plugin.use(self, **kwargs)
944
+ else
945
+ plugin.use(self)
946
+ end
947
+ own_plugins << [plugin, kwargs]
723
948
  end
724
949
 
725
950
  def plugins
726
- @plugins ||= []
951
+ find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
727
952
  end
728
953
 
954
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
729
955
  def to_graphql
730
956
  schema_defn = self.new
731
957
  schema_defn.raise_definition_error = true
732
- schema_defn.query = query
733
- schema_defn.mutation = mutation
734
- schema_defn.subscription = subscription
958
+ schema_defn.query = query && query.graphql_definition(silence_deprecation_warning: true)
959
+ schema_defn.mutation = mutation && mutation.graphql_definition(silence_deprecation_warning: true)
960
+ schema_defn.subscription = subscription && subscription.graphql_definition(silence_deprecation_warning: true)
961
+ schema_defn.validate_timeout = validate_timeout
962
+ schema_defn.validate_max_errors = validate_max_errors
735
963
  schema_defn.max_complexity = max_complexity
736
964
  schema_defn.error_bubbling = error_bubbling
737
965
  schema_defn.max_depth = max_depth
738
966
  schema_defn.default_max_page_size = default_max_page_size
739
- schema_defn.orphan_types = orphan_types
967
+ schema_defn.orphan_types = orphan_types.map { |t| t.graphql_definition(silence_deprecation_warning: true) }
968
+ schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
969
+ schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
970
+ schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
740
971
 
741
972
  prepped_dirs = {}
742
973
  directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
@@ -748,94 +979,333 @@ module GraphQL
748
979
  schema_defn.type_error = method(:type_error)
749
980
  schema_defn.context_class = context_class
750
981
  schema_defn.cursor_encoder = cursor_encoder
751
- schema_defn.tracers.concat(defined_tracers)
752
- schema_defn.query_analyzers.concat(defined_query_analyzers)
982
+ schema_defn.tracers.concat(tracers)
983
+ schema_defn.query_analyzers.concat(query_analyzers)
984
+ schema_defn.analysis_engine = analysis_engine
753
985
 
754
- schema_defn.middleware.concat(defined_middleware)
755
- schema_defn.multiplex_analyzers.concat(defined_multiplex_analyzers)
986
+ schema_defn.middleware.concat(all_middleware)
987
+ schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
756
988
  schema_defn.query_execution_strategy = query_execution_strategy
757
989
  schema_defn.mutation_execution_strategy = mutation_execution_strategy
758
990
  schema_defn.subscription_execution_strategy = subscription_execution_strategy
759
- defined_instrumenters.each do |step, insts|
991
+ schema_defn.default_mask = default_mask
992
+ instrumenters.each do |step, insts|
760
993
  insts.each do |inst|
761
994
  schema_defn.instrumenters[step] << inst
762
995
  end
763
996
  end
764
- lazy_classes.each do |lazy_class, value_method|
997
+
998
+ lazy_methods.each do |lazy_class, value_method|
765
999
  schema_defn.lazy_methods.set(lazy_class, value_method)
766
1000
  end
767
- if @rescues
768
- @rescues.each do |err_class, handler|
769
- schema_defn.rescue_from(err_class, &handler)
1001
+
1002
+ error_handler.each_rescue do |err_class, handler|
1003
+ schema_defn.rescue_from(err_class, &handler)
1004
+ end
1005
+
1006
+ schema_defn.subscriptions ||= self.subscriptions
1007
+
1008
+ if !schema_defn.interpreter?
1009
+ schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
1010
+ end
1011
+
1012
+ if new_connections?
1013
+ schema_defn.connections = self.connections
1014
+ end
1015
+
1016
+ schema_defn.send(:rebuild_artifacts)
1017
+
1018
+ schema_defn
1019
+ end
1020
+
1021
+ # Build a map of `{ name => type }` and return it
1022
+ # @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
1023
+ # @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
1024
+ def types(context = GraphQL::Query::NullContext)
1025
+ all_types = non_introspection_types.merge(introspection_system.types)
1026
+ visible_types = {}
1027
+ all_types.each do |k, v|
1028
+ visible_types[k] =if v.is_a?(Array)
1029
+ visible_t = nil
1030
+ v.each do |t|
1031
+ if t.visible?(context)
1032
+ if visible_t.nil?
1033
+ visible_t = t
1034
+ else
1035
+ raise DuplicateNamesError, "Found two visible type definitions for `#{k}`: #{visible_t.inspect}, #{t.inspect}"
1036
+ end
1037
+ end
1038
+ end
1039
+ visible_t
1040
+ else
1041
+ v
770
1042
  end
771
1043
  end
1044
+ visible_types
1045
+ end
772
1046
 
773
- if plugins.any?
774
- schema_plugins = plugins
775
- # TODO don't depend on .define
776
- schema_defn = schema_defn.redefine do
777
- schema_plugins.each do |plugin, options|
778
- if options.any?
779
- use(plugin, **options)
1047
+ # @param type_name [String]
1048
+ # @return [Module, nil] A type, or nil if there's no type called `type_name`
1049
+ def get_type(type_name, context = GraphQL::Query::NullContext)
1050
+ local_entry = own_types[type_name]
1051
+ type_defn = case local_entry
1052
+ when nil
1053
+ nil
1054
+ when Array
1055
+ visible_t = nil
1056
+ warden = Warden.from_context(context)
1057
+ local_entry.each do |t|
1058
+ if warden.visible_type?(t, context)
1059
+ if visible_t.nil?
1060
+ visible_t = t
780
1061
  else
781
- use(plugin)
1062
+ raise DuplicateNamesError, "Found two visible type definitions for `#{type_name}`: #{visible_t.inspect}, #{t.inspect}"
782
1063
  end
783
1064
  end
784
1065
  end
1066
+ visible_t
1067
+ when Module
1068
+ local_entry
1069
+ else
1070
+ raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
785
1071
  end
786
- # Do this after `plugins` since Interpreter is a plugin
787
- if schema_defn.query_execution_strategy != GraphQL::Execution::Interpreter
788
- schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
1072
+
1073
+ type_defn ||
1074
+ introspection_system.types[type_name] || # todo context-specific introspection?
1075
+ (superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
1076
+ end
1077
+
1078
+ # @api private
1079
+ attr_writer :connections
1080
+
1081
+ # @return [GraphQL::Pagination::Connections] if installed
1082
+ def connections
1083
+ if defined?(@connections)
1084
+ @connections
1085
+ else
1086
+ inherited_connections = find_inherited_value(:connections, nil)
1087
+ # This schema is part of an inheritance chain which is using new connections,
1088
+ # make a new instance, so we don't pollute the upstream one.
1089
+ if inherited_connections
1090
+ @connections = Pagination::Connections.new(schema: self)
1091
+ else
1092
+ nil
1093
+ end
789
1094
  end
790
- schema_defn.send(:rebuild_artifacts)
1095
+ end
791
1096
 
792
- schema_defn
1097
+ def new_connections?
1098
+ !!connections
793
1099
  end
794
1100
 
795
1101
  def query(new_query_object = nil)
796
1102
  if new_query_object
797
- @query_object = new_query_object
1103
+ if @query_object
1104
+ raise GraphQL::Error, "Second definition of `query(...)` (#{new_query_object.inspect}) is invalid, already configured with #{@query_object.inspect}"
1105
+ else
1106
+ @query_object = new_query_object
1107
+ add_type_and_traverse(new_query_object, root: true)
1108
+ nil
1109
+ end
798
1110
  else
799
- @query_object.respond_to?(:graphql_definition) ? @query_object.graphql_definition : @query_object
1111
+ @query_object || find_inherited_value(:query)
800
1112
  end
801
1113
  end
802
1114
 
803
1115
  def mutation(new_mutation_object = nil)
804
1116
  if new_mutation_object
805
- @mutation_object = new_mutation_object
1117
+ if @mutation_object
1118
+ raise GraphQL::Error, "Second definition of `mutation(...)` (#{new_mutation_object.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
1119
+ else
1120
+ @mutation_object = new_mutation_object
1121
+ add_type_and_traverse(new_mutation_object, root: true)
1122
+ nil
1123
+ end
806
1124
  else
807
- @mutation_object.respond_to?(:graphql_definition) ? @mutation_object.graphql_definition : @mutation_object
1125
+ @mutation_object || find_inherited_value(:mutation)
808
1126
  end
809
1127
  end
810
1128
 
811
1129
  def subscription(new_subscription_object = nil)
812
1130
  if new_subscription_object
813
- @subscription_object = new_subscription_object
1131
+ if @subscription_object
1132
+ raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
1133
+ else
1134
+ @subscription_object = new_subscription_object
1135
+ add_subscription_extension_if_necessary
1136
+ add_type_and_traverse(new_subscription_object, root: true)
1137
+ nil
1138
+ end
1139
+ else
1140
+ @subscription_object || find_inherited_value(:subscription)
1141
+ end
1142
+ end
1143
+
1144
+ # @see [GraphQL::Schema::Warden] Restricted access to root types
1145
+ # @return [GraphQL::ObjectType, nil]
1146
+ def root_type_for_operation(operation)
1147
+ case operation
1148
+ when "query"
1149
+ query
1150
+ when "mutation"
1151
+ mutation
1152
+ when "subscription"
1153
+ subscription
1154
+ else
1155
+ raise ArgumentError, "unknown operation type: #{operation}"
1156
+ end
1157
+ end
1158
+
1159
+ def root_types
1160
+ @root_types
1161
+ end
1162
+
1163
+ # @param type [Module] The type definition whose possible types you want to see
1164
+ # @return [Hash<String, Module>] All possible types, if no `type` is given.
1165
+ # @return [Array<Module>] Possible types for `type`, if it's given.
1166
+ def possible_types(type = nil, context = GraphQL::Query::NullContext)
1167
+ if type
1168
+ # TODO duck-typing `.possible_types` would probably be nicer here
1169
+ if type.kind.union?
1170
+ type.possible_types(context: context)
1171
+ else
1172
+ stored_possible_types = own_possible_types[type.graphql_name]
1173
+ visible_possible_types = if stored_possible_types && type.kind.interface?
1174
+ stored_possible_types.select do |possible_type|
1175
+ # Use `.graphql_name` comparison to match legacy vs class-based types.
1176
+ # When we don't need to support legacy `.define` types, use `.include?(type)` instead.
1177
+ possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
1178
+ end
1179
+ else
1180
+ stored_possible_types
1181
+ end
1182
+ visible_possible_types ||
1183
+ introspection_system.possible_types[type.graphql_name] ||
1184
+ (
1185
+ superclass.respond_to?(:possible_types) ?
1186
+ superclass.possible_types(type, context) :
1187
+ EMPTY_ARRAY
1188
+ )
1189
+ end
1190
+ else
1191
+ find_inherited_value(:possible_types, EMPTY_HASH)
1192
+ .merge(own_possible_types)
1193
+ .merge(introspection_system.possible_types)
1194
+ end
1195
+ end
1196
+
1197
+ def union_memberships(type = nil)
1198
+ if type
1199
+ own_um = own_union_memberships.fetch(type.graphql_name, EMPTY_ARRAY)
1200
+ inherited_um = find_inherited_value(:union_memberships, EMPTY_HASH).fetch(type.graphql_name, EMPTY_ARRAY)
1201
+ own_um + inherited_um
814
1202
  else
815
- @subscription_object.respond_to?(:graphql_definition) ? @subscription_object.graphql_definition : @subscription_object
1203
+ joined_um = own_union_memberships.dup
1204
+ find_inherited_value(:union_memberhips, EMPTY_HASH).each do |k, v|
1205
+ um = joined_um[k] ||= []
1206
+ um.concat(v)
1207
+ end
1208
+ joined_um
816
1209
  end
817
1210
  end
818
1211
 
1212
+ # @api private
1213
+ # @see GraphQL::Dataloader
1214
+ def dataloader_class
1215
+ @dataloader_class || GraphQL::Dataloader::NullDataloader
1216
+ end
1217
+
1218
+ attr_writer :dataloader_class
1219
+
1220
+ def references_to(to_type = nil, from: nil)
1221
+ @own_references_to ||= Hash.new { |h, k| h[k] = [] }
1222
+ if to_type
1223
+ if !to_type.is_a?(String)
1224
+ to_type = to_type.graphql_name
1225
+ end
1226
+
1227
+ if from
1228
+ @own_references_to[to_type] << from
1229
+ else
1230
+ own_refs = @own_references_to[to_type]
1231
+ inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
1232
+ own_refs + inherited_refs
1233
+ end
1234
+ else
1235
+ # `@own_references_to` can be quite large for big schemas,
1236
+ # and generally speaking, we won't inherit any values.
1237
+ # So optimize the most common case -- don't create a duplicate Hash.
1238
+ inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
1239
+ if inherited_value.any?
1240
+ inherited_value.merge(@own_references_to)
1241
+ else
1242
+ @own_references_to
1243
+ end
1244
+ end
1245
+ end
1246
+
1247
+ def type_from_ast(ast_node, context: nil)
1248
+ type_owner = context ? context.warden : self
1249
+ GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
1250
+ end
1251
+
1252
+ def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
1253
+ parent_type = case type_or_name
1254
+ when LateBoundType
1255
+ get_type(type_or_name.name, context)
1256
+ when String
1257
+ get_type(type_or_name, context)
1258
+ when Module
1259
+ type_or_name
1260
+ else
1261
+ raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
1262
+ end
1263
+
1264
+ if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
1265
+ field
1266
+ elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
1267
+ entry_point_field
1268
+ elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
1269
+ dynamic_field
1270
+ else
1271
+ nil
1272
+ end
1273
+ end
1274
+
1275
+ def get_fields(type, context = GraphQL::Query::NullContext)
1276
+ type.fields(context)
1277
+ end
1278
+
819
1279
  def introspection(new_introspection_namespace = nil)
820
1280
  if new_introspection_namespace
821
1281
  @introspection = new_introspection_namespace
1282
+ # reset this cached value:
1283
+ @introspection_system = nil
822
1284
  else
823
- @introspection
1285
+ @introspection || find_inherited_value(:introspection)
824
1286
  end
825
1287
  end
826
1288
 
1289
+ def introspection_system
1290
+ if !@introspection_system
1291
+ @introspection_system = Schema::IntrospectionSystem.new(self)
1292
+ @introspection_system.resolve_late_bindings
1293
+ end
1294
+ @introspection_system
1295
+ end
1296
+
827
1297
  def cursor_encoder(new_encoder = nil)
828
1298
  if new_encoder
829
1299
  @cursor_encoder = new_encoder
830
1300
  end
831
- @cursor_encoder || Base64Encoder
1301
+ @cursor_encoder || find_inherited_value(:cursor_encoder, Base64Encoder)
832
1302
  end
833
1303
 
834
1304
  def default_max_page_size(new_default_max_page_size = nil)
835
1305
  if new_default_max_page_size
836
1306
  @default_max_page_size = new_default_max_page_size
837
1307
  else
838
- @default_max_page_size
1308
+ @default_max_page_size || find_inherited_value(:default_max_page_size)
839
1309
  end
840
1310
  end
841
1311
 
@@ -843,7 +1313,7 @@ module GraphQL
843
1313
  if new_query_execution_strategy
844
1314
  @query_execution_strategy = new_query_execution_strategy
845
1315
  else
846
- @query_execution_strategy || self.default_execution_strategy
1316
+ @query_execution_strategy || find_inherited_value(:query_execution_strategy, self.default_execution_strategy)
847
1317
  end
848
1318
  end
849
1319
 
@@ -851,7 +1321,7 @@ module GraphQL
851
1321
  if new_mutation_execution_strategy
852
1322
  @mutation_execution_strategy = new_mutation_execution_strategy
853
1323
  else
854
- @mutation_execution_strategy || self.default_execution_strategy
1324
+ @mutation_execution_strategy || find_inherited_value(:mutation_execution_strategy, self.default_execution_strategy)
855
1325
  end
856
1326
  end
857
1327
 
@@ -859,47 +1329,168 @@ module GraphQL
859
1329
  if new_subscription_execution_strategy
860
1330
  @subscription_execution_strategy = new_subscription_execution_strategy
861
1331
  else
862
- @subscription_execution_strategy || self.default_execution_strategy
1332
+ @subscription_execution_strategy || find_inherited_value(:subscription_execution_strategy, self.default_execution_strategy)
1333
+ end
1334
+ end
1335
+
1336
+ attr_writer :validate_timeout
1337
+
1338
+ def validate_timeout(new_validate_timeout = nil)
1339
+ if new_validate_timeout
1340
+ @validate_timeout = new_validate_timeout
1341
+ elsif defined?(@validate_timeout)
1342
+ @validate_timeout
1343
+ else
1344
+ find_inherited_value(:validate_timeout)
1345
+ end
1346
+ end
1347
+
1348
+ # Validate a query string according to this schema.
1349
+ # @param string_or_document [String, GraphQL::Language::Nodes::Document]
1350
+ # @return [Array<GraphQL::StaticValidation::Error >]
1351
+ def validate(string_or_document, rules: nil, context: nil)
1352
+ doc = if string_or_document.is_a?(String)
1353
+ GraphQL.parse(string_or_document)
1354
+ else
1355
+ string_or_document
1356
+ end
1357
+ query = GraphQL::Query.new(self, document: doc, context: context)
1358
+ validator_opts = { schema: self }
1359
+ rules && (validator_opts[:rules] = rules)
1360
+ validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
1361
+ res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
1362
+ res[:errors]
1363
+ end
1364
+
1365
+ attr_writer :validate_max_errors
1366
+
1367
+ def validate_max_errors(new_validate_max_errors = nil)
1368
+ if new_validate_max_errors
1369
+ @validate_max_errors = new_validate_max_errors
1370
+ elsif defined?(@validate_max_errors)
1371
+ @validate_max_errors
1372
+ else
1373
+ find_inherited_value(:validate_max_errors)
863
1374
  end
864
1375
  end
865
1376
 
1377
+ attr_writer :max_complexity
1378
+
866
1379
  def max_complexity(max_complexity = nil)
867
1380
  if max_complexity
868
1381
  @max_complexity = max_complexity
869
- else
1382
+ elsif defined?(@max_complexity)
870
1383
  @max_complexity
1384
+ else
1385
+ find_inherited_value(:max_complexity)
871
1386
  end
872
1387
  end
873
1388
 
1389
+ attr_writer :analysis_engine
1390
+
1391
+ def analysis_engine
1392
+ @analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
1393
+ end
1394
+
1395
+ def using_ast_analysis?
1396
+ analysis_engine == GraphQL::Analysis::AST
1397
+ end
1398
+
1399
+ def interpreter?
1400
+ query_execution_strategy == GraphQL::Execution::Interpreter &&
1401
+ mutation_execution_strategy == GraphQL::Execution::Interpreter &&
1402
+ subscription_execution_strategy == GraphQL::Execution::Interpreter
1403
+ end
1404
+
1405
+ attr_writer :interpreter
1406
+
874
1407
  def error_bubbling(new_error_bubbling = nil)
875
1408
  if !new_error_bubbling.nil?
876
1409
  @error_bubbling = new_error_bubbling
877
1410
  else
878
- @error_bubbling
1411
+ @error_bubbling.nil? ? find_inherited_value(:error_bubbling) : @error_bubbling
879
1412
  end
880
1413
  end
881
1414
 
1415
+ attr_writer :error_bubbling
1416
+
1417
+ attr_writer :max_depth
1418
+
882
1419
  def max_depth(new_max_depth = nil)
883
1420
  if new_max_depth
884
1421
  @max_depth = new_max_depth
885
- else
1422
+ elsif defined?(@max_depth)
886
1423
  @max_depth
1424
+ else
1425
+ find_inherited_value(:max_depth)
1426
+ end
1427
+ end
1428
+
1429
+ def disable_introspection_entry_points
1430
+ @disable_introspection_entry_points = true
1431
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
1432
+ @introspection_system = nil
1433
+ end
1434
+
1435
+ def disable_schema_introspection_entry_point
1436
+ @disable_schema_introspection_entry_point = true
1437
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
1438
+ @introspection_system = nil
1439
+ end
1440
+
1441
+ def disable_type_introspection_entry_point
1442
+ @disable_type_introspection_entry_point = true
1443
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
1444
+ @introspection_system = nil
1445
+ end
1446
+
1447
+ def disable_introspection_entry_points?
1448
+ if instance_variable_defined?(:@disable_introspection_entry_points)
1449
+ @disable_introspection_entry_points
1450
+ else
1451
+ find_inherited_value(:disable_introspection_entry_points?, false)
1452
+ end
1453
+ end
1454
+
1455
+ def disable_schema_introspection_entry_point?
1456
+ if instance_variable_defined?(:@disable_schema_introspection_entry_point)
1457
+ @disable_schema_introspection_entry_point
1458
+ else
1459
+ find_inherited_value(:disable_schema_introspection_entry_point?, false)
1460
+ end
1461
+ end
1462
+
1463
+ def disable_type_introspection_entry_point?
1464
+ if instance_variable_defined?(:@disable_type_introspection_entry_point)
1465
+ @disable_type_introspection_entry_point
1466
+ else
1467
+ find_inherited_value(:disable_type_introspection_entry_point?, false)
887
1468
  end
888
1469
  end
889
1470
 
890
1471
  def orphan_types(*new_orphan_types)
891
1472
  if new_orphan_types.any?
892
- @orphan_types = new_orphan_types.flatten
893
- else
894
- @orphan_types || []
1473
+ new_orphan_types = new_orphan_types.flatten
1474
+ add_type_and_traverse(new_orphan_types, root: false)
1475
+ own_orphan_types.concat(new_orphan_types.flatten)
895
1476
  end
1477
+
1478
+ find_inherited_value(:orphan_types, EMPTY_ARRAY) + own_orphan_types
896
1479
  end
897
1480
 
898
1481
  def default_execution_strategy
899
1482
  if superclass <= GraphQL::Schema
900
1483
  superclass.default_execution_strategy
901
1484
  else
902
- @default_execution_strategy ||= GraphQL::Execution::Execute
1485
+ @default_execution_strategy ||= GraphQL::Execution::Interpreter
1486
+ end
1487
+ end
1488
+
1489
+ def default_analysis_engine
1490
+ if superclass <= GraphQL::Schema
1491
+ superclass.default_analysis_engine
1492
+ else
1493
+ @default_analysis_engine ||= GraphQL::Analysis::AST
903
1494
  end
904
1495
  end
905
1496
 
@@ -907,14 +1498,36 @@ module GraphQL
907
1498
  if new_context_class
908
1499
  @context_class = new_context_class
909
1500
  else
910
- @context_class || GraphQL::Query::Context
1501
+ @context_class || find_inherited_value(:context_class, GraphQL::Query::Context)
911
1502
  end
912
1503
  end
913
1504
 
914
1505
  def rescue_from(*err_classes, &handler_block)
915
- @rescues ||= {}
916
1506
  err_classes.each do |err_class|
917
- @rescues[err_class] = handler_block
1507
+ error_handler.rescue_from(err_class, handler_block)
1508
+ end
1509
+ end
1510
+
1511
+ # rubocop:disable Lint/DuplicateMethods
1512
+ module ResolveTypeWithType
1513
+ def resolve_type(type, obj, ctx)
1514
+ first_resolved_type, resolved_value = if type.is_a?(Module) && type.respond_to?(:resolve_type)
1515
+ type.resolve_type(obj, ctx)
1516
+ else
1517
+ super
1518
+ end
1519
+
1520
+ after_lazy(first_resolved_type) do |resolved_type|
1521
+ if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind)) || resolved_type.is_a?(GraphQL::BaseType)
1522
+ if resolved_value
1523
+ [resolved_type, resolved_value]
1524
+ else
1525
+ resolved_type
1526
+ end
1527
+ else
1528
+ raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
1529
+ end
1530
+ end
918
1531
  end
919
1532
  end
920
1533
 
@@ -922,24 +1535,33 @@ module GraphQL
922
1535
  if type.kind.object?
923
1536
  type
924
1537
  else
925
- raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
1538
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
926
1539
  end
927
1540
  end
1541
+ # rubocop:enable Lint/DuplicateMethods
1542
+
1543
+ def inherited(child_class)
1544
+ if self == GraphQL::Schema
1545
+ child_class.directives(default_directives.values)
1546
+ end
1547
+ child_class.singleton_class.prepend(ResolveTypeWithType)
1548
+ super
1549
+ end
928
1550
 
929
1551
  def object_from_id(node_id, ctx)
930
- raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
1552
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
931
1553
  end
932
1554
 
933
1555
  def id_from_object(object, type, ctx)
934
- raise NotImplementedError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
1556
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
935
1557
  end
936
1558
 
937
- def visible?(member, context)
938
- call_on_type_class(member, :visible?, context, default: true)
1559
+ def visible?(member, ctx)
1560
+ member.type_class.visible?(ctx)
939
1561
  end
940
1562
 
941
- def accessible?(member, context)
942
- call_on_type_class(member, :accessible?, context, default: true)
1563
+ def accessible?(member, ctx)
1564
+ member.type_class.accessible?(ctx)
943
1565
  end
944
1566
 
945
1567
  # This hook is called when a client tries to access one or more
@@ -993,175 +1615,313 @@ module GraphQL
993
1615
  DefaultTypeError.call(type_err, ctx)
994
1616
  end
995
1617
 
1618
+ # A function to call when {#execute} receives an invalid query string
1619
+ #
1620
+ # The default is to add the error to `context.errors`
1621
+ # @param err [GraphQL::ParseError] The error encountered during parsing
1622
+ # @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
1623
+ # @return void
1624
+ def parse_error(parse_err, ctx)
1625
+ ctx.errors.push(parse_err)
1626
+ end
1627
+
1628
+ # @return [GraphQL::Execution::Errors]
1629
+ def error_handler
1630
+ @error_handler ||= GraphQL::Execution::Errors.new(self)
1631
+ end
1632
+
996
1633
  def lazy_resolve(lazy_class, value_method)
997
- lazy_classes[lazy_class] = value_method
1634
+ lazy_methods.set(lazy_class, value_method)
998
1635
  end
999
1636
 
1000
1637
  def instrument(instrument_step, instrumenter, options = {})
1638
+ if instrument_step == :field
1639
+ GraphQL::Deprecation.warn "Field instrumentation (#{instrumenter.inspect}) will be removed in GraphQL-Ruby 2.0, please upgrade to field extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1640
+ end
1641
+
1001
1642
  step = if instrument_step == :field && options[:after_built_ins]
1002
1643
  :field_after_built_ins
1003
1644
  else
1004
1645
  instrument_step
1005
1646
  end
1006
- defined_instrumenters[step] << instrumenter
1647
+
1648
+ own_instrumenters[step] << instrumenter
1007
1649
  end
1008
1650
 
1009
- def directives(new_directives = nil)
1010
- if new_directives
1011
- @directives = new_directives.reduce({}) { |m, d| m[d.name] = d; m }
1651
+ # Add several directives at once
1652
+ # @param new_directives [Class]
1653
+ def directives(*new_directives)
1654
+ if new_directives.any?
1655
+ new_directives.flatten.each { |d| directive(d) }
1012
1656
  end
1013
1657
 
1014
- @directives ||= default_directives
1658
+ find_inherited_value(:directives, default_directives).merge(own_directives)
1015
1659
  end
1016
1660
 
1661
+ # Attach a single directive to this schema
1662
+ # @param new_directive [Class]
1663
+ # @return void
1017
1664
  def directive(new_directive)
1018
- directives[new_directive.graphql_name] = new_directive
1665
+ add_type_and_traverse(new_directive, root: false)
1019
1666
  end
1020
1667
 
1021
1668
  def default_directives
1022
- {
1023
- "include" => GraphQL::Directive::IncludeDirective,
1024
- "skip" => GraphQL::Directive::SkipDirective,
1025
- "deprecated" => GraphQL::Directive::DeprecatedDirective,
1026
- }
1669
+ @default_directives ||= {
1670
+ "include" => GraphQL::Schema::Directive::Include,
1671
+ "skip" => GraphQL::Schema::Directive::Skip,
1672
+ "deprecated" => GraphQL::Schema::Directive::Deprecated,
1673
+ }.freeze
1027
1674
  end
1028
1675
 
1029
1676
  def tracer(new_tracer)
1030
- defined_tracers << new_tracer
1677
+ own_tracers << new_tracer
1678
+ end
1679
+
1680
+ def tracers
1681
+ find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
1031
1682
  end
1032
1683
 
1033
1684
  def query_analyzer(new_analyzer)
1034
1685
  if new_analyzer == GraphQL::Authorization::Analyzer
1035
- warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1686
+ GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1036
1687
  end
1037
- defined_query_analyzers << new_analyzer
1688
+ own_query_analyzers << new_analyzer
1689
+ end
1690
+
1691
+ def query_analyzers
1692
+ find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
1038
1693
  end
1039
1694
 
1040
1695
  def middleware(new_middleware = nil)
1041
1696
  if new_middleware
1042
- defined_middleware << new_middleware
1697
+ GraphQL::Deprecation.warn "Middleware will be removed in GraphQL-Ruby 2.0, please upgrade to Field Extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1698
+ own_middleware << new_middleware
1043
1699
  else
1044
- graphql_definition.middleware
1700
+ # TODO make sure this is cached when running a query
1701
+ MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
1045
1702
  end
1046
1703
  end
1047
1704
 
1048
1705
  def multiplex_analyzer(new_analyzer)
1049
- defined_multiplex_analyzers << new_analyzer
1706
+ own_multiplex_analyzers << new_analyzer
1050
1707
  end
1051
1708
 
1052
- private
1709
+ def multiplex_analyzers
1710
+ find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
1711
+ end
1053
1712
 
1054
- def lazy_classes
1055
- @lazy_classes ||= {}
1713
+ def sanitized_printer(new_sanitized_printer = nil)
1714
+ if new_sanitized_printer
1715
+ @own_sanitized_printer = new_sanitized_printer
1716
+ else
1717
+ @own_sanitized_printer || GraphQL::Language::SanitizedPrinter
1718
+ end
1056
1719
  end
1057
1720
 
1058
- def defined_instrumenters
1059
- @defined_instrumenters ||= Hash.new { |h,k| h[k] = [] }
1721
+ # Execute a query on itself.
1722
+ # @see {Query#initialize} for arguments.
1723
+ # @return [Hash] query result, ready to be serialized as JSON
1724
+ def execute(query_str = nil, **kwargs)
1725
+ if query_str
1726
+ kwargs[:query] = query_str
1727
+ end
1728
+ # Some of the query context _should_ be passed to the multiplex, too
1729
+ multiplex_context = if (ctx = kwargs[:context])
1730
+ {
1731
+ backtrace: ctx[:backtrace],
1732
+ tracers: ctx[:tracers],
1733
+ dataloader: ctx[:dataloader],
1734
+ }
1735
+ else
1736
+ {}
1737
+ end
1738
+ # Since we're running one query, don't run a multiplex-level complexity analyzer
1739
+ all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
1740
+ all_results[0]
1060
1741
  end
1061
1742
 
1062
- def defined_tracers
1063
- @defined_tracers ||= []
1743
+ # Execute several queries on itself, concurrently.
1744
+ #
1745
+ # @example Run several queries at once
1746
+ # context = { ... }
1747
+ # queries = [
1748
+ # { query: params[:query_1], variables: params[:variables_1], context: context },
1749
+ # { query: params[:query_2], variables: params[:variables_2], context: context },
1750
+ # ]
1751
+ # results = MySchema.multiplex(queries)
1752
+ # render json: {
1753
+ # result_1: results[0],
1754
+ # result_2: results[1],
1755
+ # }
1756
+ #
1757
+ # @see {Query#initialize} for query keyword arguments
1758
+ # @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
1759
+ # @param queries [Array<Hash>] Keyword arguments for each query
1760
+ # @param context [Hash] Multiplex-level context
1761
+ # @return [Array<Hash>] One result for each query in the input
1762
+ def multiplex(queries, **kwargs)
1763
+ schema = if interpreter?
1764
+ self
1765
+ else
1766
+ graphql_definition
1767
+ end
1768
+ GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
1064
1769
  end
1065
1770
 
1066
- def defined_query_analyzers
1067
- @defined_query_analyzers ||= []
1771
+ def instrumenters
1772
+ inherited_instrumenters = find_inherited_value(:instrumenters) || Hash.new { |h,k| h[k] = [] }
1773
+ inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
1774
+ inherited + own
1775
+ end
1068
1776
  end
1069
1777
 
1070
- def defined_middleware
1071
- @defined_middleware ||= []
1778
+ # @api private
1779
+ def add_subscription_extension_if_necessary
1780
+ if interpreter? && !defined?(@subscription_extension_added) && subscription && self.subscriptions
1781
+ @subscription_extension_added = true
1782
+ if subscription.singleton_class.ancestors.include?(Subscriptions::SubscriptionRoot)
1783
+ GraphQL::Deprecation.warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
1784
+ else
1785
+ subscription.all_field_definitions.each do |field|
1786
+ field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1787
+ end
1788
+ end
1789
+ end
1072
1790
  end
1073
1791
 
1074
- def defined_multiplex_analyzers
1075
- @defined_multiplex_analyzers ||= []
1792
+ def query_stack_error(query, err)
1793
+ query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
1076
1794
  end
1077
1795
 
1078
- # Given this schema member, find the class-based definition object
1079
- # whose `method_name` should be treated as an application hook
1080
- # @see {.visible?}
1081
- # @see {.accessible?}
1082
- # @see {.authorized?}
1083
- def call_on_type_class(member, method_name, *args, default:)
1084
- member = if member.respond_to?(:metadata) && member.metadata
1085
- member.metadata[:type_class] || member
1086
- else
1087
- member
1088
- end
1796
+ private
1089
1797
 
1090
- if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
1091
- member = t
1798
+ # @param t [Module, Array<Module>]
1799
+ # @return [void]
1800
+ def add_type_and_traverse(t, root:)
1801
+ if root
1802
+ @root_types ||= []
1803
+ @root_types << t
1092
1804
  end
1805
+ new_types = Array(t)
1806
+ addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
1807
+ addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
1808
+ if (prev_entry = own_types[name])
1809
+ prev_entries = case prev_entry
1810
+ when Array
1811
+ prev_entry
1812
+ when Module
1813
+ own_types[name] = [prev_entry]
1814
+ else
1815
+ raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
1816
+ end
1093
1817
 
1094
- if member.respond_to?(method_name)
1095
- member.public_send(method_name, *args)
1096
- else
1097
- default
1818
+ case types_entry
1819
+ when Array
1820
+ prev_entries.concat(types_entry)
1821
+ prev_entries.uniq! # in case any are being re-visited
1822
+ when Module
1823
+ if !prev_entries.include?(types_entry)
1824
+ prev_entries << types_entry
1825
+ end
1826
+ else
1827
+ raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
1828
+ end
1829
+ else
1830
+ if types_entry.is_a?(Array)
1831
+ types_entry.uniq!
1832
+ end
1833
+ own_types[name] = types_entry
1834
+ end
1098
1835
  end
1099
- end
1100
- end
1101
1836
 
1837
+ own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
1838
+ own_union_memberships.merge!(addition.union_memberships)
1102
1839
 
1103
- def self.inherited(child_class)
1104
- child_class.singleton_class.class_eval do
1105
- prepend(MethodWrappers)
1106
- end
1107
- end
1840
+ addition.references.each { |thing, pointers|
1841
+ pointers.each { |pointer| references_to(thing, from: pointer) }
1842
+ }
1843
+
1844
+ addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
1108
1845
 
1109
- module MethodWrappers
1110
- # Wrap the user-provided resolve-type in a correctness check
1111
- def resolve_type(type, obj, ctx = :__undefined__)
1112
- graphql_definition.check_resolved_type(type, obj, ctx) do |ok_type, ok_obj, ok_ctx|
1113
- super(ok_type, ok_obj, ok_ctx)
1846
+ addition.arguments_with_default_values.each do |arg|
1847
+ arg.validate_default_value
1114
1848
  end
1115
1849
  end
1116
- end
1117
1850
 
1118
- # Call the given block at the right time, either:
1119
- # - Right away, if `value` is not registered with `lazy_resolve`
1120
- # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
1121
- # @api private
1122
- def after_lazy(value)
1123
- if lazy?(value)
1124
- GraphQL::Execution::Lazy.new do
1125
- result = sync_lazy(value)
1126
- # The returned result might also be lazy, so check it, too
1127
- after_lazy(result) do |final_result|
1128
- yield(final_result) if block_given?
1851
+ def lazy_methods
1852
+ if !defined?(@lazy_methods)
1853
+ if inherited_map = find_inherited_value(:lazy_methods)
1854
+ # this isn't _completely_ inherited :S (Things added after `dup` won't work)
1855
+ @lazy_methods = inherited_map.dup
1856
+ else
1857
+ @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
1858
+ @lazy_methods.set(GraphQL::Execution::Lazy, :value)
1859
+ @lazy_methods.set(GraphQL::Dataloader::Request, :load)
1129
1860
  end
1130
1861
  end
1131
- else
1132
- yield(value) if block_given?
1862
+ @lazy_methods
1133
1863
  end
1134
- end
1135
1864
 
1136
- # Override this method to handle lazy objects in a custom way.
1137
- # @param value [Object] an instance of a class registered with {.lazy_resolve}
1138
- # @param ctx [GraphQL::Query::Context] the context for this query
1139
- # @return [Object] A GraphQL-ready (non-lazy) object
1140
- def self.sync_lazy(value)
1141
- if block_given?
1142
- # This was already hit by the instance, just give it back
1143
- yield(value)
1144
- else
1145
- # This was called directly on the class, hit the instance
1146
- # which has the lazy method map
1147
- self.graphql_definition.sync_lazy(value)
1865
+ def own_types
1866
+ @own_types ||= {}
1867
+ end
1868
+
1869
+ def non_introspection_types
1870
+ find_inherited_value(:non_introspection_types, EMPTY_HASH).merge(own_types)
1871
+ end
1872
+
1873
+ def own_plugins
1874
+ @own_plugins ||= []
1875
+ end
1876
+
1877
+ def own_orphan_types
1878
+ @own_orphan_types ||= []
1879
+ end
1880
+
1881
+ def own_possible_types
1882
+ @own_possible_types ||= {}
1883
+ end
1884
+
1885
+ def own_union_memberships
1886
+ @own_union_memberships ||= {}
1887
+ end
1888
+
1889
+ def own_directives
1890
+ @own_directives ||= {}
1891
+ end
1892
+
1893
+ def own_instrumenters
1894
+ @own_instrumenters ||= Hash.new { |h,k| h[k] = [] }
1895
+ end
1896
+
1897
+ def own_tracers
1898
+ @own_tracers ||= []
1899
+ end
1900
+
1901
+ def own_query_analyzers
1902
+ @defined_query_analyzers ||= []
1903
+ end
1904
+
1905
+ def all_middleware
1906
+ find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
1907
+ end
1908
+
1909
+ def own_middleware
1910
+ @own_middleware ||= []
1911
+ end
1912
+
1913
+ def own_multiplex_analyzers
1914
+ @own_multiplex_analyzers ||= []
1148
1915
  end
1149
1916
  end
1150
1917
 
1151
- # @see Schema.sync_lazy for a hook to override
1152
- # @api private
1153
- def sync_lazy(value)
1154
- self.class.sync_lazy(value) { |v|
1155
- lazy_method = lazy_method_name(v)
1156
- if lazy_method
1157
- synced_value = value.public_send(lazy_method)
1158
- sync_lazy(synced_value)
1159
- else
1160
- v
1161
- end
1162
- }
1918
+ def dataloader_class
1919
+ self.class.dataloader_class
1163
1920
  end
1164
1921
 
1922
+ # Install these here so that subclasses will also install it.
1923
+ use(GraphQL::Pagination::Connections)
1924
+
1165
1925
  protected
1166
1926
 
1167
1927
  def rescues?