graphql 0.16.0 → 2.0.15

Sign up to get free protection for your applications and to get access to all the features.
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