graphql 0.16.0 → 2.0.15

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 (490) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +5 -0
  3. data/lib/generators/graphql/core.rb +69 -0
  4. data/lib/generators/graphql/enum_generator.rb +27 -0
  5. data/lib/generators/graphql/field_extractor.rb +31 -0
  6. data/lib/generators/graphql/input_generator.rb +50 -0
  7. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  8. data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
  9. data/lib/generators/graphql/install/templates/mutation_type.erb +12 -0
  10. data/lib/generators/graphql/install_generator.rb +197 -0
  11. data/lib/generators/graphql/interface_generator.rb +27 -0
  12. data/lib/generators/graphql/loader_generator.rb +21 -0
  13. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  15. data/lib/generators/graphql/mutation_generator.rb +30 -0
  16. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  17. data/lib/generators/graphql/object_generator.rb +50 -0
  18. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  19. data/lib/generators/graphql/relay.rb +49 -0
  20. data/lib/generators/graphql/relay_generator.rb +21 -0
  21. data/lib/generators/graphql/scalar_generator.rb +22 -0
  22. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  23. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  24. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  25. data/lib/generators/graphql/templates/base_enum.erb +6 -0
  26. data/lib/generators/graphql/templates/base_field.erb +7 -0
  27. data/lib/generators/graphql/templates/base_input_object.erb +7 -0
  28. data/lib/generators/graphql/templates/base_interface.erb +9 -0
  29. data/lib/generators/graphql/templates/base_object.erb +7 -0
  30. data/lib/generators/graphql/templates/base_scalar.erb +6 -0
  31. data/lib/generators/graphql/templates/base_union.erb +6 -0
  32. data/lib/generators/graphql/templates/enum.erb +11 -0
  33. data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
  34. data/lib/generators/graphql/templates/input.erb +9 -0
  35. data/lib/generators/graphql/templates/interface.erb +10 -0
  36. data/lib/generators/graphql/templates/loader.erb +19 -0
  37. data/lib/generators/graphql/templates/mutation.erb +16 -0
  38. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  40. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  41. data/lib/generators/graphql/templates/node_type.erb +9 -0
  42. data/lib/generators/graphql/templates/object.erb +10 -0
  43. data/lib/generators/graphql/templates/query_type.erb +15 -0
  44. data/lib/generators/graphql/templates/scalar.erb +17 -0
  45. data/lib/generators/graphql/templates/schema.erb +30 -0
  46. data/lib/generators/graphql/templates/union.erb +9 -0
  47. data/lib/generators/graphql/type_generator.rb +135 -0
  48. data/lib/generators/graphql/union_generator.rb +33 -0
  49. data/lib/graphql/analysis/ast/analyzer.rb +84 -0
  50. data/lib/graphql/analysis/ast/field_usage.rb +57 -0
  51. data/lib/graphql/analysis/ast/max_query_complexity.rb +22 -0
  52. data/lib/graphql/analysis/ast/max_query_depth.rb +22 -0
  53. data/lib/graphql/analysis/ast/query_complexity.rb +230 -0
  54. data/lib/graphql/analysis/ast/query_depth.rb +55 -0
  55. data/lib/graphql/analysis/ast/visitor.rb +269 -0
  56. data/lib/graphql/analysis/ast.rb +81 -0
  57. data/lib/graphql/analysis.rb +2 -5
  58. data/lib/graphql/analysis_error.rb +1 -0
  59. data/lib/graphql/backtrace/inspect_result.rb +50 -0
  60. data/lib/graphql/backtrace/table.rb +141 -0
  61. data/lib/graphql/backtrace/traced_error.rb +54 -0
  62. data/lib/graphql/backtrace/tracer.rb +80 -0
  63. data/lib/graphql/backtrace.rb +58 -0
  64. data/lib/graphql/coercion_error.rb +13 -0
  65. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  66. data/lib/graphql/dataloader/request.rb +19 -0
  67. data/lib/graphql/dataloader/request_all.rb +19 -0
  68. data/lib/graphql/dataloader/source.rb +164 -0
  69. data/lib/graphql/dataloader.rb +311 -0
  70. data/lib/graphql/date_encoding_error.rb +16 -0
  71. data/lib/graphql/deprecation.rb +9 -0
  72. data/lib/graphql/dig.rb +19 -0
  73. data/lib/graphql/execution/directive_checks.rb +37 -0
  74. data/lib/graphql/execution/errors.rb +93 -0
  75. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  76. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  77. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  78. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  79. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  80. data/lib/graphql/execution/interpreter/resolve.rb +77 -0
  81. data/lib/graphql/execution/interpreter/runtime.rb +994 -0
  82. data/lib/graphql/execution/interpreter.rb +226 -0
  83. data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
  84. data/lib/graphql/execution/lazy.rb +75 -0
  85. data/lib/graphql/execution/lookahead.rb +311 -0
  86. data/lib/graphql/execution/multiplex.rb +45 -0
  87. data/lib/graphql/execution.rb +18 -0
  88. data/lib/graphql/execution_error.rb +34 -1
  89. data/lib/graphql/filter.rb +53 -0
  90. data/lib/graphql/integer_decoding_error.rb +17 -0
  91. data/lib/graphql/integer_encoding_error.rb +36 -0
  92. data/lib/graphql/introspection/base_object.rb +13 -0
  93. data/lib/graphql/introspection/directive_location_enum.rb +12 -5
  94. data/lib/graphql/introspection/directive_type.rb +30 -10
  95. data/lib/graphql/introspection/dynamic_fields.rb +12 -0
  96. data/lib/graphql/introspection/entry_points.rb +22 -0
  97. data/lib/graphql/introspection/enum_value_type.rb +21 -8
  98. data/lib/graphql/introspection/field_type.rb +26 -10
  99. data/lib/graphql/introspection/input_value_type.rb +64 -14
  100. data/lib/graphql/introspection/introspection_query.rb +7 -76
  101. data/lib/graphql/introspection/schema_type.rb +42 -17
  102. data/lib/graphql/introspection/type_kind_enum.rb +11 -5
  103. data/lib/graphql/introspection/type_type.rb +104 -16
  104. data/lib/graphql/introspection.rb +104 -13
  105. data/lib/graphql/invalid_name_error.rb +11 -0
  106. data/lib/graphql/invalid_null_error.rb +36 -8
  107. data/lib/graphql/language/block_string.rb +99 -0
  108. data/lib/graphql/language/cache.rb +37 -0
  109. data/lib/graphql/language/definition_slice.rb +41 -0
  110. data/lib/graphql/language/document_from_schema_definition.rb +335 -0
  111. data/lib/graphql/language/generation.rb +16 -86
  112. data/lib/graphql/language/lexer.rb +1436 -705
  113. data/lib/graphql/language/lexer.rl +172 -64
  114. data/lib/graphql/language/nodes.rb +617 -105
  115. data/lib/graphql/language/parser.rb +1524 -430
  116. data/lib/graphql/language/parser.y +348 -73
  117. data/lib/graphql/language/printer.rb +386 -0
  118. data/lib/graphql/language/sanitized_printer.rb +222 -0
  119. data/lib/graphql/language/token.rb +16 -3
  120. data/lib/graphql/language/visitor.rb +169 -25
  121. data/lib/graphql/language.rb +30 -0
  122. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  123. data/lib/graphql/name_validator.rb +11 -0
  124. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  125. data/lib/graphql/pagination/array_connection.rb +79 -0
  126. data/lib/graphql/pagination/connection.rb +253 -0
  127. data/lib/graphql/pagination/connections.rb +135 -0
  128. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  129. data/lib/graphql/pagination/relation_connection.rb +228 -0
  130. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  131. data/lib/graphql/pagination.rb +6 -0
  132. data/lib/graphql/parse_error.rb +24 -0
  133. data/lib/graphql/query/context.rb +266 -12
  134. data/lib/graphql/query/fingerprint.rb +26 -0
  135. data/lib/graphql/query/input_validation_result.rb +34 -7
  136. data/lib/graphql/query/null_context.rb +52 -0
  137. data/lib/graphql/query/result.rb +63 -0
  138. data/lib/graphql/query/validation_pipeline.rb +114 -0
  139. data/lib/graphql/query/variable_validation_error.rb +27 -3
  140. data/lib/graphql/query/variables.rb +75 -24
  141. data/lib/graphql/query.rb +359 -92
  142. data/lib/graphql/railtie.rb +13 -0
  143. data/lib/graphql/rake_task/validate.rb +63 -0
  144. data/lib/graphql/rake_task.rb +146 -0
  145. data/lib/graphql/relay/range_add.rb +52 -0
  146. data/lib/graphql/relay.rb +3 -0
  147. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  148. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  149. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  150. data/lib/graphql/rubocop.rb +4 -0
  151. data/lib/graphql/runtime_type_error.rb +5 -0
  152. data/lib/graphql/schema/addition.rb +245 -0
  153. data/lib/graphql/schema/argument.rb +395 -0
  154. data/lib/graphql/schema/base_64_bp.rb +26 -0
  155. data/lib/graphql/schema/base_64_encoder.rb +21 -0
  156. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
  157. data/lib/graphql/schema/build_from_definition/resolve_map.rb +78 -0
  158. data/lib/graphql/schema/build_from_definition.rb +492 -0
  159. data/lib/graphql/schema/built_in_types.rb +12 -0
  160. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  161. data/lib/graphql/schema/directive/feature.rb +66 -0
  162. data/lib/graphql/schema/directive/flagged.rb +57 -0
  163. data/lib/graphql/schema/directive/include.rb +25 -0
  164. data/lib/graphql/schema/directive/one_of.rb +12 -0
  165. data/lib/graphql/schema/directive/skip.rb +25 -0
  166. data/lib/graphql/schema/directive/transform.rb +60 -0
  167. data/lib/graphql/schema/directive.rb +212 -0
  168. data/lib/graphql/schema/enum.rb +176 -0
  169. data/lib/graphql/schema/enum_value.rb +77 -0
  170. data/lib/graphql/schema/field/connection_extension.rb +80 -0
  171. data/lib/graphql/schema/field/scope_extension.rb +22 -0
  172. data/lib/graphql/schema/field.rb +862 -0
  173. data/lib/graphql/schema/field_extension.rb +156 -0
  174. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  175. data/lib/graphql/schema/finder.rb +155 -0
  176. data/lib/graphql/schema/input_object.rb +258 -0
  177. data/lib/graphql/schema/interface.rb +113 -0
  178. data/lib/graphql/schema/introspection_system.rb +164 -0
  179. data/lib/graphql/schema/invalid_type_error.rb +1 -0
  180. data/lib/graphql/schema/late_bound_type.rb +37 -0
  181. data/lib/graphql/schema/list.rb +86 -0
  182. data/lib/graphql/schema/loader.rb +228 -0
  183. data/lib/graphql/schema/member/base_dsl_methods.rb +124 -0
  184. data/lib/graphql/schema/member/build_type.rb +178 -0
  185. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  186. data/lib/graphql/schema/member/has_arguments.rb +376 -0
  187. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  188. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  189. data/lib/graphql/schema/member/has_directives.rb +113 -0
  190. data/lib/graphql/schema/member/has_fields.rb +163 -0
  191. data/lib/graphql/schema/member/has_interfaces.rb +88 -0
  192. data/lib/graphql/schema/member/has_path.rb +25 -0
  193. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  194. data/lib/graphql/schema/member/has_validators.rb +31 -0
  195. data/lib/graphql/schema/member/relay_shortcuts.rb +73 -0
  196. data/lib/graphql/schema/member/scoped.rb +21 -0
  197. data/lib/graphql/schema/member/type_system_helpers.rb +38 -0
  198. data/lib/graphql/schema/member/validates_input.rb +33 -0
  199. data/lib/graphql/schema/member.rb +39 -0
  200. data/lib/graphql/schema/mutation.rb +85 -0
  201. data/lib/graphql/schema/non_null.rb +67 -0
  202. data/lib/graphql/schema/null_mask.rb +11 -0
  203. data/lib/graphql/schema/object.rb +117 -0
  204. data/lib/graphql/schema/printer.rb +72 -128
  205. data/lib/graphql/schema/relay_classic_mutation.rb +179 -0
  206. data/lib/graphql/schema/resolver/has_payload_type.rb +106 -0
  207. data/lib/graphql/schema/resolver.rb +402 -0
  208. data/lib/graphql/schema/scalar.rb +68 -0
  209. data/lib/graphql/schema/subscription.rb +148 -0
  210. data/lib/graphql/schema/timeout.rb +123 -0
  211. data/lib/graphql/schema/type_expression.rb +29 -5
  212. data/lib/graphql/schema/type_membership.rb +51 -0
  213. data/lib/graphql/schema/union.rb +81 -0
  214. data/lib/graphql/schema/unique_within_type.rb +34 -0
  215. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  216. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  217. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  218. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  219. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  220. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  221. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  222. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  223. data/lib/graphql/schema/validator.rb +171 -0
  224. data/lib/graphql/schema/warden.rb +413 -0
  225. data/lib/graphql/schema/wrapper.rb +24 -0
  226. data/lib/graphql/schema.rb +1179 -104
  227. data/lib/graphql/static_validation/all_rules.rb +14 -0
  228. data/lib/graphql/static_validation/base_visitor.rb +200 -0
  229. data/lib/graphql/static_validation/definition_dependencies.rb +198 -0
  230. data/lib/graphql/static_validation/error.rb +46 -0
  231. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  232. data/lib/graphql/static_validation/literal_validator.rb +113 -22
  233. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +59 -11
  234. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +48 -0
  235. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +31 -0
  236. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  237. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +62 -8
  238. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
  239. data/lib/graphql/static_validation/rules/directives_are_defined.rb +20 -13
  240. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  241. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +32 -26
  242. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  243. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +21 -23
  244. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  245. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +55 -18
  246. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  247. data/lib/graphql/static_validation/rules/fields_will_merge.rb +390 -70
  248. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +53 -0
  249. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +30 -0
  250. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  251. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +54 -37
  252. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  253. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +26 -16
  254. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  255. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +13 -19
  256. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  257. data/lib/graphql/static_validation/rules/fragments_are_named.rb +16 -0
  258. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  259. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +25 -20
  260. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  261. data/lib/graphql/static_validation/rules/fragments_are_used.rb +22 -33
  262. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  263. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  264. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  265. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +17 -0
  266. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  267. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +41 -0
  268. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  269. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  270. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  271. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +36 -0
  272. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  273. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  274. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  275. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +22 -21
  276. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  277. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +59 -0
  278. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  279. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +17 -0
  280. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  281. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +56 -0
  282. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  283. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +36 -18
  284. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  285. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +24 -0
  286. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  287. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +103 -39
  288. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  289. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +22 -14
  290. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  291. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +92 -70
  292. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  293. data/lib/graphql/static_validation/type_stack.rb +85 -24
  294. data/lib/graphql/static_validation/validation_context.rb +25 -46
  295. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  296. data/lib/graphql/static_validation/validator.rb +46 -15
  297. data/lib/graphql/static_validation.rb +6 -3
  298. data/lib/graphql/string_encoding_error.rb +20 -0
  299. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +247 -0
  300. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  301. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  302. data/lib/graphql/subscriptions/event.rb +144 -0
  303. data/lib/graphql/subscriptions/instrumentation.rb +28 -0
  304. data/lib/graphql/subscriptions/serialize.rb +158 -0
  305. data/lib/graphql/subscriptions.rb +306 -0
  306. data/lib/graphql/tracing/active_support_notifications_tracing.rb +21 -0
  307. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  308. data/lib/graphql/tracing/appsignal_tracing.rb +51 -0
  309. data/lib/graphql/tracing/data_dog_tracing.rb +100 -0
  310. data/lib/graphql/tracing/instrumentation_tracing.rb +83 -0
  311. data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
  312. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  313. data/lib/graphql/tracing/platform_tracing.rb +122 -0
  314. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +32 -0
  315. data/lib/graphql/tracing/prometheus_tracing.rb +67 -0
  316. data/lib/graphql/tracing/scout_tracing.rb +54 -0
  317. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  318. data/lib/graphql/tracing.rb +94 -0
  319. data/lib/graphql/type_kinds.rb +50 -22
  320. data/lib/graphql/types/big_int.rb +23 -0
  321. data/lib/graphql/types/boolean.rb +18 -0
  322. data/lib/graphql/types/float.rb +19 -0
  323. data/lib/graphql/types/id.rb +24 -0
  324. data/lib/graphql/types/int.rb +36 -0
  325. data/lib/graphql/types/iso_8601_date.rb +45 -0
  326. data/lib/graphql/types/iso_8601_date_time.rb +76 -0
  327. data/lib/graphql/types/json.rb +25 -0
  328. data/lib/graphql/types/relay/base_connection.rb +49 -0
  329. data/lib/graphql/types/relay/base_edge.rb +29 -0
  330. data/lib/graphql/types/relay/connection_behaviors.rb +154 -0
  331. data/lib/graphql/types/relay/default_relay.rb +21 -0
  332. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  333. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  334. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  335. data/lib/graphql/types/relay/node.rb +15 -0
  336. data/lib/graphql/types/relay/node_behaviors.rb +19 -0
  337. data/lib/graphql/types/relay/page_info.rb +11 -0
  338. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  339. data/lib/graphql/types/relay.rb +39 -0
  340. data/lib/graphql/types/string.rb +29 -0
  341. data/lib/graphql/types.rb +11 -0
  342. data/lib/graphql/unauthorized_error.rb +29 -0
  343. data/lib/graphql/unauthorized_field_error.rb +23 -0
  344. data/lib/graphql/unresolved_type_error.rb +35 -0
  345. data/lib/graphql/version.rb +2 -1
  346. data/lib/graphql.rb +86 -41
  347. data/readme.md +15 -101
  348. metadata +394 -279
  349. data/lib/graphql/analysis/analyze_query.rb +0 -73
  350. data/lib/graphql/analysis/max_query_complexity.rb +0 -25
  351. data/lib/graphql/analysis/max_query_depth.rb +0 -25
  352. data/lib/graphql/analysis/query_complexity.rb +0 -122
  353. data/lib/graphql/analysis/query_depth.rb +0 -54
  354. data/lib/graphql/argument.rb +0 -25
  355. data/lib/graphql/base_type.rb +0 -115
  356. data/lib/graphql/boolean_type.rb +0 -9
  357. data/lib/graphql/define/assign_argument.rb +0 -20
  358. data/lib/graphql/define/assign_enum_value.rb +0 -16
  359. data/lib/graphql/define/assign_object_field.rb +0 -21
  360. data/lib/graphql/define/assignment_dictionary.rb +0 -26
  361. data/lib/graphql/define/defined_object_proxy.rb +0 -32
  362. data/lib/graphql/define/instance_definable.rb +0 -79
  363. data/lib/graphql/define/non_null_with_bang.rb +0 -15
  364. data/lib/graphql/define/type_definer.rb +0 -30
  365. data/lib/graphql/define.rb +0 -8
  366. data/lib/graphql/directive/include_directive.rb +0 -10
  367. data/lib/graphql/directive/skip_directive.rb +0 -11
  368. data/lib/graphql/directive.rb +0 -49
  369. data/lib/graphql/enum_type.rb +0 -95
  370. data/lib/graphql/field.rb +0 -131
  371. data/lib/graphql/float_type.rb +0 -5
  372. data/lib/graphql/id_type.rb +0 -12
  373. data/lib/graphql/input_object_type.rb +0 -71
  374. data/lib/graphql/int_type.rb +0 -5
  375. data/lib/graphql/interface_type.rb +0 -38
  376. data/lib/graphql/internal_representation/node.rb +0 -81
  377. data/lib/graphql/internal_representation/rewrite.rb +0 -177
  378. data/lib/graphql/internal_representation.rb +0 -2
  379. data/lib/graphql/introspection/arguments_field.rb +0 -5
  380. data/lib/graphql/introspection/enum_values_field.rb +0 -13
  381. data/lib/graphql/introspection/fields_field.rb +0 -13
  382. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  383. data/lib/graphql/introspection/interfaces_field.rb +0 -5
  384. data/lib/graphql/introspection/of_type_field.rb +0 -6
  385. data/lib/graphql/introspection/possible_types_field.rb +0 -11
  386. data/lib/graphql/introspection/schema_field.rb +0 -15
  387. data/lib/graphql/introspection/type_by_name_field.rb +0 -16
  388. data/lib/graphql/introspection/typename_field.rb +0 -15
  389. data/lib/graphql/list_type.rb +0 -46
  390. data/lib/graphql/non_null_type.rb +0 -43
  391. data/lib/graphql/object_type.rb +0 -93
  392. data/lib/graphql/query/arguments.rb +0 -76
  393. data/lib/graphql/query/directive_resolution.rb +0 -16
  394. data/lib/graphql/query/executor.rb +0 -45
  395. data/lib/graphql/query/literal_input.rb +0 -90
  396. data/lib/graphql/query/serial_execution/execution_context.rb +0 -31
  397. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -82
  398. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -27
  399. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -42
  400. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -107
  401. data/lib/graphql/query/serial_execution.rb +0 -41
  402. data/lib/graphql/query/type_resolver.rb +0 -25
  403. data/lib/graphql/scalar_type.rb +0 -53
  404. data/lib/graphql/schema/catchall_middleware.rb +0 -34
  405. data/lib/graphql/schema/middleware_chain.rb +0 -28
  406. data/lib/graphql/schema/possible_types.rb +0 -34
  407. data/lib/graphql/schema/reduce_types.rb +0 -68
  408. data/lib/graphql/schema/rescue_middleware.rb +0 -53
  409. data/lib/graphql/schema/timeout_middleware.rb +0 -67
  410. data/lib/graphql/schema/type_map.rb +0 -30
  411. data/lib/graphql/schema/validation.rb +0 -164
  412. data/lib/graphql/static_validation/arguments_validator.rb +0 -48
  413. data/lib/graphql/static_validation/message.rb +0 -36
  414. data/lib/graphql/string_type.rb +0 -5
  415. data/lib/graphql/union_type.rb +0 -38
  416. data/spec/graphql/analysis/analyze_query_spec.rb +0 -50
  417. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -62
  418. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -100
  419. data/spec/graphql/analysis/query_complexity_spec.rb +0 -235
  420. data/spec/graphql/analysis/query_depth_spec.rb +0 -80
  421. data/spec/graphql/argument_spec.rb +0 -20
  422. data/spec/graphql/base_type_spec.rb +0 -24
  423. data/spec/graphql/boolean_type_spec.rb +0 -20
  424. data/spec/graphql/define/instance_definable_spec.rb +0 -55
  425. data/spec/graphql/directive_spec.rb +0 -77
  426. data/spec/graphql/enum_type_spec.rb +0 -31
  427. data/spec/graphql/execution_error_spec.rb +0 -61
  428. data/spec/graphql/field_spec.rb +0 -92
  429. data/spec/graphql/float_type_spec.rb +0 -15
  430. data/spec/graphql/id_type_spec.rb +0 -32
  431. data/spec/graphql/input_object_type_spec.rb +0 -162
  432. data/spec/graphql/int_type_spec.rb +0 -15
  433. data/spec/graphql/interface_type_spec.rb +0 -56
  434. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -120
  435. data/spec/graphql/introspection/directive_type_spec.rb +0 -50
  436. data/spec/graphql/introspection/input_value_type_spec.rb +0 -42
  437. data/spec/graphql/introspection/introspection_query_spec.rb +0 -10
  438. data/spec/graphql/introspection/schema_type_spec.rb +0 -45
  439. data/spec/graphql/introspection/type_type_spec.rb +0 -122
  440. data/spec/graphql/language/generation_spec.rb +0 -42
  441. data/spec/graphql/language/parser_spec.rb +0 -442
  442. data/spec/graphql/language/visitor_spec.rb +0 -49
  443. data/spec/graphql/list_type_spec.rb +0 -32
  444. data/spec/graphql/non_null_type_spec.rb +0 -31
  445. data/spec/graphql/object_type_spec.rb +0 -42
  446. data/spec/graphql/query/arguments_spec.rb +0 -25
  447. data/spec/graphql/query/context_spec.rb +0 -83
  448. data/spec/graphql/query/executor_spec.rb +0 -273
  449. data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -53
  450. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -66
  451. data/spec/graphql/query/type_resolver_spec.rb +0 -8
  452. data/spec/graphql/query/variables_spec.rb +0 -28
  453. data/spec/graphql/query_spec.rb +0 -363
  454. data/spec/graphql/scalar_type_spec.rb +0 -61
  455. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -32
  456. data/spec/graphql/schema/middleware_chain_spec.rb +0 -42
  457. data/spec/graphql/schema/printer_spec.rb +0 -190
  458. data/spec/graphql/schema/reduce_types_spec.rb +0 -102
  459. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -33
  460. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -180
  461. data/spec/graphql/schema/type_expression_spec.rb +0 -38
  462. data/spec/graphql/schema/validation_spec.rb +0 -219
  463. data/spec/graphql/schema_spec.rb +0 -23
  464. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -63
  465. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -48
  466. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -34
  467. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -39
  468. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -60
  469. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -31
  470. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -48
  471. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -47
  472. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -39
  473. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -44
  474. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -49
  475. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -25
  476. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -42
  477. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -44
  478. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -63
  479. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -37
  480. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -53
  481. data/spec/graphql/static_validation/type_stack_spec.rb +0 -37
  482. data/spec/graphql/static_validation/validator_spec.rb +0 -69
  483. data/spec/graphql/string_type_spec.rb +0 -15
  484. data/spec/graphql/union_type_spec.rb +0 -31
  485. data/spec/spec_helper.rb +0 -18
  486. data/spec/support/dairy_app.rb +0 -309
  487. data/spec/support/dairy_data.rb +0 -23
  488. data/spec/support/minimum_input_object.rb +0 -16
  489. data/spec/support/star_wars_data.rb +0 -71
  490. data/spec/support/star_wars_schema.rb +0 -76
@@ -1,127 +1,1202 @@
1
- require "graphql/schema/catchall_middleware"
1
+ # frozen_string_literal: true
2
+ require "graphql/schema/addition"
3
+ require "graphql/schema/base_64_encoder"
4
+ require "graphql/schema/find_inherited_value"
5
+ require "graphql/schema/finder"
2
6
  require "graphql/schema/invalid_type_error"
3
- require "graphql/schema/middleware_chain"
4
- require "graphql/schema/rescue_middleware"
5
- require "graphql/schema/possible_types"
6
- require "graphql/schema/reduce_types"
7
- require "graphql/schema/timeout_middleware"
7
+ require "graphql/schema/introspection_system"
8
+ require "graphql/schema/late_bound_type"
9
+ require "graphql/schema/null_mask"
10
+ require "graphql/schema/timeout"
8
11
  require "graphql/schema/type_expression"
9
- require "graphql/schema/type_map"
10
- require "graphql/schema/validation"
12
+ require "graphql/schema/unique_within_type"
13
+ require "graphql/schema/warden"
14
+ require "graphql/schema/build_from_definition"
15
+
16
+ require "graphql/schema/validator"
17
+ require "graphql/schema/member"
18
+ require "graphql/schema/wrapper"
19
+ require "graphql/schema/list"
20
+ require "graphql/schema/non_null"
21
+ require "graphql/schema/argument"
22
+ require "graphql/schema/enum_value"
23
+ require "graphql/schema/enum"
24
+ require "graphql/schema/field_extension"
25
+ require "graphql/schema/field"
26
+ require "graphql/schema/input_object"
27
+ require "graphql/schema/interface"
28
+ require "graphql/schema/scalar"
29
+ require "graphql/schema/object"
30
+ require "graphql/schema/union"
31
+ require "graphql/schema/directive"
32
+ require "graphql/schema/directive/deprecated"
33
+ require "graphql/schema/directive/include"
34
+ require "graphql/schema/directive/one_of"
35
+ require "graphql/schema/directive/skip"
36
+ require "graphql/schema/directive/feature"
37
+ require "graphql/schema/directive/flagged"
38
+ require "graphql/schema/directive/transform"
39
+ require "graphql/schema/type_membership"
40
+
41
+ require "graphql/schema/resolver"
42
+ require "graphql/schema/mutation"
43
+ require "graphql/schema/relay_classic_mutation"
44
+ require "graphql/schema/subscription"
11
45
 
12
46
  module GraphQL
13
47
  # A GraphQL schema which may be queried with {GraphQL::Query}.
48
+ #
49
+ # The {Schema} contains:
50
+ #
51
+ # - types for exposing your application
52
+ # - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
53
+ # - execution strategies for running incoming queries
54
+ #
55
+ # Schemas start with root types, {Schema#query}, {Schema#mutation} and {Schema#subscription}.
56
+ # The schema will traverse the tree of fields & types, using those as starting points.
57
+ # Any undiscoverable types may be provided with the `types` configuration.
58
+ #
59
+ # Schemas can restrict large incoming queries with `max_depth` and `max_complexity` configurations.
60
+ # (These configurations can be overridden by specific calls to {Schema#execute})
61
+ #
62
+ # Schemas can specify how queries should be executed against them.
63
+ # `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
64
+ # each apply to corresponding root types.
65
+ # #
66
+ # @example defining a schema
67
+ # class MySchema < GraphQL::Schema
68
+ # query QueryType
69
+ # # If types are only connected by way of interfaces, they must be added here
70
+ # orphan_types ImageType, AudioType
71
+ # end
72
+ #
14
73
  class Schema
15
- extend Forwardable
16
-
17
- DIRECTIVES = [GraphQL::Directive::SkipDirective, GraphQL::Directive::IncludeDirective]
18
- DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
19
-
20
- attr_reader :query, :mutation, :subscription, :directives, :static_validator, :query_analyzers
21
- attr_accessor :max_depth
22
- attr_accessor :max_complexity
23
-
24
- # Override these if you don't want the default executor:
25
- attr_accessor :query_execution_strategy,
26
- :mutation_execution_strategy,
27
- :subscription_execution_strategy
28
-
29
- # @return [Array<#call>] Middlewares suitable for MiddlewareChain, applied to fields during execution
30
- attr_reader :middleware
31
-
32
- # @param query [GraphQL::ObjectType] the query root for the schema
33
- # @param mutation [GraphQL::ObjectType] the mutation root for the schema
34
- # @param subscription [GraphQL::ObjectType] the subscription root for the schema
35
- # @param max_depth [Integer] maximum query nesting (if it's greater, raise an error)
36
- # @param types [Array<GraphQL::BaseType>] additional types to include in this schema
37
- def initialize(query:, mutation: nil, subscription: nil, max_depth: nil, max_complexity: nil, types: [])
38
- @query = query
39
- @mutation = mutation
40
- @subscription = subscription
41
- @max_depth = max_depth
42
- @max_complexity = max_complexity
43
- @orphan_types = types
44
- @directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
45
- @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
46
- @rescue_middleware = GraphQL::Schema::RescueMiddleware.new
47
- @middleware = [@rescue_middleware]
48
- @query_analyzers = []
49
- # Default to the built-in execution strategy:
50
- self.query_execution_strategy = GraphQL::Query::SerialExecution
51
- self.mutation_execution_strategy = GraphQL::Query::SerialExecution
52
- self.subscription_execution_strategy = GraphQL::Query::SerialExecution
53
- end
54
-
55
- def_delegators :@rescue_middleware, :rescue_from, :remove_handler
74
+ extend GraphQL::Schema::Member::HasAstNode
75
+ extend GraphQL::Schema::FindInheritedValue
56
76
 
57
- # @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
58
- def types
59
- @types ||= begin
60
- all_types = @orphan_types + [query, mutation, subscription, GraphQL::Introspection::SchemaType]
61
- GraphQL::Schema::ReduceTypes.reduce(all_types.compact)
77
+ class DuplicateNamesError < GraphQL::Error
78
+ attr_reader :duplicated_name
79
+ def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
80
+ @duplicated_name = duplicated_name
81
+ super(
82
+ "Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
83
+ )
62
84
  end
63
85
  end
64
86
 
65
- # Execute a query on itself.
66
- # See {Query#initialize} for arguments.
67
- # @return [Hash] query result, ready to be serialized as JSON
68
- def execute(*args)
69
- query = GraphQL::Query.new(self, *args)
70
- query.result
87
+ class UnresolvedLateBoundTypeError < GraphQL::Error
88
+ attr_reader :type
89
+ def initialize(type:)
90
+ @type = type
91
+ super("Late bound type was never found: #{type.inspect}")
92
+ end
71
93
  end
72
94
 
73
- # Resolve field named `field_name` for type `parent_type`.
74
- # Handles dynamic fields `__typename`, `__type` and `__schema`, too
75
- def get_field(parent_type, field_name)
76
- defined_field = parent_type.get_field(field_name)
77
- if defined_field
78
- defined_field
79
- elsif field_name == "__typename"
80
- GraphQL::Introspection::TypenameField.create(parent_type)
81
- elsif field_name == "__schema" && parent_type == query
82
- GraphQL::Introspection::SchemaField.create(self)
83
- elsif field_name == "__type" && parent_type == query
84
- GraphQL::Introspection::TypeByNameField.create(self.types)
85
- else
95
+ # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
96
+ class InvalidDocumentError < Error; end;
97
+
98
+ class << self
99
+ # Create schema with the result of an introspection query.
100
+ # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
101
+ # @return [Class<GraphQL::Schema>] the schema described by `input`
102
+ def from_introspection(introspection_result)
103
+ GraphQL::Schema::Loader.load(introspection_result)
104
+ end
105
+
106
+ # Create schema from an IDL schema or file containing an IDL definition.
107
+ # @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
108
+ # @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
109
+ # @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
110
+ # @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
111
+ # @return [Class] the schema described by `document`
112
+ def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
113
+ # If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
114
+ if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
115
+ GraphQL::Schema::BuildFromDefinition.from_definition_path(
116
+ self,
117
+ definition_or_path,
118
+ default_resolve: default_resolve,
119
+ parser: parser,
120
+ using: using,
121
+ )
122
+ else
123
+ GraphQL::Schema::BuildFromDefinition.from_definition(
124
+ self,
125
+ definition_or_path,
126
+ default_resolve: default_resolve,
127
+ parser: parser,
128
+ using: using,
129
+ )
130
+ end
131
+ end
132
+
133
+ def deprecated_graphql_definition
134
+ graphql_definition(silence_deprecation_warning: true)
135
+ end
136
+
137
+ # @return [GraphQL::Subscriptions]
138
+ def subscriptions(inherited: true)
139
+ defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
140
+ end
141
+
142
+ def subscriptions=(new_implementation)
143
+ @subscriptions = new_implementation
144
+ end
145
+
146
+ # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
147
+ # @see {#as_json}
148
+ # @return [String]
149
+ def to_json(**args)
150
+ JSON.pretty_generate(as_json(**args))
151
+ end
152
+
153
+ # Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
154
+ # @param context [Hash]
155
+ # @param only [<#call(member, ctx)>]
156
+ # @param except [<#call(member, ctx)>]
157
+ # @return [Hash] GraphQL result
158
+ def as_json(only: nil, except: nil, context: {})
159
+ execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
160
+ end
161
+
162
+ # Return the GraphQL IDL for the schema
163
+ # @param context [Hash]
164
+ # @param only [<#call(member, ctx)>]
165
+ # @param except [<#call(member, ctx)>]
166
+ # @return [String]
167
+ def to_definition(only: nil, except: nil, context: {})
168
+ GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
169
+ end
170
+
171
+ # Return the GraphQL::Language::Document IDL AST for the schema
172
+ # @return [GraphQL::Language::Document]
173
+ def to_document
174
+ GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
175
+ end
176
+
177
+ # @return [String, nil]
178
+ def description(new_description = nil)
179
+ if new_description
180
+ @description = new_description
181
+ elsif defined?(@description)
182
+ @description
183
+ else
184
+ find_inherited_value(:description, nil)
185
+ end
186
+ end
187
+
188
+ def find(path)
189
+ if !@finder
190
+ @find_cache = {}
191
+ @finder ||= GraphQL::Schema::Finder.new(self)
192
+ end
193
+ @find_cache[path] ||= @finder.find(path)
194
+ end
195
+
196
+ def default_filter
197
+ GraphQL::Filter.new(except: default_mask)
198
+ end
199
+
200
+ def default_mask(new_mask = nil)
201
+ if new_mask
202
+ @own_default_mask = new_mask
203
+ else
204
+ @own_default_mask || find_inherited_value(:default_mask, Schema::NullMask)
205
+ end
206
+ end
207
+
208
+ def static_validator
209
+ GraphQL::StaticValidation::Validator.new(schema: self)
210
+ end
211
+
212
+ def use(plugin, **kwargs)
213
+ if kwargs.any?
214
+ plugin.use(self, **kwargs)
215
+ else
216
+ plugin.use(self)
217
+ end
218
+ own_plugins << [plugin, kwargs]
219
+ end
220
+
221
+ def plugins
222
+ find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
223
+ end
224
+
225
+ # Build a map of `{ name => type }` and return it
226
+ # @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
227
+ # @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
228
+ def types(context = GraphQL::Query::NullContext)
229
+ all_types = non_introspection_types.merge(introspection_system.types)
230
+ visible_types = {}
231
+ all_types.each do |k, v|
232
+ visible_types[k] =if v.is_a?(Array)
233
+ visible_t = nil
234
+ v.each do |t|
235
+ if t.visible?(context)
236
+ if visible_t.nil?
237
+ visible_t = t
238
+ else
239
+ raise DuplicateNamesError.new(
240
+ duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
241
+ )
242
+ end
243
+ end
244
+ end
245
+ visible_t
246
+ else
247
+ v
248
+ end
249
+ end
250
+ visible_types
251
+ end
252
+
253
+ # @param type_name [String]
254
+ # @return [Module, nil] A type, or nil if there's no type called `type_name`
255
+ def get_type(type_name, context = GraphQL::Query::NullContext)
256
+ local_entry = own_types[type_name]
257
+ type_defn = case local_entry
258
+ when nil
259
+ nil
260
+ when Array
261
+ visible_t = nil
262
+ warden = Warden.from_context(context)
263
+ local_entry.each do |t|
264
+ if warden.visible_type?(t, context)
265
+ if visible_t.nil?
266
+ visible_t = t
267
+ else
268
+ raise DuplicateNamesError.new(
269
+ duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
270
+ )
271
+ end
272
+ end
273
+ end
274
+ visible_t
275
+ when Module
276
+ local_entry
277
+ else
278
+ raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
279
+ end
280
+
281
+ type_defn ||
282
+ introspection_system.types[type_name] || # todo context-specific introspection?
283
+ (superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
284
+ end
285
+
286
+ # @api private
287
+ attr_writer :connections
288
+
289
+ # @return [GraphQL::Pagination::Connections] if installed
290
+ def connections
291
+ if defined?(@connections)
292
+ @connections
293
+ else
294
+ inherited_connections = find_inherited_value(:connections, nil)
295
+ # This schema is part of an inheritance chain which is using new connections,
296
+ # make a new instance, so we don't pollute the upstream one.
297
+ if inherited_connections
298
+ @connections = Pagination::Connections.new(schema: self)
299
+ else
300
+ nil
301
+ end
302
+ end
303
+ end
304
+
305
+ def new_connections?
306
+ !!connections
307
+ end
308
+
309
+ def query(new_query_object = nil)
310
+ if new_query_object
311
+ if @query_object
312
+ raise GraphQL::Error, "Second definition of `query(...)` (#{new_query_object.inspect}) is invalid, already configured with #{@query_object.inspect}"
313
+ else
314
+ @query_object = new_query_object
315
+ add_type_and_traverse(new_query_object, root: true)
316
+ nil
317
+ end
318
+ else
319
+ @query_object || find_inherited_value(:query)
320
+ end
321
+ end
322
+
323
+ def mutation(new_mutation_object = nil)
324
+ if new_mutation_object
325
+ if @mutation_object
326
+ raise GraphQL::Error, "Second definition of `mutation(...)` (#{new_mutation_object.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
327
+ else
328
+ @mutation_object = new_mutation_object
329
+ add_type_and_traverse(new_mutation_object, root: true)
330
+ nil
331
+ end
332
+ else
333
+ @mutation_object || find_inherited_value(:mutation)
334
+ end
335
+ end
336
+
337
+ def subscription(new_subscription_object = nil)
338
+ if new_subscription_object
339
+ if @subscription_object
340
+ raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
341
+ else
342
+ @subscription_object = new_subscription_object
343
+ add_subscription_extension_if_necessary
344
+ add_type_and_traverse(new_subscription_object, root: true)
345
+ nil
346
+ end
347
+ else
348
+ @subscription_object || find_inherited_value(:subscription)
349
+ end
350
+ end
351
+
352
+ # @see [GraphQL::Schema::Warden] Restricted access to root types
353
+ # @return [GraphQL::ObjectType, nil]
354
+ def root_type_for_operation(operation)
355
+ case operation
356
+ when "query"
357
+ query
358
+ when "mutation"
359
+ mutation
360
+ when "subscription"
361
+ subscription
362
+ else
363
+ raise ArgumentError, "unknown operation type: #{operation}"
364
+ end
365
+ end
366
+
367
+ def root_types
368
+ @root_types
369
+ end
370
+
371
+ # @param type [Module] The type definition whose possible types you want to see
372
+ # @return [Hash<String, Module>] All possible types, if no `type` is given.
373
+ # @return [Array<Module>] Possible types for `type`, if it's given.
374
+ def possible_types(type = nil, context = GraphQL::Query::NullContext)
375
+ if type
376
+ # TODO duck-typing `.possible_types` would probably be nicer here
377
+ if type.kind.union?
378
+ type.possible_types(context: context)
379
+ else
380
+ stored_possible_types = own_possible_types[type.graphql_name]
381
+ visible_possible_types = if stored_possible_types && type.kind.interface?
382
+ stored_possible_types.select do |possible_type|
383
+ possible_type.interfaces(context).include?(type)
384
+ end
385
+ else
386
+ stored_possible_types
387
+ end
388
+ visible_possible_types ||
389
+ introspection_system.possible_types[type.graphql_name] ||
390
+ (
391
+ superclass.respond_to?(:possible_types) ?
392
+ superclass.possible_types(type, context) :
393
+ EMPTY_ARRAY
394
+ )
395
+ end
396
+ else
397
+ find_inherited_value(:possible_types, EMPTY_HASH)
398
+ .merge(own_possible_types)
399
+ .merge(introspection_system.possible_types)
400
+ end
401
+ end
402
+
403
+ def union_memberships(type = nil)
404
+ if type
405
+ own_um = own_union_memberships.fetch(type.graphql_name, EMPTY_ARRAY)
406
+ inherited_um = find_inherited_value(:union_memberships, EMPTY_HASH).fetch(type.graphql_name, EMPTY_ARRAY)
407
+ own_um + inherited_um
408
+ else
409
+ joined_um = own_union_memberships.dup
410
+ find_inherited_value(:union_memberhips, EMPTY_HASH).each do |k, v|
411
+ um = joined_um[k] ||= []
412
+ um.concat(v)
413
+ end
414
+ joined_um
415
+ end
416
+ end
417
+
418
+ # @api private
419
+ # @see GraphQL::Dataloader
420
+ def dataloader_class
421
+ @dataloader_class || GraphQL::Dataloader::NullDataloader
422
+ end
423
+
424
+ attr_writer :dataloader_class
425
+
426
+ def references_to(to_type = nil, from: nil)
427
+ @own_references_to ||= Hash.new { |h, k| h[k] = [] }
428
+ if to_type
429
+ if !to_type.is_a?(String)
430
+ to_type = to_type.graphql_name
431
+ end
432
+
433
+ if from
434
+ @own_references_to[to_type] << from
435
+ else
436
+ own_refs = @own_references_to[to_type]
437
+ inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
438
+ own_refs + inherited_refs
439
+ end
440
+ else
441
+ # `@own_references_to` can be quite large for big schemas,
442
+ # and generally speaking, we won't inherit any values.
443
+ # So optimize the most common case -- don't create a duplicate Hash.
444
+ inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
445
+ if inherited_value.any?
446
+ inherited_value.merge(@own_references_to)
447
+ else
448
+ @own_references_to
449
+ end
450
+ end
451
+ end
452
+
453
+ def type_from_ast(ast_node, context: nil)
454
+ type_owner = context ? context.warden : self
455
+ GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
456
+ end
457
+
458
+ def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
459
+ parent_type = case type_or_name
460
+ when LateBoundType
461
+ get_type(type_or_name.name, context)
462
+ when String
463
+ get_type(type_or_name, context)
464
+ when Module
465
+ type_or_name
466
+ else
467
+ raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
468
+ end
469
+
470
+ if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
471
+ field
472
+ elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
473
+ entry_point_field
474
+ elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
475
+ dynamic_field
476
+ else
477
+ nil
478
+ end
479
+ end
480
+
481
+ def get_fields(type, context = GraphQL::Query::NullContext)
482
+ type.fields(context)
483
+ end
484
+
485
+ def introspection(new_introspection_namespace = nil)
486
+ if new_introspection_namespace
487
+ @introspection = new_introspection_namespace
488
+ # reset this cached value:
489
+ @introspection_system = nil
490
+ else
491
+ @introspection || find_inherited_value(:introspection)
492
+ end
493
+ end
494
+
495
+ def introspection_system
496
+ if !@introspection_system
497
+ @introspection_system = Schema::IntrospectionSystem.new(self)
498
+ @introspection_system.resolve_late_bindings
499
+ end
500
+ @introspection_system
501
+ end
502
+
503
+ def cursor_encoder(new_encoder = nil)
504
+ if new_encoder
505
+ @cursor_encoder = new_encoder
506
+ end
507
+ @cursor_encoder || find_inherited_value(:cursor_encoder, Base64Encoder)
508
+ end
509
+
510
+ def default_max_page_size(new_default_max_page_size = nil)
511
+ if new_default_max_page_size
512
+ @default_max_page_size = new_default_max_page_size
513
+ else
514
+ @default_max_page_size || find_inherited_value(:default_max_page_size)
515
+ end
516
+ end
517
+
518
+ def default_page_size(new_default_page_size = nil)
519
+ if new_default_page_size
520
+ @default_page_size = new_default_page_size
521
+ else
522
+ @default_page_size || find_inherited_value(:default_page_size)
523
+ end
524
+ end
525
+
526
+ def query_execution_strategy(new_query_execution_strategy = nil)
527
+ if new_query_execution_strategy
528
+ @query_execution_strategy = new_query_execution_strategy
529
+ else
530
+ @query_execution_strategy || find_inherited_value(:query_execution_strategy, self.default_execution_strategy)
531
+ end
532
+ end
533
+
534
+ def mutation_execution_strategy(new_mutation_execution_strategy = nil)
535
+ if new_mutation_execution_strategy
536
+ @mutation_execution_strategy = new_mutation_execution_strategy
537
+ else
538
+ @mutation_execution_strategy || find_inherited_value(:mutation_execution_strategy, self.default_execution_strategy)
539
+ end
540
+ end
541
+
542
+ def subscription_execution_strategy(new_subscription_execution_strategy = nil)
543
+ if new_subscription_execution_strategy
544
+ @subscription_execution_strategy = new_subscription_execution_strategy
545
+ else
546
+ @subscription_execution_strategy || find_inherited_value(:subscription_execution_strategy, self.default_execution_strategy)
547
+ end
548
+ end
549
+
550
+ attr_writer :validate_timeout
551
+
552
+ def validate_timeout(new_validate_timeout = nil)
553
+ if new_validate_timeout
554
+ @validate_timeout = new_validate_timeout
555
+ elsif defined?(@validate_timeout)
556
+ @validate_timeout
557
+ else
558
+ find_inherited_value(:validate_timeout)
559
+ end
560
+ end
561
+
562
+ # Validate a query string according to this schema.
563
+ # @param string_or_document [String, GraphQL::Language::Nodes::Document]
564
+ # @return [Array<GraphQL::StaticValidation::Error >]
565
+ def validate(string_or_document, rules: nil, context: nil)
566
+ doc = if string_or_document.is_a?(String)
567
+ GraphQL.parse(string_or_document)
568
+ else
569
+ string_or_document
570
+ end
571
+ query = GraphQL::Query.new(self, document: doc, context: context)
572
+ validator_opts = { schema: self }
573
+ rules && (validator_opts[:rules] = rules)
574
+ validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
575
+ res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
576
+ res[:errors]
577
+ end
578
+
579
+ attr_writer :validate_max_errors
580
+
581
+ def validate_max_errors(new_validate_max_errors = nil)
582
+ if new_validate_max_errors
583
+ @validate_max_errors = new_validate_max_errors
584
+ elsif defined?(@validate_max_errors)
585
+ @validate_max_errors
586
+ else
587
+ find_inherited_value(:validate_max_errors)
588
+ end
589
+ end
590
+
591
+ attr_writer :max_complexity
592
+
593
+ def max_complexity(max_complexity = nil)
594
+ if max_complexity
595
+ @max_complexity = max_complexity
596
+ elsif defined?(@max_complexity)
597
+ @max_complexity
598
+ else
599
+ find_inherited_value(:max_complexity)
600
+ end
601
+ end
602
+
603
+ attr_writer :analysis_engine
604
+
605
+ def analysis_engine
606
+ @analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
607
+ end
608
+
609
+ def using_ast_analysis?
610
+ true
611
+ end
612
+
613
+ def interpreter?
614
+ true
615
+ end
616
+
617
+ attr_writer :interpreter
618
+
619
+ def error_bubbling(new_error_bubbling = nil)
620
+ if !new_error_bubbling.nil?
621
+ @error_bubbling = new_error_bubbling
622
+ else
623
+ @error_bubbling.nil? ? find_inherited_value(:error_bubbling) : @error_bubbling
624
+ end
625
+ end
626
+
627
+ attr_writer :error_bubbling
628
+
629
+ attr_writer :max_depth
630
+
631
+ def max_depth(new_max_depth = nil)
632
+ if new_max_depth
633
+ @max_depth = new_max_depth
634
+ elsif defined?(@max_depth)
635
+ @max_depth
636
+ else
637
+ find_inherited_value(:max_depth)
638
+ end
639
+ end
640
+
641
+ def disable_introspection_entry_points
642
+ @disable_introspection_entry_points = true
643
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
644
+ @introspection_system = nil
645
+ end
646
+
647
+ def disable_schema_introspection_entry_point
648
+ @disable_schema_introspection_entry_point = true
649
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
650
+ @introspection_system = nil
651
+ end
652
+
653
+ def disable_type_introspection_entry_point
654
+ @disable_type_introspection_entry_point = true
655
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
656
+ @introspection_system = nil
657
+ end
658
+
659
+ def disable_introspection_entry_points?
660
+ if instance_variable_defined?(:@disable_introspection_entry_points)
661
+ @disable_introspection_entry_points
662
+ else
663
+ find_inherited_value(:disable_introspection_entry_points?, false)
664
+ end
665
+ end
666
+
667
+ def disable_schema_introspection_entry_point?
668
+ if instance_variable_defined?(:@disable_schema_introspection_entry_point)
669
+ @disable_schema_introspection_entry_point
670
+ else
671
+ find_inherited_value(:disable_schema_introspection_entry_point?, false)
672
+ end
673
+ end
674
+
675
+ def disable_type_introspection_entry_point?
676
+ if instance_variable_defined?(:@disable_type_introspection_entry_point)
677
+ @disable_type_introspection_entry_point
678
+ else
679
+ find_inherited_value(:disable_type_introspection_entry_point?, false)
680
+ end
681
+ end
682
+
683
+ def orphan_types(*new_orphan_types)
684
+ if new_orphan_types.any?
685
+ new_orphan_types = new_orphan_types.flatten
686
+ add_type_and_traverse(new_orphan_types, root: false)
687
+ own_orphan_types.concat(new_orphan_types.flatten)
688
+ end
689
+
690
+ find_inherited_value(:orphan_types, EMPTY_ARRAY) + own_orphan_types
691
+ end
692
+
693
+ def default_execution_strategy
694
+ if superclass <= GraphQL::Schema
695
+ superclass.default_execution_strategy
696
+ else
697
+ @default_execution_strategy ||= GraphQL::Execution::Interpreter
698
+ end
699
+ end
700
+
701
+ def default_analysis_engine
702
+ if superclass <= GraphQL::Schema
703
+ superclass.default_analysis_engine
704
+ else
705
+ @default_analysis_engine ||= GraphQL::Analysis::AST
706
+ end
707
+ end
708
+
709
+ def context_class(new_context_class = nil)
710
+ if new_context_class
711
+ @context_class = new_context_class
712
+ else
713
+ @context_class || find_inherited_value(:context_class, GraphQL::Query::Context)
714
+ end
715
+ end
716
+
717
+ def rescue_from(*err_classes, &handler_block)
718
+ err_classes.each do |err_class|
719
+ Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
720
+ end
721
+ end
722
+
723
+ NEW_HANDLER_HASH = ->(h, k) {
724
+ h[k] = {
725
+ class: k,
726
+ handler: nil,
727
+ subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
728
+ }
729
+ }
730
+
731
+ def error_handlers
732
+ @error_handlers ||= {
733
+ class: nil,
734
+ handler: nil,
735
+ subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
736
+ }
737
+ end
738
+
739
+ # @api private
740
+ def handle_or_reraise(context, err)
741
+ handler = Execution::Errors.find_handler_for(self, err.class)
742
+ if handler
743
+ obj = context[:current_object]
744
+ args = context[:current_arguments]
745
+ args = args && args.keyword_arguments
746
+ field = context[:current_field]
747
+ if obj.is_a?(GraphQL::Schema::Object)
748
+ obj = obj.object
749
+ end
750
+ handler[:handler].call(err, obj, args, context, field)
751
+ else
752
+ raise err
753
+ end
754
+ end
755
+
756
+ # rubocop:disable Lint/DuplicateMethods
757
+ module ResolveTypeWithType
758
+ def resolve_type(type, obj, ctx)
759
+ maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
760
+ type.resolve_type(obj, ctx)
761
+ else
762
+ super
763
+ end
764
+
765
+ after_lazy(maybe_lazy_resolve_type_result) do |resolve_type_result|
766
+ if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
767
+ resolved_type = resolve_type_result[0]
768
+ resolved_value = resolve_type_result[1]
769
+ else
770
+ resolved_type = resolve_type_result
771
+ resolved_value = obj
772
+ end
773
+
774
+ if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
775
+ if resolved_value
776
+ [resolved_type, resolved_value]
777
+ else
778
+ resolved_type
779
+ end
780
+ else
781
+ raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
782
+ end
783
+ end
784
+ end
785
+ end
786
+
787
+ def resolve_type(type, obj, ctx)
788
+ if type.kind.object?
789
+ type
790
+ else
791
+ 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})"
792
+ end
793
+ end
794
+ # rubocop:enable Lint/DuplicateMethods
795
+
796
+ def inherited(child_class)
797
+ if self == GraphQL::Schema
798
+ child_class.directives(default_directives.values)
799
+ end
800
+ child_class.singleton_class.prepend(ResolveTypeWithType)
801
+ super
802
+ end
803
+
804
+ def object_from_id(node_id, ctx)
805
+ 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}`)"
806
+ end
807
+
808
+ def id_from_object(object, type, ctx)
809
+ 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}`)"
810
+ end
811
+
812
+ def visible?(member, ctx)
813
+ member.visible?(ctx)
814
+ end
815
+
816
+ def accessible?(member, ctx)
817
+ member.accessible?(ctx)
818
+ end
819
+
820
+ def schema_directive(dir_class, **options)
821
+ @own_schema_directives ||= []
822
+ Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
823
+ end
824
+
825
+ def schema_directives
826
+ Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
827
+ end
828
+
829
+ # This hook is called when a client tries to access one or more
830
+ # fields that fail the `accessible?` check.
831
+ #
832
+ # By default, an error is added to the response. Override this hook to
833
+ # track metrics or return a different error to the client.
834
+ #
835
+ # @param error [InaccessibleFieldsError] The analysis error for this check
836
+ # @return [AnalysisError, nil] Return an error to skip the query
837
+ def inaccessible_fields(error)
838
+ error
839
+ end
840
+
841
+ # This hook is called when an object fails an `authorized?` check.
842
+ # You might report to your bug tracker here, so you can correct
843
+ # the field resolvers not to return unauthorized objects.
844
+ #
845
+ # By default, this hook just replaces the unauthorized object with `nil`.
846
+ #
847
+ # Whatever value is returned from this method will be used instead of the
848
+ # unauthorized object (accessible as `unauthorized_error.object`). If an
849
+ # error is raised, then `nil` will be used.
850
+ #
851
+ # If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
852
+ # in this hook.
853
+ #
854
+ # @param unauthorized_error [GraphQL::UnauthorizedError]
855
+ # @return [Object] The returned object will be put in the GraphQL response
856
+ def unauthorized_object(unauthorized_error)
86
857
  nil
87
858
  end
88
- end
89
859
 
90
- def type_from_ast(ast_node)
91
- GraphQL::Schema::TypeExpression.build_type(self, ast_node)
92
- end
860
+ # This hook is called when a field fails an `authorized?` check.
861
+ #
862
+ # By default, this hook implements the same behavior as unauthorized_object.
863
+ #
864
+ # Whatever value is returned from this method will be used instead of the
865
+ # unauthorized field . If an error is raised, then `nil` will be used.
866
+ #
867
+ # If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
868
+ # in this hook.
869
+ #
870
+ # @param unauthorized_error [GraphQL::UnauthorizedFieldError]
871
+ # @return [Field] The returned field will be put in the GraphQL response
872
+ def unauthorized_field(unauthorized_error)
873
+ unauthorized_object(unauthorized_error)
874
+ end
93
875
 
94
- # @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
95
- # @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
96
- def possible_types(type_defn)
97
- @interface_possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
98
- @interface_possible_types.possible_types(type_defn)
99
- end
876
+ def type_error(type_error, ctx)
877
+ case type_error
878
+ when GraphQL::InvalidNullError
879
+ ctx.errors << type_error
880
+ when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
881
+ raise type_error
882
+ when GraphQL::IntegerDecodingError
883
+ nil
884
+ end
885
+ end
100
886
 
101
- def root_type_for_operation(operation)
102
- case operation
103
- when "query"
104
- query
105
- when "mutation"
106
- mutation
107
- when "subscription"
108
- subscription
109
- else
110
- raise ArgumentError, "unknown operation type: #{operation}"
887
+ # A function to call when {#execute} receives an invalid query string
888
+ #
889
+ # The default is to add the error to `context.errors`
890
+ # @param err [GraphQL::ParseError] The error encountered during parsing
891
+ # @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
892
+ # @return void
893
+ def parse_error(parse_err, ctx)
894
+ ctx.errors.push(parse_err)
895
+ end
896
+
897
+ def lazy_resolve(lazy_class, value_method)
898
+ lazy_methods.set(lazy_class, value_method)
899
+ end
900
+
901
+ def instrument(instrument_step, instrumenter, options = {})
902
+ own_instrumenters[instrument_step] << instrumenter
903
+ end
904
+
905
+ # Add several directives at once
906
+ # @param new_directives [Class]
907
+ def directives(*new_directives)
908
+ if new_directives.any?
909
+ new_directives.flatten.each { |d| directive(d) }
910
+ end
911
+
912
+ find_inherited_value(:directives, default_directives).merge(own_directives)
913
+ end
914
+
915
+ # Attach a single directive to this schema
916
+ # @param new_directive [Class]
917
+ # @return void
918
+ def directive(new_directive)
919
+ add_type_and_traverse(new_directive, root: false)
920
+ end
921
+
922
+ def default_directives
923
+ @default_directives ||= {
924
+ "include" => GraphQL::Schema::Directive::Include,
925
+ "skip" => GraphQL::Schema::Directive::Skip,
926
+ "deprecated" => GraphQL::Schema::Directive::Deprecated,
927
+ "oneOf" => GraphQL::Schema::Directive::OneOf,
928
+ }.freeze
929
+ end
930
+
931
+ def tracer(new_tracer)
932
+ own_tracers << new_tracer
933
+ end
934
+
935
+ def tracers
936
+ find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
937
+ end
938
+
939
+ def query_analyzer(new_analyzer)
940
+ own_query_analyzers << new_analyzer
941
+ end
942
+
943
+ def query_analyzers
944
+ find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
945
+ end
946
+
947
+ def multiplex_analyzer(new_analyzer)
948
+ own_multiplex_analyzers << new_analyzer
949
+ end
950
+
951
+ def multiplex_analyzers
952
+ find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
953
+ end
954
+
955
+ def sanitized_printer(new_sanitized_printer = nil)
956
+ if new_sanitized_printer
957
+ @own_sanitized_printer = new_sanitized_printer
958
+ else
959
+ @own_sanitized_printer || GraphQL::Language::SanitizedPrinter
960
+ end
961
+ end
962
+
963
+ # Execute a query on itself.
964
+ # @see {Query#initialize} for arguments.
965
+ # @return [Hash] query result, ready to be serialized as JSON
966
+ def execute(query_str = nil, **kwargs)
967
+ if query_str
968
+ kwargs[:query] = query_str
969
+ end
970
+ # Some of the query context _should_ be passed to the multiplex, too
971
+ multiplex_context = if (ctx = kwargs[:context])
972
+ {
973
+ backtrace: ctx[:backtrace],
974
+ tracers: ctx[:tracers],
975
+ dataloader: ctx[:dataloader],
976
+ }
977
+ else
978
+ {}
979
+ end
980
+ # Since we're running one query, don't run a multiplex-level complexity analyzer
981
+ all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
982
+ all_results[0]
983
+ end
984
+
985
+ # Execute several queries on itself, concurrently.
986
+ #
987
+ # @example Run several queries at once
988
+ # context = { ... }
989
+ # queries = [
990
+ # { query: params[:query_1], variables: params[:variables_1], context: context },
991
+ # { query: params[:query_2], variables: params[:variables_2], context: context },
992
+ # ]
993
+ # results = MySchema.multiplex(queries)
994
+ # render json: {
995
+ # result_1: results[0],
996
+ # result_2: results[1],
997
+ # }
998
+ #
999
+ # @see {Query#initialize} for query keyword arguments
1000
+ # @see {Execution::Multiplex#run_all} for multiplex keyword arguments
1001
+ # @param queries [Array<Hash>] Keyword arguments for each query
1002
+ # @param context [Hash] Multiplex-level context
1003
+ # @return [Array<Hash>] One result for each query in the input
1004
+ def multiplex(queries, **kwargs)
1005
+ GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
1006
+ end
1007
+
1008
+ def instrumenters
1009
+ inherited_instrumenters = find_inherited_value(:instrumenters) || Hash.new { |h,k| h[k] = [] }
1010
+ inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
1011
+ inherited + own
1012
+ end
1013
+ end
1014
+
1015
+ # @api private
1016
+ def add_subscription_extension_if_necessary
1017
+ if !defined?(@subscription_extension_added) && subscription && self.subscriptions
1018
+ @subscription_extension_added = true
1019
+ subscription.all_field_definitions.each do |field|
1020
+ if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
1021
+ field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1022
+ end
1023
+ end
1024
+ end
1025
+ end
1026
+
1027
+ def query_stack_error(query, err)
1028
+ query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
1029
+ end
1030
+
1031
+ # Call the given block at the right time, either:
1032
+ # - Right away, if `value` is not registered with `lazy_resolve`
1033
+ # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
1034
+ # @api private
1035
+ def after_lazy(value, &block)
1036
+ if lazy?(value)
1037
+ GraphQL::Execution::Lazy.new do
1038
+ result = sync_lazy(value)
1039
+ # The returned result might also be lazy, so check it, too
1040
+ after_lazy(result, &block)
1041
+ end
1042
+ else
1043
+ yield(value) if block_given?
1044
+ end
1045
+ end
1046
+
1047
+ # Override this method to handle lazy objects in a custom way.
1048
+ # @param value [Object] an instance of a class registered with {.lazy_resolve}
1049
+ # @return [Object] A GraphQL-ready (non-lazy) object
1050
+ # @api private
1051
+ def sync_lazy(value)
1052
+ lazy_method = lazy_method_name(value)
1053
+ if lazy_method
1054
+ synced_value = value.public_send(lazy_method)
1055
+ sync_lazy(synced_value)
1056
+ else
1057
+ value
1058
+ end
1059
+ end
1060
+
1061
+ # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
1062
+ def lazy_method_name(obj)
1063
+ lazy_methods.get(obj)
1064
+ end
1065
+
1066
+ # @return [Boolean] True if this object should be lazily resolved
1067
+ def lazy?(obj)
1068
+ !!lazy_method_name(obj)
1069
+ end
1070
+
1071
+ # Return a lazy if any of `maybe_lazies` are lazy,
1072
+ # otherwise, call the block eagerly and return the result.
1073
+ # @param maybe_lazies [Array]
1074
+ # @api private
1075
+ def after_any_lazies(maybe_lazies)
1076
+ if maybe_lazies.any? { |l| lazy?(l) }
1077
+ GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
1078
+ yield result
1079
+ end
1080
+ else
1081
+ yield maybe_lazies
1082
+ end
111
1083
  end
112
- end
113
1084
 
114
- def execution_strategy_for_operation(operation)
115
- case operation
116
- when "query"
117
- query_execution_strategy
118
- when "mutation"
119
- mutation_execution_strategy
120
- when "subscription"
121
- subscription_execution_strategy
122
- else
123
- raise ArgumentError, "unknown operation type: #{operation}"
1085
+ private
1086
+
1087
+ # @param t [Module, Array<Module>]
1088
+ # @return [void]
1089
+ def add_type_and_traverse(t, root:)
1090
+ if root
1091
+ @root_types ||= []
1092
+ @root_types << t
1093
+ end
1094
+ new_types = Array(t)
1095
+ addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
1096
+ addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
1097
+ if (prev_entry = own_types[name])
1098
+ prev_entries = case prev_entry
1099
+ when Array
1100
+ prev_entry
1101
+ when Module
1102
+ own_types[name] = [prev_entry]
1103
+ else
1104
+ raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
1105
+ end
1106
+
1107
+ case types_entry
1108
+ when Array
1109
+ prev_entries.concat(types_entry)
1110
+ prev_entries.uniq! # in case any are being re-visited
1111
+ when Module
1112
+ if !prev_entries.include?(types_entry)
1113
+ prev_entries << types_entry
1114
+ end
1115
+ else
1116
+ raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
1117
+ end
1118
+ else
1119
+ if types_entry.is_a?(Array)
1120
+ types_entry.uniq!
1121
+ end
1122
+ own_types[name] = types_entry
1123
+ end
1124
+ end
1125
+
1126
+ own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
1127
+ own_union_memberships.merge!(addition.union_memberships)
1128
+
1129
+ addition.references.each { |thing, pointers|
1130
+ pointers.each { |pointer| references_to(thing, from: pointer) }
1131
+ }
1132
+
1133
+ addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
1134
+
1135
+ addition.arguments_with_default_values.each do |arg|
1136
+ arg.validate_default_value
1137
+ end
1138
+ end
1139
+
1140
+ def lazy_methods
1141
+ if !defined?(@lazy_methods)
1142
+ if inherited_map = find_inherited_value(:lazy_methods)
1143
+ # this isn't _completely_ inherited :S (Things added after `dup` won't work)
1144
+ @lazy_methods = inherited_map.dup
1145
+ else
1146
+ @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
1147
+ @lazy_methods.set(GraphQL::Execution::Lazy, :value)
1148
+ @lazy_methods.set(GraphQL::Dataloader::Request, :load)
1149
+ end
1150
+ end
1151
+ @lazy_methods
1152
+ end
1153
+
1154
+ def own_types
1155
+ @own_types ||= {}
1156
+ end
1157
+
1158
+ def non_introspection_types
1159
+ find_inherited_value(:non_introspection_types, EMPTY_HASH).merge(own_types)
1160
+ end
1161
+
1162
+ def own_plugins
1163
+ @own_plugins ||= []
1164
+ end
1165
+
1166
+ def own_orphan_types
1167
+ @own_orphan_types ||= []
1168
+ end
1169
+
1170
+ def own_possible_types
1171
+ @own_possible_types ||= {}
1172
+ end
1173
+
1174
+ def own_union_memberships
1175
+ @own_union_memberships ||= {}
1176
+ end
1177
+
1178
+ def own_directives
1179
+ @own_directives ||= {}
1180
+ end
1181
+
1182
+ def own_instrumenters
1183
+ @own_instrumenters ||= Hash.new { |h,k| h[k] = [] }
1184
+ end
1185
+
1186
+ def own_tracers
1187
+ @own_tracers ||= []
1188
+ end
1189
+
1190
+ def own_query_analyzers
1191
+ @defined_query_analyzers ||= []
1192
+ end
1193
+
1194
+ def own_multiplex_analyzers
1195
+ @own_multiplex_analyzers ||= []
124
1196
  end
125
1197
  end
1198
+
1199
+ # Install these here so that subclasses will also install it.
1200
+ self.connections = GraphQL::Pagination::Connections.new(schema: self)
126
1201
  end
127
1202
  end