graphql 1.9.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (723) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/core.rb +21 -9
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install/templates/base_mutation.erb +12 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +4 -0
  9. data/lib/generators/graphql/install_generator.rb +49 -9
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +66 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +8 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +10 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +10 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +4 -0
  25. data/lib/generators/graphql/templates/base_field.erb +9 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +5 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +6 -0
  28. data/lib/generators/graphql/templates/base_object.erb +5 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  30. data/lib/generators/graphql/templates/base_union.erb +4 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +23 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +4 -0
  36. data/lib/generators/graphql/templates/mutation.erb +5 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +11 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +5 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +27 -27
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/ast/analyzer.rb +41 -12
  49. data/lib/graphql/analysis/ast/field_usage.rb +32 -3
  50. data/lib/graphql/analysis/ast/max_query_complexity.rb +4 -5
  51. data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
  52. data/lib/graphql/analysis/ast/query_complexity.rb +182 -66
  53. data/lib/graphql/analysis/ast/query_depth.rb +15 -26
  54. data/lib/graphql/analysis/ast/visitor.rb +83 -62
  55. data/lib/graphql/analysis/ast.rb +23 -20
  56. data/lib/graphql/analysis.rb +0 -7
  57. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  58. data/lib/graphql/backtrace/table.rb +37 -16
  59. data/lib/graphql/backtrace/trace.rb +96 -0
  60. data/lib/graphql/backtrace/traced_error.rb +0 -1
  61. data/lib/graphql/backtrace/tracer.rb +39 -9
  62. data/lib/graphql/backtrace.rb +22 -18
  63. data/lib/graphql/coercion_error.rb +8 -0
  64. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  65. data/lib/graphql/dataloader/request.rb +19 -0
  66. data/lib/graphql/dataloader/request_all.rb +19 -0
  67. data/lib/graphql/dataloader/source.rb +195 -0
  68. data/lib/graphql/dataloader.rb +320 -0
  69. data/lib/graphql/date_encoding_error.rb +16 -0
  70. data/lib/graphql/deprecation.rb +9 -0
  71. data/lib/graphql/dig.rb +1 -1
  72. data/lib/graphql/execution/directive_checks.rb +2 -2
  73. data/lib/graphql/execution/errors.rb +93 -0
  74. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  75. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  76. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  77. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  78. data/lib/graphql/execution/interpreter/resolve.rb +62 -24
  79. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
  80. data/lib/graphql/execution/interpreter/runtime.rb +695 -392
  81. data/lib/graphql/execution/interpreter.rb +199 -74
  82. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  83. data/lib/graphql/execution/lazy.rb +11 -21
  84. data/lib/graphql/execution/lookahead.rb +110 -150
  85. data/lib/graphql/execution/multiplex.rb +6 -148
  86. data/lib/graphql/execution.rb +12 -4
  87. data/lib/graphql/execution_error.rb +3 -2
  88. data/lib/graphql/integer_decoding_error.rb +17 -0
  89. data/lib/graphql/integer_encoding_error.rb +26 -2
  90. data/lib/graphql/introspection/base_object.rb +2 -5
  91. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  92. data/lib/graphql/introspection/directive_type.rb +12 -6
  93. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  94. data/lib/graphql/introspection/entry_points.rb +6 -18
  95. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  96. data/lib/graphql/introspection/field_type.rb +9 -5
  97. data/lib/graphql/introspection/input_value_type.rb +41 -7
  98. data/lib/graphql/introspection/introspection_query.rb +6 -92
  99. data/lib/graphql/introspection/schema_type.rb +13 -12
  100. data/lib/graphql/introspection/type_type.rb +34 -17
  101. data/lib/graphql/introspection.rb +100 -0
  102. data/lib/graphql/invalid_null_error.rb +18 -0
  103. data/lib/graphql/language/block_string.rb +50 -23
  104. data/lib/graphql/language/cache.rb +37 -0
  105. data/lib/graphql/language/definition_slice.rb +21 -10
  106. data/lib/graphql/language/document_from_schema_definition.rb +153 -87
  107. data/lib/graphql/language/lexer.rb +249 -1450
  108. data/lib/graphql/language/nodes.rb +152 -142
  109. data/lib/graphql/language/parser.rb +1036 -953
  110. data/lib/graphql/language/parser.y +159 -120
  111. data/lib/graphql/language/printer.rb +342 -154
  112. data/lib/graphql/language/sanitized_printer.rb +220 -0
  113. data/lib/graphql/language/static_visitor.rb +167 -0
  114. data/lib/graphql/language/token.rb +2 -2
  115. data/lib/graphql/language/visitor.rb +196 -140
  116. data/lib/graphql/language.rb +4 -1
  117. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  118. data/lib/graphql/name_validator.rb +2 -7
  119. data/lib/graphql/pagination/active_record_relation_connection.rb +77 -0
  120. data/lib/graphql/pagination/array_connection.rb +79 -0
  121. data/lib/graphql/pagination/connection.rb +275 -0
  122. data/lib/graphql/pagination/connections.rb +135 -0
  123. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  124. data/lib/graphql/pagination/relation_connection.rb +228 -0
  125. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  126. data/lib/graphql/pagination.rb +6 -0
  127. data/lib/graphql/parse_error.rb +0 -1
  128. data/lib/graphql/query/context/scoped_context.rb +101 -0
  129. data/lib/graphql/query/context.rb +157 -187
  130. data/lib/graphql/query/fingerprint.rb +26 -0
  131. data/lib/graphql/query/input_validation_result.rb +33 -7
  132. data/lib/graphql/query/null_context.rb +21 -14
  133. data/lib/graphql/query/validation_pipeline.rb +17 -38
  134. data/lib/graphql/query/variable_validation_error.rb +17 -3
  135. data/lib/graphql/query/variables.rb +49 -14
  136. data/lib/graphql/query.rb +142 -61
  137. data/lib/graphql/railtie.rb +6 -102
  138. data/lib/graphql/rake_task/validate.rb +5 -2
  139. data/lib/graphql/rake_task.rb +42 -20
  140. data/lib/graphql/relay/range_add.rb +17 -10
  141. data/lib/graphql/relay.rb +0 -15
  142. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  143. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  144. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  145. data/lib/graphql/rubocop.rb +4 -0
  146. data/lib/graphql/schema/addition.rb +271 -0
  147. data/lib/graphql/schema/always_visible.rb +10 -0
  148. data/lib/graphql/schema/argument.rb +301 -32
  149. data/lib/graphql/schema/base_64_bp.rb +3 -2
  150. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  151. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  152. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  153. data/lib/graphql/schema/build_from_definition.rb +349 -203
  154. data/lib/graphql/schema/built_in_types.rb +5 -5
  155. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  156. data/lib/graphql/schema/directive/feature.rb +2 -2
  157. data/lib/graphql/schema/directive/flagged.rb +57 -0
  158. data/lib/graphql/schema/directive/include.rb +2 -2
  159. data/lib/graphql/schema/directive/one_of.rb +12 -0
  160. data/lib/graphql/schema/directive/skip.rb +2 -2
  161. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  162. data/lib/graphql/schema/directive/transform.rb +14 -2
  163. data/lib/graphql/schema/directive.rb +134 -15
  164. data/lib/graphql/schema/enum.rb +137 -39
  165. data/lib/graphql/schema/enum_value.rb +17 -23
  166. data/lib/graphql/schema/field/connection_extension.rb +36 -20
  167. data/lib/graphql/schema/field/scope_extension.rb +15 -5
  168. data/lib/graphql/schema/field.rb +570 -334
  169. data/lib/graphql/schema/field_extension.rb +88 -4
  170. data/lib/graphql/schema/find_inherited_value.rb +31 -0
  171. data/lib/graphql/schema/finder.rb +16 -14
  172. data/lib/graphql/schema/has_single_input_argument.rb +156 -0
  173. data/lib/graphql/schema/input_object.rb +190 -48
  174. data/lib/graphql/schema/interface.rb +24 -49
  175. data/lib/graphql/schema/introspection_system.rb +109 -36
  176. data/lib/graphql/schema/late_bound_type.rb +9 -2
  177. data/lib/graphql/schema/list.rb +61 -3
  178. data/lib/graphql/schema/loader.rb +146 -97
  179. data/lib/graphql/schema/member/base_dsl_methods.rb +45 -51
  180. data/lib/graphql/schema/member/build_type.rb +34 -17
  181. data/lib/graphql/schema/member/has_arguments.rb +385 -10
  182. data/lib/graphql/schema/member/has_ast_node.rb +32 -0
  183. data/lib/graphql/schema/member/has_deprecation_reason.rb +24 -0
  184. data/lib/graphql/schema/member/has_directives.rb +118 -0
  185. data/lib/graphql/schema/member/has_fields.rb +180 -35
  186. data/lib/graphql/schema/member/has_interfaces.rb +143 -0
  187. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  188. data/lib/graphql/schema/member/has_validators.rb +57 -0
  189. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  190. data/lib/graphql/schema/member/scoped.rb +19 -0
  191. data/lib/graphql/schema/member/type_system_helpers.rb +20 -3
  192. data/lib/graphql/schema/member/validates_input.rb +33 -0
  193. data/lib/graphql/schema/member.rb +11 -6
  194. data/lib/graphql/schema/mutation.rb +4 -9
  195. data/lib/graphql/schema/non_null.rb +34 -4
  196. data/lib/graphql/schema/object.rb +55 -64
  197. data/lib/graphql/schema/printer.rb +26 -40
  198. data/lib/graphql/schema/relay_classic_mutation.rb +13 -80
  199. data/lib/graphql/schema/resolver/has_payload_type.rb +53 -12
  200. data/lib/graphql/schema/resolver.rb +182 -162
  201. data/lib/graphql/schema/scalar.rb +40 -15
  202. data/lib/graphql/schema/subscription.rb +85 -27
  203. data/lib/graphql/schema/timeout.rb +119 -0
  204. data/lib/graphql/schema/type_expression.rb +21 -13
  205. data/lib/graphql/schema/type_membership.rb +51 -0
  206. data/lib/graphql/schema/union.rb +69 -15
  207. data/lib/graphql/schema/unique_within_type.rb +1 -2
  208. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  209. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  210. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  211. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  212. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  213. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  214. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  215. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  216. data/lib/graphql/schema/validator.rb +171 -0
  217. data/lib/graphql/schema/warden.rb +330 -59
  218. data/lib/graphql/schema/wrapper.rb +0 -5
  219. data/lib/graphql/schema.rb +985 -858
  220. data/lib/graphql/static_validation/all_rules.rb +4 -1
  221. data/lib/graphql/static_validation/base_visitor.rb +33 -32
  222. data/lib/graphql/static_validation/definition_dependencies.rb +28 -14
  223. data/lib/graphql/static_validation/error.rb +3 -1
  224. data/lib/graphql/static_validation/literal_validator.rb +71 -28
  225. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
  226. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
  227. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  228. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  229. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
  230. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
  231. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  232. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +15 -7
  233. data/lib/graphql/static_validation/rules/fields_will_merge.rb +107 -57
  234. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  235. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  236. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  237. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  238. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  239. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  240. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  241. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  242. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  243. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +6 -4
  244. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +22 -10
  245. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  246. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  247. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  248. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  249. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  250. data/lib/graphql/static_validation/validation_context.rb +17 -7
  251. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  252. data/lib/graphql/static_validation/validator.rb +32 -20
  253. data/lib/graphql/static_validation.rb +1 -3
  254. data/lib/graphql/string_encoding_error.rb +13 -3
  255. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +134 -24
  256. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  257. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  258. data/lib/graphql/subscriptions/event.rb +90 -27
  259. data/lib/graphql/subscriptions/instrumentation.rb +0 -47
  260. data/lib/graphql/subscriptions/serialize.rb +53 -6
  261. data/lib/graphql/subscriptions.rb +147 -62
  262. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  263. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  264. data/lib/graphql/tracing/appoptics_trace.rb +251 -0
  265. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  266. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  267. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  268. data/lib/graphql/tracing/data_dog_trace.rb +196 -0
  269. data/lib/graphql/tracing/data_dog_tracing.rb +53 -2
  270. data/lib/graphql/tracing/legacy_trace.rb +69 -0
  271. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  272. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  273. data/lib/graphql/tracing/notifications_trace.rb +45 -0
  274. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  275. data/lib/graphql/tracing/platform_trace.rb +118 -0
  276. data/lib/graphql/tracing/platform_tracing.rb +77 -31
  277. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  278. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +5 -2
  279. data/lib/graphql/tracing/prometheus_tracing.rb +11 -3
  280. data/lib/graphql/tracing/scout_trace.rb +72 -0
  281. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  282. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  283. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  284. data/lib/graphql/tracing/trace.rb +75 -0
  285. data/lib/graphql/tracing.rb +24 -67
  286. data/lib/graphql/type_kinds.rb +6 -3
  287. data/lib/graphql/types/big_int.rb +23 -0
  288. data/lib/graphql/types/int.rb +11 -3
  289. data/lib/graphql/types/iso_8601_date.rb +45 -0
  290. data/lib/graphql/types/iso_8601_date_time.rb +36 -8
  291. data/lib/graphql/types/json.rb +25 -0
  292. data/lib/graphql/types/relay/base_connection.rb +18 -90
  293. data/lib/graphql/types/relay/base_edge.rb +2 -36
  294. data/lib/graphql/types/relay/connection_behaviors.rb +193 -0
  295. data/lib/graphql/types/relay/edge_behaviors.rb +82 -0
  296. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  297. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  298. data/lib/graphql/types/relay/node.rb +2 -4
  299. data/lib/graphql/types/relay/node_behaviors.rb +25 -0
  300. data/lib/graphql/types/relay/page_info.rb +2 -14
  301. data/lib/graphql/types/relay/page_info_behaviors.rb +30 -0
  302. data/lib/graphql/types/relay.rb +10 -5
  303. data/lib/graphql/types/string.rb +8 -2
  304. data/lib/graphql/types.rb +3 -0
  305. data/lib/graphql/unauthorized_error.rb +3 -3
  306. data/lib/graphql/unauthorized_field_error.rb +1 -1
  307. data/lib/graphql/unresolved_type_error.rb +2 -2
  308. data/lib/graphql/version.rb +1 -1
  309. data/lib/graphql.rb +68 -54
  310. data/readme.md +4 -7
  311. metadata +150 -822
  312. data/lib/graphql/analysis/analyze_query.rb +0 -91
  313. data/lib/graphql/analysis/field_usage.rb +0 -45
  314. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  315. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  316. data/lib/graphql/analysis/query_complexity.rb +0 -88
  317. data/lib/graphql/analysis/query_depth.rb +0 -56
  318. data/lib/graphql/analysis/reducer_state.rb +0 -48
  319. data/lib/graphql/argument.rb +0 -153
  320. data/lib/graphql/authorization.rb +0 -82
  321. data/lib/graphql/backwards_compatibility.rb +0 -60
  322. data/lib/graphql/base_type.rb +0 -226
  323. data/lib/graphql/boolean_type.rb +0 -2
  324. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  325. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  326. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  327. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  328. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  329. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
  330. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  331. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  332. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  333. data/lib/graphql/compatibility.rb +0 -5
  334. data/lib/graphql/define/assign_argument.rb +0 -12
  335. data/lib/graphql/define/assign_connection.rb +0 -13
  336. data/lib/graphql/define/assign_enum_value.rb +0 -18
  337. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  338. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  339. data/lib/graphql/define/assign_object_field.rb +0 -42
  340. data/lib/graphql/define/defined_object_proxy.rb +0 -50
  341. data/lib/graphql/define/instance_definable.rb +0 -300
  342. data/lib/graphql/define/no_definition_error.rb +0 -7
  343. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  344. data/lib/graphql/define/type_definer.rb +0 -31
  345. data/lib/graphql/define.rb +0 -31
  346. data/lib/graphql/deprecated_dsl.rb +0 -42
  347. data/lib/graphql/directive/deprecated_directive.rb +0 -13
  348. data/lib/graphql/directive/include_directive.rb +0 -2
  349. data/lib/graphql/directive/skip_directive.rb +0 -2
  350. data/lib/graphql/directive.rb +0 -104
  351. data/lib/graphql/enum_type.rb +0 -193
  352. data/lib/graphql/execution/execute.rb +0 -319
  353. data/lib/graphql/execution/flatten.rb +0 -40
  354. data/lib/graphql/execution/instrumentation.rb +0 -92
  355. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  356. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  357. data/lib/graphql/execution/typecast.rb +0 -50
  358. data/lib/graphql/field/resolve.rb +0 -59
  359. data/lib/graphql/field.rb +0 -330
  360. data/lib/graphql/filter.rb +0 -53
  361. data/lib/graphql/float_type.rb +0 -2
  362. data/lib/graphql/function.rb +0 -153
  363. data/lib/graphql/id_type.rb +0 -2
  364. data/lib/graphql/input_object_type.rb +0 -153
  365. data/lib/graphql/int_type.rb +0 -2
  366. data/lib/graphql/interface_type.rb +0 -86
  367. data/lib/graphql/internal_representation/document.rb +0 -27
  368. data/lib/graphql/internal_representation/node.rb +0 -206
  369. data/lib/graphql/internal_representation/print.rb +0 -51
  370. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  371. data/lib/graphql/internal_representation/scope.rb +0 -88
  372. data/lib/graphql/internal_representation/visit.rb +0 -36
  373. data/lib/graphql/internal_representation.rb +0 -7
  374. data/lib/graphql/language/lexer.rl +0 -236
  375. data/lib/graphql/list_type.rb +0 -80
  376. data/lib/graphql/literal_validation_error.rb +0 -6
  377. data/lib/graphql/non_null_type.rb +0 -81
  378. data/lib/graphql/object_type.rb +0 -141
  379. data/lib/graphql/query/arguments.rb +0 -179
  380. data/lib/graphql/query/arguments_cache.rb +0 -25
  381. data/lib/graphql/query/executor.rb +0 -53
  382. data/lib/graphql/query/literal_input.rb +0 -115
  383. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  384. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  385. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  386. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  387. data/lib/graphql/query/serial_execution.rb +0 -39
  388. data/lib/graphql/relay/array_connection.rb +0 -85
  389. data/lib/graphql/relay/base_connection.rb +0 -172
  390. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  391. data/lib/graphql/relay/connection_resolve.rb +0 -43
  392. data/lib/graphql/relay/connection_type.rb +0 -40
  393. data/lib/graphql/relay/edge.rb +0 -27
  394. data/lib/graphql/relay/edge_type.rb +0 -18
  395. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  396. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  397. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  398. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  399. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  400. data/lib/graphql/relay/mutation/result.rb +0 -38
  401. data/lib/graphql/relay/mutation.rb +0 -190
  402. data/lib/graphql/relay/node.rb +0 -36
  403. data/lib/graphql/relay/page_info.rb +0 -7
  404. data/lib/graphql/relay/relation_connection.rb +0 -186
  405. data/lib/graphql/relay/type_extensions.rb +0 -30
  406. data/lib/graphql/scalar_type.rb +0 -135
  407. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  408. data/lib/graphql/schema/default_parse_error.rb +0 -10
  409. data/lib/graphql/schema/default_type_error.rb +0 -15
  410. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  411. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
  412. data/lib/graphql/schema/member/instrumentation.rb +0 -121
  413. data/lib/graphql/schema/middleware_chain.rb +0 -82
  414. data/lib/graphql/schema/possible_types.rb +0 -39
  415. data/lib/graphql/schema/rescue_middleware.rb +0 -55
  416. data/lib/graphql/schema/timeout_middleware.rb +0 -85
  417. data/lib/graphql/schema/traversal.rb +0 -228
  418. data/lib/graphql/schema/validation.rb +0 -286
  419. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  420. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  421. data/lib/graphql/static_validation/type_stack.rb +0 -216
  422. data/lib/graphql/string_type.rb +0 -2
  423. data/lib/graphql/subscriptions/subscription_root.rb +0 -66
  424. data/lib/graphql/tracing/skylight_tracing.rb +0 -61
  425. data/lib/graphql/types/relay/base_field.rb +0 -22
  426. data/lib/graphql/types/relay/base_interface.rb +0 -29
  427. data/lib/graphql/types/relay/base_object.rb +0 -26
  428. data/lib/graphql/types/relay/node_field.rb +0 -43
  429. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  430. data/lib/graphql/union_type.rb +0 -100
  431. data/lib/graphql/upgrader/member.rb +0 -899
  432. data/lib/graphql/upgrader/schema.rb +0 -37
  433. data/spec/dummy/Gemfile +0 -12
  434. data/spec/dummy/Gemfile.lock +0 -157
  435. data/spec/dummy/README.md +0 -24
  436. data/spec/dummy/Rakefile +0 -7
  437. data/spec/dummy/app/assets/config/manifest.js +0 -1
  438. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  439. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  440. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  441. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  442. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  443. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  444. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  445. data/spec/dummy/app/jobs/application_job.rb +0 -3
  446. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  447. data/spec/dummy/app/views/pages/show.html +0 -16
  448. data/spec/dummy/bin/bundle +0 -4
  449. data/spec/dummy/bin/rails +0 -5
  450. data/spec/dummy/bin/rake +0 -5
  451. data/spec/dummy/bin/setup +0 -31
  452. data/spec/dummy/bin/update +0 -27
  453. data/spec/dummy/bin/yarn +0 -12
  454. data/spec/dummy/config/application.rb +0 -30
  455. data/spec/dummy/config/boot.rb +0 -4
  456. data/spec/dummy/config/cable.yml +0 -10
  457. data/spec/dummy/config/environment.rb +0 -6
  458. data/spec/dummy/config/environments/development.rb +0 -40
  459. data/spec/dummy/config/environments/production.rb +0 -76
  460. data/spec/dummy/config/environments/test.rb +0 -37
  461. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  462. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  463. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  464. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  465. data/spec/dummy/config/initializers/inflections.rb +0 -17
  466. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  467. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  468. data/spec/dummy/config/locales/en.yml +0 -33
  469. data/spec/dummy/config/puma.rb +0 -57
  470. data/spec/dummy/config/routes.rb +0 -4
  471. data/spec/dummy/config/secrets.yml +0 -32
  472. data/spec/dummy/config.ru +0 -6
  473. data/spec/dummy/log/test.log +0 -199
  474. data/spec/dummy/package.json +0 -5
  475. data/spec/dummy/public/404.html +0 -67
  476. data/spec/dummy/public/422.html +0 -67
  477. data/spec/dummy/public/500.html +0 -66
  478. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  479. data/spec/dummy/public/apple-touch-icon.png +0 -0
  480. data/spec/dummy/public/favicon.ico +0 -0
  481. data/spec/dummy/public/robots.txt +0 -1
  482. data/spec/dummy/test/application_system_test_case.rb +0 -6
  483. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  484. data/spec/dummy/test/test_helper.rb +0 -4
  485. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  486. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
  487. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
  488. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
  489. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
  490. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  491. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
  492. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
  493. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  494. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  495. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
  496. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  497. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
  498. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
  499. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
  500. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
  501. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  502. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
  503. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  504. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  505. data/spec/fixtures/upgrader/account.original.rb +0 -19
  506. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  507. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  508. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  509. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  510. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  511. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  512. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  513. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  514. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  515. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  516. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  517. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  518. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  519. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  520. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  521. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  522. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  523. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  524. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  525. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  526. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  527. data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
  528. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  529. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  530. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
  531. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  532. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  533. data/spec/graphql/analysis/ast_spec.rb +0 -269
  534. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  535. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  536. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
  537. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  538. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  539. data/spec/graphql/argument_spec.rb +0 -159
  540. data/spec/graphql/authorization_spec.rb +0 -901
  541. data/spec/graphql/backtrace_spec.rb +0 -206
  542. data/spec/graphql/base_type_spec.rb +0 -171
  543. data/spec/graphql/boolean_type_spec.rb +0 -21
  544. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  545. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  546. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  547. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  548. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  549. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  550. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  551. data/spec/graphql/directive_spec.rb +0 -295
  552. data/spec/graphql/enum_type_spec.rb +0 -158
  553. data/spec/graphql/execution/execute_spec.rb +0 -303
  554. data/spec/graphql/execution/instrumentation_spec.rb +0 -184
  555. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  556. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  557. data/spec/graphql/execution/lazy_spec.rb +0 -240
  558. data/spec/graphql/execution/lookahead_spec.rb +0 -363
  559. data/spec/graphql/execution/multiplex_spec.rb +0 -211
  560. data/spec/graphql/execution/typecast_spec.rb +0 -47
  561. data/spec/graphql/execution_error_spec.rb +0 -325
  562. data/spec/graphql/field_spec.rb +0 -246
  563. data/spec/graphql/float_type_spec.rb +0 -16
  564. data/spec/graphql/function_spec.rb +0 -129
  565. data/spec/graphql/id_type_spec.rb +0 -33
  566. data/spec/graphql/input_object_type_spec.rb +0 -25
  567. data/spec/graphql/int_type_spec.rb +0 -35
  568. data/spec/graphql/interface_type_spec.rb +0 -196
  569. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  570. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
  571. data/spec/graphql/introspection/directive_type_spec.rb +0 -61
  572. data/spec/graphql/introspection/input_value_type_spec.rb +0 -105
  573. data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
  574. data/spec/graphql/introspection/schema_type_spec.rb +0 -56
  575. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  576. data/spec/graphql/language/block_string_spec.rb +0 -70
  577. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  578. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  579. data/spec/graphql/language/equality_spec.rb +0 -84
  580. data/spec/graphql/language/generation_spec.rb +0 -38
  581. data/spec/graphql/language/lexer_spec.rb +0 -135
  582. data/spec/graphql/language/nodes_spec.rb +0 -67
  583. data/spec/graphql/language/parser_spec.rb +0 -175
  584. data/spec/graphql/language/printer_spec.rb +0 -215
  585. data/spec/graphql/language/visitor_spec.rb +0 -400
  586. data/spec/graphql/list_type_spec.rb +0 -57
  587. data/spec/graphql/non_null_type_spec.rb +0 -48
  588. data/spec/graphql/object_type_spec.rb +0 -197
  589. data/spec/graphql/query/arguments_spec.rb +0 -346
  590. data/spec/graphql/query/context_spec.rb +0 -292
  591. data/spec/graphql/query/executor_spec.rb +0 -314
  592. data/spec/graphql/query/literal_input_spec.rb +0 -91
  593. data/spec/graphql/query/result_spec.rb +0 -29
  594. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  595. data/spec/graphql/query_spec.rb +0 -800
  596. data/spec/graphql/rake_task_spec.rb +0 -59
  597. data/spec/graphql/scalar_type_spec.rb +0 -66
  598. data/spec/graphql/schema/argument_spec.rb +0 -127
  599. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
  600. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
  601. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  602. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  603. data/spec/graphql/schema/enum_spec.rb +0 -83
  604. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  605. data/spec/graphql/schema/field_extension_spec.rb +0 -115
  606. data/spec/graphql/schema/field_spec.rb +0 -301
  607. data/spec/graphql/schema/finder_spec.rb +0 -135
  608. data/spec/graphql/schema/input_object_spec.rb +0 -238
  609. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  610. data/spec/graphql/schema/interface_spec.rb +0 -215
  611. data/spec/graphql/schema/introspection_system_spec.rb +0 -47
  612. data/spec/graphql/schema/list_spec.rb +0 -46
  613. data/spec/graphql/schema/loader_spec.rb +0 -286
  614. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  615. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  616. data/spec/graphql/schema/member/scoped_spec.rb +0 -177
  617. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  618. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  619. data/spec/graphql/schema/mutation_spec.rb +0 -150
  620. data/spec/graphql/schema/non_null_spec.rb +0 -46
  621. data/spec/graphql/schema/object_spec.rb +0 -244
  622. data/spec/graphql/schema/printer_spec.rb +0 -869
  623. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -234
  624. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -74
  625. data/spec/graphql/schema/resolver_spec.rb +0 -640
  626. data/spec/graphql/schema/scalar_spec.rb +0 -101
  627. data/spec/graphql/schema/subscription_spec.rb +0 -416
  628. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  629. data/spec/graphql/schema/traversal_spec.rb +0 -222
  630. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  631. data/spec/graphql/schema/union_spec.rb +0 -72
  632. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  633. data/spec/graphql/schema/validation_spec.rb +0 -355
  634. data/spec/graphql/schema/warden_spec.rb +0 -926
  635. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
  636. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  637. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  638. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  639. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  640. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  641. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  642. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  643. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  644. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  645. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  646. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  647. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  648. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  649. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  650. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  651. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  652. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  653. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
  654. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -58
  655. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  656. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  657. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  658. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  659. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  660. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  661. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  662. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  663. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  664. data/spec/graphql/string_type_spec.rb +0 -80
  665. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  666. data/spec/graphql/subscriptions_spec.rb +0 -502
  667. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -63
  668. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -137
  669. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  670. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  671. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  672. data/spec/graphql/tracing_spec.rb +0 -52
  673. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  674. data/spec/graphql/union_type_spec.rb +0 -211
  675. data/spec/graphql/upgrader/member_spec.rb +0 -583
  676. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  677. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  678. data/spec/integration/mongoid/spec_helper.rb +0 -2
  679. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  680. data/spec/integration/mongoid/star_trek/schema.rb +0 -425
  681. data/spec/integration/rails/data.rb +0 -110
  682. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  683. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  684. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
  685. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  686. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  687. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  688. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  689. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  690. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  691. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  692. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  693. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
  694. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  695. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  696. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  697. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  698. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  699. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  700. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  701. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  702. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  703. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  704. data/spec/integration/rails/graphql/schema_spec.rb +0 -476
  705. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  706. data/spec/integration/rails/spec_helper.rb +0 -25
  707. data/spec/integration/tmp/app/graphql/types/family_type.rb +0 -9
  708. data/spec/spec_helper.rb +0 -116
  709. data/spec/support/dummy/data.rb +0 -45
  710. data/spec/support/dummy/schema.rb +0 -492
  711. data/spec/support/error_bubbling_helpers.rb +0 -23
  712. data/spec/support/global_id.rb +0 -23
  713. data/spec/support/jazz.rb +0 -759
  714. data/spec/support/lazy_helpers.rb +0 -192
  715. data/spec/support/magic_cards/schema.graphql +0 -33
  716. data/spec/support/minimum_input_object.rb +0 -21
  717. data/spec/support/new_relic.rb +0 -27
  718. data/spec/support/parser/filename_example.graphql +0 -5
  719. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  720. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  721. data/spec/support/skylight.rb +0 -39
  722. data/spec/support/star_wars/schema.rb +0 -465
  723. data/spec/support/static_validation_helpers.rb +0 -32
@@ -1,24 +1,20 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/schema/addition"
3
+ require "graphql/schema/always_visible"
2
4
  require "graphql/schema/base_64_encoder"
3
- require "graphql/schema/catchall_middleware"
4
- require "graphql/schema/default_parse_error"
5
- require "graphql/schema/default_type_error"
5
+ require "graphql/schema/find_inherited_value"
6
6
  require "graphql/schema/finder"
7
7
  require "graphql/schema/invalid_type_error"
8
8
  require "graphql/schema/introspection_system"
9
9
  require "graphql/schema/late_bound_type"
10
- require "graphql/schema/middleware_chain"
11
10
  require "graphql/schema/null_mask"
12
- require "graphql/schema/possible_types"
13
- require "graphql/schema/rescue_middleware"
14
- require "graphql/schema/timeout_middleware"
15
- require "graphql/schema/traversal"
11
+ require "graphql/schema/timeout"
16
12
  require "graphql/schema/type_expression"
17
13
  require "graphql/schema/unique_within_type"
18
- require "graphql/schema/validation"
19
14
  require "graphql/schema/warden"
20
15
  require "graphql/schema/build_from_definition"
21
16
 
17
+ require "graphql/schema/validator"
22
18
  require "graphql/schema/member"
23
19
  require "graphql/schema/wrapper"
24
20
  require "graphql/schema/list"
@@ -34,13 +30,19 @@ require "graphql/schema/scalar"
34
30
  require "graphql/schema/object"
35
31
  require "graphql/schema/union"
36
32
  require "graphql/schema/directive"
33
+ require "graphql/schema/directive/deprecated"
37
34
  require "graphql/schema/directive/include"
35
+ require "graphql/schema/directive/one_of"
38
36
  require "graphql/schema/directive/skip"
39
37
  require "graphql/schema/directive/feature"
38
+ require "graphql/schema/directive/flagged"
40
39
  require "graphql/schema/directive/transform"
40
+ require "graphql/schema/directive/specified_by"
41
+ require "graphql/schema/type_membership"
41
42
 
42
43
  require "graphql/schema/resolver"
43
44
  require "graphql/schema/mutation"
45
+ require "graphql/schema/has_single_input_argument"
44
46
  require "graphql/schema/relay_classic_mutation"
45
47
  require "graphql/schema/subscription"
46
48
 
@@ -52,7 +54,6 @@ module GraphQL
52
54
  # - types for exposing your application
53
55
  # - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
54
56
  # - execution strategies for running incoming queries
55
- # - middleware for interacting with execution
56
57
  #
57
58
  # Schemas start with root types, {Schema#query}, {Schema#mutation} and {Schema#subscription}.
58
59
  # The schema will traverse the tree of fields & types, using those as starting points.
@@ -65,777 +66,535 @@ module GraphQL
65
66
  # `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
66
67
  # each apply to corresponding root types.
67
68
  #
68
- # A schema accepts a `Relay::GlobalNodeIdentification` instance for use with Relay IDs.
69
- #
70
69
  # @example defining a schema
71
- # MySchema = GraphQL::Schema.define do
70
+ # class MySchema < GraphQL::Schema
72
71
  # query QueryType
73
- # middleware PermissionMiddleware
74
- # rescue_from(ActiveRecord::RecordNotFound) { "Not found" }
75
72
  # # If types are only connected by way of interfaces, they must be added here
76
73
  # orphan_types ImageType, AudioType
77
74
  # end
78
75
  #
79
76
  class Schema
80
- extend Forwardable
81
- extend GraphQL::Schema::Member::AcceptsDefinition
82
- include GraphQL::Define::InstanceDefinable
83
- accepts_definitions \
84
- :query, :mutation, :subscription,
85
- :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
86
- :max_depth, :max_complexity, :default_max_page_size,
87
- :orphan_types, :resolve_type, :type_error, :parse_error,
88
- :error_bubbling,
89
- :raise_definition_error,
90
- :object_from_id, :id_from_object,
91
- :default_mask,
92
- :cursor_encoder,
93
- directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m } },
94
- directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
95
- instrument: ->(schema, type, instrumenter, after_built_ins: false) {
96
- if type == :field && after_built_ins
97
- type = :field_after_built_ins
98
- end
99
- schema.instrumenters[type] << instrumenter
100
- },
101
- query_analyzer: ->(schema, analyzer) {
102
- if analyzer == GraphQL::Authorization::Analyzer
103
- warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
104
- end
105
- schema.query_analyzers << analyzer
106
- },
107
- multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
108
- middleware: ->(schema, middleware) { schema.middleware << middleware },
109
- lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
110
- rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
111
- tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
112
-
113
- attr_accessor \
114
- :query, :mutation, :subscription,
115
- :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
116
- :max_depth, :max_complexity, :default_max_page_size,
117
- :orphan_types, :directives,
118
- :query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
119
- :cursor_encoder,
120
- :ast_node,
121
- :raise_definition_error,
122
- :introspection_namespace,
123
- :analysis_engine
124
-
125
- # [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
126
- attr_accessor :error_bubbling
127
-
128
- # Single, long-lived instance of the provided subscriptions class, if there is one.
129
- # @return [GraphQL::Subscriptions]
130
- attr_accessor :subscriptions
131
-
132
- # @return [MiddlewareChain] MiddlewareChain which is applied to fields during execution
133
- attr_accessor :middleware
134
-
135
- # @return [<#call(member, ctx)>] A callable for filtering members of the schema
136
- # @see {Query.new} for query-specific filters with `except:`
137
- attr_accessor :default_mask
138
-
139
- # @see {GraphQL::Query::Context} The parent class of these classes
140
- # @return [Class] Instantiated for each query
141
- attr_accessor :context_class
142
-
143
- class << self
144
- attr_writer :default_execution_strategy
145
- end
146
-
147
- def default_filter
148
- GraphQL::Filter.new(except: default_mask)
149
- end
77
+ extend GraphQL::Schema::Member::HasAstNode
78
+ extend GraphQL::Schema::FindInheritedValue
150
79
 
151
- # @return [Array<#trace(key, data)>] Tracers applied to every query
152
- # @see {Query#tracers} for query-specific tracers
153
- attr_reader :tracers
154
-
155
- DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
156
-
157
- attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
158
-
159
- def initialize
160
- @tracers = []
161
- @definition_error = nil
162
- @orphan_types = []
163
- @directives = self.class.default_directives
164
- @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
165
- @middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
166
- @query_analyzers = []
167
- @multiplex_analyzers = []
168
- @resolve_type_proc = nil
169
- @object_from_id_proc = nil
170
- @id_from_object_proc = nil
171
- @type_error_proc = DefaultTypeError
172
- @parse_error_proc = DefaultParseError
173
- @instrumenters = Hash.new { |h, k| h[k] = [] }
174
- @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
175
- @lazy_methods.set(GraphQL::Execution::Lazy, :value)
176
- @cursor_encoder = Base64Encoder
177
- # Default to the built-in execution strategy:
178
- @analysis_engine = GraphQL::Analysis
179
- @query_execution_strategy = self.class.default_execution_strategy
180
- @mutation_execution_strategy = self.class.default_execution_strategy
181
- @subscription_execution_strategy = self.class.default_execution_strategy
182
- @default_mask = GraphQL::Schema::NullMask
183
- @rebuilding_artifacts = false
184
- @context_class = GraphQL::Query::Context
185
- @introspection_namespace = nil
186
- @introspection_system = nil
187
- @interpreter = false
188
- @error_bubbling = false
189
- end
190
-
191
- # @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
192
- def interpreter?
193
- @interpreter
80
+ class DuplicateNamesError < GraphQL::Error
81
+ attr_reader :duplicated_name
82
+ def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
83
+ @duplicated_name = duplicated_name
84
+ super(
85
+ "Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
86
+ )
87
+ end
194
88
  end
195
89
 
196
- # @api private
197
- attr_writer :interpreter
198
-
199
- def inspect
200
- "#<#{self.class.name} ...>"
90
+ class UnresolvedLateBoundTypeError < GraphQL::Error
91
+ attr_reader :type
92
+ def initialize(type:)
93
+ @type = type
94
+ super("Late bound type was never found: #{type.inspect}")
95
+ end
201
96
  end
202
97
 
203
- def initialize_copy(other)
204
- super
205
- @orphan_types = other.orphan_types.dup
206
- @directives = other.directives.dup
207
- @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
208
- @middleware = other.middleware.dup
209
- @query_analyzers = other.query_analyzers.dup
210
- @multiplex_analyzers = other.multiplex_analyzers.dup
211
- @tracers = other.tracers.dup
212
- @possible_types = GraphQL::Schema::PossibleTypes.new(self)
213
-
214
- @lazy_methods = other.lazy_methods.dup
98
+ # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
99
+ class InvalidDocumentError < Error; end;
215
100
 
216
- @instrumenters = Hash.new { |h, k| h[k] = [] }
217
- other.instrumenters.each do |key, insts|
218
- @instrumenters[key].concat(insts)
101
+ class << self
102
+ # Create schema with the result of an introspection query.
103
+ # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
104
+ # @return [Class<GraphQL::Schema>] the schema described by `input`
105
+ def from_introspection(introspection_result)
106
+ GraphQL::Schema::Loader.load(introspection_result)
107
+ end
108
+
109
+ # Create schema from an IDL schema or file containing an IDL definition.
110
+ # @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
111
+ # @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
112
+ # @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
113
+ # @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
114
+ # @return [Class] the schema described by `document`
115
+ def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
116
+ # If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
117
+ if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
118
+ GraphQL::Schema::BuildFromDefinition.from_definition_path(
119
+ self,
120
+ definition_or_path,
121
+ default_resolve: default_resolve,
122
+ parser: parser,
123
+ using: using,
124
+ )
125
+ else
126
+ GraphQL::Schema::BuildFromDefinition.from_definition(
127
+ self,
128
+ definition_or_path,
129
+ default_resolve: default_resolve,
130
+ parser: parser,
131
+ using: using,
132
+ )
133
+ end
219
134
  end
220
135
 
221
- if other.rescues?
222
- @rescue_middleware = other.rescue_middleware
136
+ def deprecated_graphql_definition
137
+ graphql_definition(silence_deprecation_warning: true)
223
138
  end
224
139
 
225
- # This will be rebuilt when it's requested
226
- # or during a later `define` call
227
- @types = nil
228
- @introspection_system = nil
229
- end
230
-
231
- def rescue_from(*args, &block)
232
- rescue_middleware.rescue_from(*args, &block)
233
- end
234
-
235
- def remove_handler(*args, &block)
236
- rescue_middleware.remove_handler(*args, &block)
237
- end
238
-
239
- def using_ast_analysis?
240
- @analysis_engine == GraphQL::Analysis::AST
241
- end
242
-
243
- # For forwards-compatibility with Schema classes
244
- alias :graphql_definition :itself
245
-
246
- # Validate a query string according to this schema.
247
- # @param string_or_document [String, GraphQL::Language::Nodes::Document]
248
- # @return [Array<GraphQL::StaticValidation::Error >]
249
- def validate(string_or_document, rules: nil)
250
- doc = if string_or_document.is_a?(String)
251
- GraphQL.parse(string_or_document)
252
- else
253
- string_or_document
254
- end
255
- query = GraphQL::Query.new(self, document: doc)
256
- validator_opts = { schema: self }
257
- rules && (validator_opts[:rules] = rules)
258
- validator = GraphQL::StaticValidation::Validator.new(validator_opts)
259
- res = validator.validate(query)
260
- res[:errors]
261
- end
262
-
263
- def define(**kwargs, &block)
264
- super
265
- ensure_defined
266
- # Assert that all necessary configs are present:
267
- validation_error = Validation.validate(self)
268
- validation_error && raise(NotImplementedError, validation_error)
269
- rebuild_artifacts
270
-
271
- @definition_error = nil
272
- nil
273
- rescue StandardError => err
274
- if @raise_definition_error || err.is_a?(CyclicalDefinitionError)
275
- raise
276
- else
277
- # Raise this error _later_ to avoid messing with Rails constant loading
278
- @definition_error = err
279
- end
280
- nil
281
- end
282
-
283
- # Attach `instrumenter` to this schema for instrumenting events of `instrumentation_type`.
284
- # @param instrumentation_type [Symbol]
285
- # @param instrumenter
286
- # @return [void]
287
- def instrument(instrumentation_type, instrumenter)
288
- @instrumenters[instrumentation_type] << instrumenter
289
- if instrumentation_type == :field
290
- rebuild_artifacts
140
+ # @return [GraphQL::Subscriptions]
141
+ def subscriptions(inherited: true)
142
+ defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
291
143
  end
292
- end
293
144
 
294
- # @return [Array<GraphQL::BaseType>] The root types of this schema
295
- def root_types
296
- @root_types ||= begin
297
- rebuild_artifacts
298
- @root_types
145
+ def subscriptions=(new_implementation)
146
+ @subscriptions = new_implementation
299
147
  end
300
- end
301
148
 
302
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
303
- # @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
304
- def types
305
- @types ||= begin
306
- rebuild_artifacts
307
- @types
149
+ def trace_class(new_class = nil)
150
+ if new_class
151
+ trace_mode(:default, new_class)
152
+ backtrace_class = Class.new(new_class)
153
+ backtrace_class.include(GraphQL::Backtrace::Trace)
154
+ trace_mode(:default_backtrace, backtrace_class)
155
+ end
156
+ trace_class_for(:default)
157
+ end
158
+
159
+ # @return [Class] Return the trace class to use for this mode, looking one up on the superclass if this Schema doesn't have one defined.
160
+ def trace_class_for(mode)
161
+ @trace_modes ||= {}
162
+ @trace_modes[mode] ||= begin
163
+ case mode
164
+ when :default
165
+ superclass_base_class = if superclass.respond_to?(:trace_class_for)
166
+ superclass.trace_class_for(mode)
167
+ else
168
+ GraphQL::Tracing::Trace
169
+ end
170
+ Class.new(superclass_base_class)
171
+ when :default_backtrace
172
+ schema_base_class = trace_class_for(:default)
173
+ Class.new(schema_base_class) do
174
+ include(GraphQL::Backtrace::Trace)
175
+ end
176
+ else
177
+ mods = trace_modules_for(mode)
178
+ Class.new(trace_class_for(:default)) do
179
+ mods.any? && include(*mods)
180
+ end
181
+ end
182
+ end
308
183
  end
309
- end
310
184
 
311
- # @api private
312
- def introspection_system
313
- @introspection_system ||= begin
314
- rebuild_artifacts
315
- @introspection_system
185
+ # Configure `trace_class` to be used whenever `context: { trace_mode: mode_name }` is requested.
186
+ # `:default` is used when no `trace_mode: ...` is requested.
187
+ # @param mode_name [Symbol]
188
+ # @param trace_class [Class] subclass of GraphQL::Tracing::Trace
189
+ # @return void
190
+ def trace_mode(mode_name, trace_class)
191
+ @trace_modes ||= {}
192
+ @trace_modes[mode_name] = trace_class
193
+ nil
316
194
  end
317
- end
318
-
319
- # Returns a list of Arguments and Fields referencing a certain type
320
- # @param type_name [String]
321
- # @return [Hash]
322
- def references_to(type_name)
323
- rebuild_artifacts unless defined?(@type_reference_map)
324
- @type_reference_map.fetch(type_name, [])
325
- end
326
195
 
327
- # Returns a list of Union types in which a type is a member
328
- # @param type [GraphQL::ObjectType]
329
- # @return [Array<GraphQL::UnionType>] list of union types of which the type is a member
330
- def union_memberships(type)
331
- rebuild_artifacts unless defined?(@union_memberships)
332
- @union_memberships.fetch(type.name, [])
333
- end
334
-
335
- # Execute a query on itself. Raises an error if the schema definition is invalid.
336
- # @see {Query#initialize} for arguments.
337
- # @return [Hash] query result, ready to be serialized as JSON
338
- def execute(query_str = nil, **kwargs)
339
- if query_str
340
- kwargs[:query] = query_str
341
- end
342
- # Some of the query context _should_ be passed to the multiplex, too
343
- multiplex_context = if (ctx = kwargs[:context])
344
- {
345
- backtrace: ctx[:backtrace],
346
- tracers: ctx[:tracers],
347
- }
348
- else
349
- {}
196
+ def own_trace_modules
197
+ @own_trace_modules ||= Hash.new { |h, k| h[k] = [] }
350
198
  end
351
- # Since we're running one query, don't run a multiplex-level complexity analyzer
352
- all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
353
- all_results[0]
354
- end
355
-
356
- # Execute several queries on itself. Raises an error if the schema definition is invalid.
357
- # @example Run several queries at once
358
- # context = { ... }
359
- # queries = [
360
- # { query: params[:query_1], variables: params[:variables_1], context: context },
361
- # { query: params[:query_2], variables: params[:variables_2], context: context },
362
- # ]
363
- # results = MySchema.multiplex(queries)
364
- # render json: {
365
- # result_1: results[0],
366
- # result_2: results[1],
367
- # }
368
- #
369
- # @see {Query#initialize} for query keyword arguments
370
- # @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
371
- # @param queries [Array<Hash>] Keyword arguments for each query
372
- # @param context [Hash] Multiplex-level context
373
- # @return [Array<Hash>] One result for each query in the input
374
- def multiplex(queries, **kwargs)
375
- with_definition_error_check {
376
- GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
377
- }
378
- end
379
-
380
- # Search for a schema member using a string path
381
- # @example Finding a Field
382
- # Schema.find("Ensemble.musicians")
383
- #
384
- # @see {GraphQL::Schema::Finder} for more examples
385
- # @param path [String] A dot-separated path to the member
386
- # @raise [Schema::Finder::MemberNotFoundError] if path could not be found
387
- # @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
388
- def find(path)
389
- rebuild_artifacts unless defined?(@finder)
390
- @find_cache[path] ||= @finder.find(path)
391
- end
392
199
 
393
- # Resolve field named `field_name` for type `parent_type`.
394
- # Handles dynamic fields `__typename`, `__type` and `__schema`, too
395
- # @param parent_type [String, GraphQL::BaseType]
396
- # @param field_name [String]
397
- # @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
398
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
399
- def get_field(parent_type, field_name)
400
- with_definition_error_check do
401
- parent_type_name = case parent_type
402
- when GraphQL::BaseType
403
- parent_type.name
404
- when String
405
- parent_type
406
- else
407
- raise "Unexpected parent_type: #{parent_type}"
200
+ # @return [Array<Module>] Modules added for tracing in `trace_mode`, including inherited ones
201
+ def trace_modules_for(trace_mode)
202
+ modules = own_trace_modules[trace_mode]
203
+ if superclass.respond_to?(:trace_modules_for)
204
+ modules += superclass.trace_modules_for(trace_mode)
408
205
  end
409
-
410
- defined_field = @instrumented_field_map[parent_type_name][field_name]
411
- if defined_field
412
- defined_field
413
- elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
414
- entry_point_field
415
- elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
416
- dynamic_field
206
+ modules
207
+ end
208
+
209
+
210
+ # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
211
+ # @see {#as_json}
212
+ # @return [String]
213
+ def to_json(**args)
214
+ JSON.pretty_generate(as_json(**args))
215
+ end
216
+
217
+ # Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
218
+ # @param context [Hash]
219
+ # @param only [<#call(member, ctx)>]
220
+ # @param except [<#call(member, ctx)>]
221
+ # @param include_deprecated_args [Boolean] If true, deprecated arguments will be included in the JSON response
222
+ # @param include_schema_description [Boolean] If true, the schema's description will be queried and included in the response
223
+ # @param include_is_repeatable [Boolean] If true, `isRepeatable: true|false` will be included with the schema's directives
224
+ # @param include_specified_by_url [Boolean] If true, scalar types' `specifiedByUrl:` will be included in the response
225
+ # @param include_is_one_of [Boolean] If true, `isOneOf: true|false` will be included with input objects
226
+ # @return [Hash] GraphQL result
227
+ def as_json(context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
228
+ introspection_query = Introspection.query(
229
+ include_deprecated_args: include_deprecated_args,
230
+ include_schema_description: include_schema_description,
231
+ include_is_repeatable: include_is_repeatable,
232
+ include_is_one_of: include_is_one_of,
233
+ include_specified_by_url: include_specified_by_url,
234
+ )
235
+
236
+ execute(introspection_query, context: context).to_h
237
+ end
238
+
239
+ # Return the GraphQL IDL for the schema
240
+ # @param context [Hash]
241
+ # @return [String]
242
+ def to_definition(context: {})
243
+ GraphQL::Schema::Printer.print_schema(self, context: context)
244
+ end
245
+
246
+ # Return the GraphQL::Language::Document IDL AST for the schema
247
+ # @return [GraphQL::Language::Document]
248
+ def to_document
249
+ GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
250
+ end
251
+
252
+ # @return [String, nil]
253
+ def description(new_description = nil)
254
+ if new_description
255
+ @description = new_description
256
+ elsif defined?(@description)
257
+ @description
417
258
  else
418
- nil
259
+ find_inherited_value(:description, nil)
419
260
  end
420
261
  end
421
- end
422
-
423
- # Fields for this type, after instrumentation is applied
424
- # @return [Hash<String, GraphQL::Field>]
425
- def get_fields(type)
426
- @instrumented_field_map[type.graphql_name]
427
- end
428
-
429
- def type_from_ast(ast_node)
430
- GraphQL::Schema::TypeExpression.build_type(self.types, ast_node)
431
- end
432
-
433
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
434
- # @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
435
- # @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
436
- def possible_types(type_defn)
437
- @possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
438
- @possible_types.possible_types(type_defn)
439
- end
440
262
 
441
- # @see [GraphQL::Schema::Warden] Resticted access to root types
442
- # @return [GraphQL::ObjectType, nil]
443
- def root_type_for_operation(operation)
444
- case operation
445
- when "query"
446
- query
447
- when "mutation"
448
- mutation
449
- when "subscription"
450
- subscription
451
- else
452
- raise ArgumentError, "unknown operation type: #{operation}"
263
+ def find(path)
264
+ if !@finder
265
+ @find_cache = {}
266
+ @finder ||= GraphQL::Schema::Finder.new(self)
267
+ end
268
+ @find_cache[path] ||= @finder.find(path)
453
269
  end
454
- end
455
270
 
456
- def execution_strategy_for_operation(operation)
457
- case operation
458
- when "query"
459
- query_execution_strategy
460
- when "mutation"
461
- mutation_execution_strategy
462
- when "subscription"
463
- subscription_execution_strategy
464
- else
465
- raise ArgumentError, "unknown operation type: #{operation}"
271
+ def static_validator
272
+ GraphQL::StaticValidation::Validator.new(schema: self)
466
273
  end
467
- end
468
274
 
469
- # Determine the GraphQL type for a given object.
470
- # This is required for unions and interfaces (including Relay's `Node` interface)
471
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
472
- # @param type [GraphQL::UnionType, GraphQL:InterfaceType] the abstract type which is being resolved
473
- # @param object [Any] An application object which GraphQL is currently resolving on
474
- # @param ctx [GraphQL::Query::Context] The context for the current query
475
- # @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
476
- def resolve_type(type, object, ctx = :__undefined__)
477
- check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
478
- if @resolve_type_proc.nil?
479
- raise(NotImplementedError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
275
+ def use(plugin, **kwargs)
276
+ if kwargs.any?
277
+ plugin.use(self, **kwargs)
278
+ else
279
+ plugin.use(self)
480
280
  end
481
- @resolve_type_proc.call(ok_type, ok_object, ok_ctx)
281
+ own_plugins << [plugin, kwargs]
482
282
  end
483
- end
484
283
 
485
- # This is a compatibility hack so that instance-level and class-level
486
- # methods can get correctness checks without calling one another
487
- # @api private
488
- def check_resolved_type(type, object, ctx = :__undefined__)
489
- if ctx == :__undefined__
490
- # Old method signature
491
- ctx = object
492
- object = type
493
- type = nil
284
+ def plugins
285
+ find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
286
+ end
287
+
288
+ # Build a map of `{ name => type }` and return it
289
+ # @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
290
+ # @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
291
+ def types(context = GraphQL::Query::NullContext)
292
+ all_types = non_introspection_types.merge(introspection_system.types)
293
+ visible_types = {}
294
+ all_types.each do |k, v|
295
+ visible_types[k] =if v.is_a?(Array)
296
+ visible_t = nil
297
+ v.each do |t|
298
+ if t.visible?(context)
299
+ if visible_t.nil?
300
+ visible_t = t
301
+ else
302
+ raise DuplicateNamesError.new(
303
+ duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
304
+ )
305
+ end
306
+ end
307
+ end
308
+ visible_t
309
+ else
310
+ v
311
+ end
312
+ end
313
+ visible_types
494
314
  end
495
315
 
496
- if object.is_a?(GraphQL::Schema::Object)
497
- object = object.object
498
- end
316
+ # @param type_name [String]
317
+ # @return [Module, nil] A type, or nil if there's no type called `type_name`
318
+ def get_type(type_name, context = GraphQL::Query::NullContext)
319
+ local_entry = own_types[type_name]
320
+ type_defn = case local_entry
321
+ when nil
322
+ nil
323
+ when Array
324
+ visible_t = nil
325
+ warden = Warden.from_context(context)
326
+ local_entry.each do |t|
327
+ if warden.visible_type?(t, context)
328
+ if visible_t.nil?
329
+ visible_t = t
330
+ else
331
+ raise DuplicateNamesError.new(
332
+ duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
333
+ )
334
+ end
335
+ end
336
+ end
337
+ visible_t
338
+ when Module
339
+ local_entry
340
+ else
341
+ raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
342
+ end
499
343
 
500
- if type.respond_to?(:graphql_definition)
501
- type = type.graphql_definition
344
+ type_defn ||
345
+ introspection_system.types[type_name] || # todo context-specific introspection?
346
+ (superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
502
347
  end
503
348
 
504
- # Prefer a type-local function; fall back to the schema-level function
505
- type_proc = type && type.resolve_type_proc
506
- type_result = if type_proc
507
- type_proc.call(object, ctx)
508
- else
509
- yield(type, object, ctx)
510
- end
349
+ # @api private
350
+ attr_writer :connections
511
351
 
512
- if type_result.nil?
513
- nil
514
- else
515
- after_lazy(type_result) do |resolved_type_result|
516
- if resolved_type_result.respond_to?(:graphql_definition)
517
- resolved_type_result = resolved_type_result.graphql_definition
518
- end
519
- if !resolved_type_result.is_a?(GraphQL::BaseType)
520
- type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
521
- raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
352
+ # @return [GraphQL::Pagination::Connections] if installed
353
+ def connections
354
+ if defined?(@connections)
355
+ @connections
356
+ else
357
+ inherited_connections = find_inherited_value(:connections, nil)
358
+ # This schema is part of an inheritance chain which is using new connections,
359
+ # make a new instance, so we don't pollute the upstream one.
360
+ if inherited_connections
361
+ @connections = Pagination::Connections.new(schema: self)
522
362
  else
523
- resolved_type_result
363
+ nil
524
364
  end
525
365
  end
526
366
  end
527
- end
528
367
 
529
- def resolve_type=(new_resolve_type_proc)
530
- callable = GraphQL::BackwardsCompatibility.wrap_arity(new_resolve_type_proc, from: 2, to: 3, last: true, name: "Schema#resolve_type(type, obj, ctx)")
531
- @resolve_type_proc = callable
532
- end
533
-
534
- # Fetch an application object by its unique id
535
- # @param id [String] A unique identifier, provided previously by this GraphQL schema
536
- # @param ctx [GraphQL::Query::Context] The context for the current query
537
- # @return [Any] The application object identified by `id`
538
- def object_from_id(id, ctx)
539
- if @object_from_id_proc.nil?
540
- raise(NotImplementedError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
541
- else
542
- @object_from_id_proc.call(id, ctx)
368
+ def new_connections?
369
+ !!connections
543
370
  end
544
- end
545
371
 
546
- # @param new_proc [#call] A new callable for fetching objects by ID
547
- def object_from_id=(new_proc)
548
- @object_from_id_proc = new_proc
549
- end
550
-
551
- # When we encounter a type error during query execution, we call this hook.
552
- #
553
- # You can use this hook to write a log entry,
554
- # add a {GraphQL::ExecutionError} to the response (with `ctx.add_error`)
555
- # or raise an exception and halt query execution.
556
- #
557
- # @example A `nil` is encountered by a non-null field
558
- # type_error ->(err, query_ctx) {
559
- # err.is_a?(GraphQL::InvalidNullError) # => true
560
- # }
561
- #
562
- # @example An object doesn't resolve to one of a {UnionType}'s members
563
- # type_error ->(err, query_ctx) {
564
- # err.is_a?(GraphQL::UnresolvedTypeError) # => true
565
- # }
566
- #
567
- # @see {DefaultTypeError} is the default behavior.
568
- # @param err [GraphQL::TypeError] The error encountered during execution
569
- # @param ctx [GraphQL::Query::Context] The context for the field where the error occurred
570
- # @return void
571
- def type_error(err, ctx)
572
- @type_error_proc.call(err, ctx)
573
- end
574
-
575
- # @param new_proc [#call] A new callable for handling type errors during execution
576
- def type_error=(new_proc)
577
- @type_error_proc = new_proc
578
- end
579
-
580
- # Can't delegate to `class`
581
- alias :_schema_class :class
582
- def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :unauthorized_field, :inaccessible_fields
583
- def_delegators :_schema_class, :directive
584
-
585
- # A function to call when {#execute} receives an invalid query string
586
- #
587
- # @see {DefaultParseError} is the default behavior.
588
- # @param err [GraphQL::ParseError] The error encountered during parsing
589
- # @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
590
- # @return void
591
- def parse_error(err, ctx)
592
- @parse_error_proc.call(err, ctx)
593
- end
594
-
595
- # @param new_proc [#call] A new callable for handling parse errors during execution
596
- def parse_error=(new_proc)
597
- @parse_error_proc = new_proc
598
- end
599
-
600
- # Get a unique identifier from this object
601
- # @param object [Any] An application object
602
- # @param type [GraphQL::BaseType] The current type definition
603
- # @param ctx [GraphQL::Query::Context] the context for the current query
604
- # @return [String] a unique identifier for `object` which clients can use to refetch it
605
- def id_from_object(object, type, ctx)
606
- if @id_from_object_proc.nil?
607
- raise(NotImplementedError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
608
- else
609
- @id_from_object_proc.call(object, type, ctx)
372
+ def query(new_query_object = nil)
373
+ if new_query_object
374
+ if @query_object
375
+ raise GraphQL::Error, "Second definition of `query(...)` (#{new_query_object.inspect}) is invalid, already configured with #{@query_object.inspect}"
376
+ else
377
+ @query_object = new_query_object
378
+ add_type_and_traverse(new_query_object, root: true)
379
+ nil
380
+ end
381
+ else
382
+ @query_object || find_inherited_value(:query)
383
+ end
610
384
  end
611
- end
612
-
613
- # @param new_proc [#call] A new callable for generating unique IDs
614
- def id_from_object=(new_proc)
615
- @id_from_object_proc = new_proc
616
- end
617
-
618
- # Create schema with the result of an introspection query.
619
- # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
620
- # @return [GraphQL::Schema] the schema described by `input`
621
- def self.from_introspection(introspection_result)
622
- GraphQL::Schema::Loader.load(introspection_result)
623
- end
624
-
625
- # Create schema from an IDL schema or file containing an IDL definition.
626
- # @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
627
- # @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
628
- # @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
629
- # @return [GraphQL::Schema] the schema described by `document`
630
- def self.from_definition(definition_or_path, default_resolve: BuildFromDefinition::DefaultResolve, parser: BuildFromDefinition::DefaultParser)
631
- # If the file ends in `.graphql`, treat it like a filepath
632
- definition = if definition_or_path.end_with?(".graphql")
633
- File.read(definition_or_path)
634
- else
635
- definition_or_path
636
- end
637
- GraphQL::Schema::BuildFromDefinition.from_definition(definition, default_resolve: default_resolve, parser: parser)
638
- end
639
-
640
- # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
641
- class InvalidDocumentError < Error; end;
642
-
643
- # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
644
- def lazy_method_name(obj)
645
- @lazy_methods.get(obj)
646
- end
647
-
648
- # @return [Boolean] True if this object should be lazily resolved
649
- def lazy?(obj)
650
- !!lazy_method_name(obj)
651
- end
652
-
653
- # Return the GraphQL IDL for the schema
654
- # @param context [Hash]
655
- # @param only [<#call(member, ctx)>]
656
- # @param except [<#call(member, ctx)>]
657
- # @return [String]
658
- def to_definition(only: nil, except: nil, context: {})
659
- GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
660
- end
661
-
662
- # Return the GraphQL::Language::Document IDL AST for the schema
663
- # @return [GraphQL::Language::Document]
664
- def to_document
665
- GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
666
- end
667
-
668
- # Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
669
- # @param context [Hash]
670
- # @param only [<#call(member, ctx)>]
671
- # @param except [<#call(member, ctx)>]
672
- # @return [Hash] GraphQL result
673
- def as_json(only: nil, except: nil, context: {})
674
- execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
675
- end
676
385
 
677
- # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
678
- # @see {#as_json}
679
- # @return [String]
680
- def to_json(*args)
681
- JSON.pretty_generate(as_json(*args))
682
- end
683
-
684
- class << self
685
- extend Forwardable
686
- # For compatibility, these methods all:
687
- # - Cause the Schema instance to be created, if it hasn't been created yet
688
- # - Delegate to that instance
689
- # Eventually, the methods will be moved into this class, removing the need for the singleton.
690
- def_delegators :graphql_definition,
691
- # Schema structure
692
- :as_json, :to_json, :to_document, :to_definition,
693
- # Execution
694
- :execute, :multiplex,
695
- :static_validator, :introspection_system,
696
- :query_analyzers, :tracers, :instrumenters,
697
- :execution_strategy_for_operation,
698
- :validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy, :sync_lazy,
699
- # Configuration
700
- :analysis_engine, :analysis_engine=, :using_ast_analysis?, :interpreter?,
701
- :max_complexity=, :max_depth=,
702
- :error_bubbling=,
703
- :metadata,
704
- :default_mask,
705
- :default_filter, :redefine,
706
- :id_from_object_proc, :object_from_id_proc,
707
- :id_from_object=, :object_from_id=,
708
- :remove_handler,
709
- # Members
710
- :types, :get_fields, :find,
711
- :root_type_for_operation,
712
- :subscriptions,
713
- :union_memberships,
714
- :get_field, :root_types, :references_to, :type_from_ast,
715
- :possible_types
716
-
717
- def graphql_definition
718
- @graphql_definition ||= to_graphql
719
- end
720
-
721
- def use(plugin, options = {})
722
- plugins << [plugin, options]
386
+ def mutation(new_mutation_object = nil)
387
+ if new_mutation_object
388
+ if @mutation_object
389
+ raise GraphQL::Error, "Second definition of `mutation(...)` (#{new_mutation_object.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
390
+ else
391
+ @mutation_object = new_mutation_object
392
+ add_type_and_traverse(new_mutation_object, root: true)
393
+ nil
394
+ end
395
+ else
396
+ @mutation_object || find_inherited_value(:mutation)
397
+ end
723
398
  end
724
399
 
725
- def plugins
726
- @plugins ||= []
727
- end
728
-
729
- def to_graphql
730
- schema_defn = self.new
731
- schema_defn.raise_definition_error = true
732
- schema_defn.query = query
733
- schema_defn.mutation = mutation
734
- schema_defn.subscription = subscription
735
- schema_defn.max_complexity = max_complexity
736
- schema_defn.error_bubbling = error_bubbling
737
- schema_defn.max_depth = max_depth
738
- schema_defn.default_max_page_size = default_max_page_size
739
- schema_defn.orphan_types = orphan_types
740
-
741
- prepped_dirs = {}
742
- directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
743
- schema_defn.directives = prepped_dirs
744
- schema_defn.introspection_namespace = introspection
745
- schema_defn.resolve_type = method(:resolve_type)
746
- schema_defn.object_from_id = method(:object_from_id)
747
- schema_defn.id_from_object = method(:id_from_object)
748
- schema_defn.type_error = method(:type_error)
749
- schema_defn.context_class = context_class
750
- schema_defn.cursor_encoder = cursor_encoder
751
- schema_defn.tracers.concat(defined_tracers)
752
- schema_defn.query_analyzers.concat(defined_query_analyzers)
753
-
754
- schema_defn.middleware.concat(defined_middleware)
755
- schema_defn.multiplex_analyzers.concat(defined_multiplex_analyzers)
756
- schema_defn.query_execution_strategy = query_execution_strategy
757
- schema_defn.mutation_execution_strategy = mutation_execution_strategy
758
- schema_defn.subscription_execution_strategy = subscription_execution_strategy
759
- defined_instrumenters.each do |step, insts|
760
- insts.each do |inst|
761
- schema_defn.instrumenters[step] << inst
400
+ def subscription(new_subscription_object = nil)
401
+ if new_subscription_object
402
+ if @subscription_object
403
+ raise GraphQL::Error, "Second definition of `subscription(...)` (#{new_subscription_object.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
404
+ else
405
+ @subscription_object = new_subscription_object
406
+ add_subscription_extension_if_necessary
407
+ add_type_and_traverse(new_subscription_object, root: true)
408
+ nil
762
409
  end
410
+ else
411
+ @subscription_object || find_inherited_value(:subscription)
763
412
  end
764
- lazy_classes.each do |lazy_class, value_method|
765
- schema_defn.lazy_methods.set(lazy_class, value_method)
413
+ end
414
+
415
+ # @see [GraphQL::Schema::Warden] Restricted access to root types
416
+ # @return [GraphQL::ObjectType, nil]
417
+ def root_type_for_operation(operation)
418
+ case operation
419
+ when "query"
420
+ query
421
+ when "mutation"
422
+ mutation
423
+ when "subscription"
424
+ subscription
425
+ else
426
+ raise ArgumentError, "unknown operation type: #{operation}"
766
427
  end
767
- if @rescues
768
- @rescues.each do |err_class, handler|
769
- schema_defn.rescue_from(err_class, &handler)
770
- end
428
+ end
429
+
430
+ def root_types
431
+ @root_types
432
+ end
433
+
434
+ def warden_class
435
+ if defined?(@warden_class)
436
+ @warden_class
437
+ elsif superclass.respond_to?(:warden_class)
438
+ superclass.warden_class
439
+ else
440
+ GraphQL::Schema::Warden
771
441
  end
442
+ end
772
443
 
773
- if plugins.any?
774
- schema_plugins = plugins
775
- # TODO don't depend on .define
776
- schema_defn = schema_defn.redefine do
777
- schema_plugins.each do |plugin, options|
778
- if options.any?
779
- use(plugin, **options)
780
- else
781
- use(plugin)
444
+ attr_writer :warden_class
445
+
446
+ # @param type [Module] The type definition whose possible types you want to see
447
+ # @return [Hash<String, Module>] All possible types, if no `type` is given.
448
+ # @return [Array<Module>] Possible types for `type`, if it's given.
449
+ def possible_types(type = nil, context = GraphQL::Query::NullContext)
450
+ if type
451
+ # TODO duck-typing `.possible_types` would probably be nicer here
452
+ if type.kind.union?
453
+ type.possible_types(context: context)
454
+ else
455
+ stored_possible_types = own_possible_types[type.graphql_name]
456
+ visible_possible_types = if stored_possible_types && type.kind.interface?
457
+ stored_possible_types.select do |possible_type|
458
+ possible_type.interfaces(context).include?(type)
782
459
  end
460
+ else
461
+ stored_possible_types
783
462
  end
463
+ visible_possible_types ||
464
+ introspection_system.possible_types[type.graphql_name] ||
465
+ (
466
+ superclass.respond_to?(:possible_types) ?
467
+ superclass.possible_types(type, context) :
468
+ EMPTY_ARRAY
469
+ )
784
470
  end
471
+ else
472
+ find_inherited_value(:possible_types, EMPTY_HASH)
473
+ .merge(own_possible_types)
474
+ .merge(introspection_system.possible_types)
785
475
  end
786
- # Do this after `plugins` since Interpreter is a plugin
787
- if schema_defn.query_execution_strategy != GraphQL::Execution::Interpreter
788
- schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
476
+ end
477
+
478
+ def union_memberships(type = nil)
479
+ if type
480
+ own_um = own_union_memberships.fetch(type.graphql_name, EMPTY_ARRAY)
481
+ inherited_um = find_inherited_value(:union_memberships, EMPTY_HASH).fetch(type.graphql_name, EMPTY_ARRAY)
482
+ own_um + inherited_um
483
+ else
484
+ joined_um = own_union_memberships.dup
485
+ find_inherited_value(:union_memberhips, EMPTY_HASH).each do |k, v|
486
+ um = joined_um[k] ||= []
487
+ um.concat(v)
488
+ end
489
+ joined_um
789
490
  end
790
- schema_defn.send(:rebuild_artifacts)
491
+ end
791
492
 
792
- schema_defn
493
+ # @api private
494
+ # @see GraphQL::Dataloader
495
+ def dataloader_class
496
+ @dataloader_class || GraphQL::Dataloader::NullDataloader
793
497
  end
794
498
 
795
- def query(new_query_object = nil)
796
- if new_query_object
797
- @query_object = new_query_object
499
+ attr_writer :dataloader_class
500
+
501
+ def references_to(to_type = nil, from: nil)
502
+ @own_references_to ||= Hash.new { |h, k| h[k] = [] }
503
+ if to_type
504
+ if !to_type.is_a?(String)
505
+ to_type = to_type.graphql_name
506
+ end
507
+
508
+ if from
509
+ @own_references_to[to_type] << from
510
+ else
511
+ own_refs = @own_references_to[to_type]
512
+ inherited_refs = find_inherited_value(:references_to, EMPTY_HASH)[to_type] || EMPTY_ARRAY
513
+ own_refs + inherited_refs
514
+ end
798
515
  else
799
- @query_object.respond_to?(:graphql_definition) ? @query_object.graphql_definition : @query_object
516
+ # `@own_references_to` can be quite large for big schemas,
517
+ # and generally speaking, we won't inherit any values.
518
+ # So optimize the most common case -- don't create a duplicate Hash.
519
+ inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
520
+ if inherited_value.any?
521
+ inherited_value.merge(@own_references_to)
522
+ else
523
+ @own_references_to
524
+ end
800
525
  end
801
526
  end
802
527
 
803
- def mutation(new_mutation_object = nil)
804
- if new_mutation_object
805
- @mutation_object = new_mutation_object
528
+ def type_from_ast(ast_node, context: nil)
529
+ type_owner = context ? context.warden : self
530
+ GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
531
+ end
532
+
533
+ def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
534
+ parent_type = case type_or_name
535
+ when LateBoundType
536
+ get_type(type_or_name.name, context)
537
+ when String
538
+ get_type(type_or_name, context)
539
+ when Module
540
+ type_or_name
806
541
  else
807
- @mutation_object.respond_to?(:graphql_definition) ? @mutation_object.graphql_definition : @mutation_object
542
+ raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
808
543
  end
809
- end
810
544
 
811
- def subscription(new_subscription_object = nil)
812
- if new_subscription_object
813
- @subscription_object = new_subscription_object
545
+ if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
546
+ field
547
+ elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
548
+ entry_point_field
549
+ elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
550
+ dynamic_field
814
551
  else
815
- @subscription_object.respond_to?(:graphql_definition) ? @subscription_object.graphql_definition : @subscription_object
552
+ nil
816
553
  end
817
554
  end
818
555
 
556
+ def get_fields(type, context = GraphQL::Query::NullContext)
557
+ type.fields(context)
558
+ end
559
+
819
560
  def introspection(new_introspection_namespace = nil)
820
561
  if new_introspection_namespace
821
562
  @introspection = new_introspection_namespace
563
+ # reset this cached value:
564
+ @introspection_system = nil
822
565
  else
823
- @introspection
566
+ @introspection || find_inherited_value(:introspection)
567
+ end
568
+ end
569
+
570
+ def introspection_system
571
+ if !@introspection_system
572
+ @introspection_system = Schema::IntrospectionSystem.new(self)
573
+ @introspection_system.resolve_late_bindings
824
574
  end
575
+ @introspection_system
825
576
  end
826
577
 
827
578
  def cursor_encoder(new_encoder = nil)
828
579
  if new_encoder
829
580
  @cursor_encoder = new_encoder
830
581
  end
831
- @cursor_encoder || Base64Encoder
582
+ @cursor_encoder || find_inherited_value(:cursor_encoder, Base64Encoder)
832
583
  end
833
584
 
834
585
  def default_max_page_size(new_default_max_page_size = nil)
835
586
  if new_default_max_page_size
836
587
  @default_max_page_size = new_default_max_page_size
837
588
  else
838
- @default_max_page_size
589
+ @default_max_page_size || find_inherited_value(:default_max_page_size)
590
+ end
591
+ end
592
+
593
+ def default_page_size(new_default_page_size = nil)
594
+ if new_default_page_size
595
+ @default_page_size = new_default_page_size
596
+ else
597
+ @default_page_size || find_inherited_value(:default_page_size)
839
598
  end
840
599
  end
841
600
 
@@ -843,7 +602,7 @@ module GraphQL
843
602
  if new_query_execution_strategy
844
603
  @query_execution_strategy = new_query_execution_strategy
845
604
  else
846
- @query_execution_strategy || self.default_execution_strategy
605
+ @query_execution_strategy || find_inherited_value(:query_execution_strategy, self.default_execution_strategy)
847
606
  end
848
607
  end
849
608
 
@@ -851,7 +610,7 @@ module GraphQL
851
610
  if new_mutation_execution_strategy
852
611
  @mutation_execution_strategy = new_mutation_execution_strategy
853
612
  else
854
- @mutation_execution_strategy || self.default_execution_strategy
613
+ @mutation_execution_strategy || find_inherited_value(:mutation_execution_strategy, self.default_execution_strategy)
855
614
  end
856
615
  end
857
616
 
@@ -859,39 +618,159 @@ module GraphQL
859
618
  if new_subscription_execution_strategy
860
619
  @subscription_execution_strategy = new_subscription_execution_strategy
861
620
  else
862
- @subscription_execution_strategy || self.default_execution_strategy
621
+ @subscription_execution_strategy || find_inherited_value(:subscription_execution_strategy, self.default_execution_strategy)
622
+ end
623
+ end
624
+
625
+ attr_writer :validate_timeout
626
+
627
+ def validate_timeout(new_validate_timeout = nil)
628
+ if new_validate_timeout
629
+ @validate_timeout = new_validate_timeout
630
+ elsif defined?(@validate_timeout)
631
+ @validate_timeout
632
+ else
633
+ find_inherited_value(:validate_timeout)
863
634
  end
864
635
  end
865
636
 
637
+ # Validate a query string according to this schema.
638
+ # @param string_or_document [String, GraphQL::Language::Nodes::Document]
639
+ # @return [Array<GraphQL::StaticValidation::Error >]
640
+ def validate(string_or_document, rules: nil, context: nil)
641
+ doc = if string_or_document.is_a?(String)
642
+ GraphQL.parse(string_or_document)
643
+ else
644
+ string_or_document
645
+ end
646
+ query = GraphQL::Query.new(self, document: doc, context: context)
647
+ validator_opts = { schema: self }
648
+ rules && (validator_opts[:rules] = rules)
649
+ validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
650
+ res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
651
+ res[:errors]
652
+ end
653
+
654
+ attr_writer :validate_max_errors
655
+
656
+ def validate_max_errors(new_validate_max_errors = nil)
657
+ if new_validate_max_errors
658
+ @validate_max_errors = new_validate_max_errors
659
+ elsif defined?(@validate_max_errors)
660
+ @validate_max_errors
661
+ else
662
+ find_inherited_value(:validate_max_errors)
663
+ end
664
+ end
665
+
666
+ attr_writer :max_complexity
667
+
866
668
  def max_complexity(max_complexity = nil)
867
669
  if max_complexity
868
670
  @max_complexity = max_complexity
869
- else
671
+ elsif defined?(@max_complexity)
870
672
  @max_complexity
673
+ else
674
+ find_inherited_value(:max_complexity)
871
675
  end
872
676
  end
873
677
 
678
+ attr_writer :analysis_engine
679
+
680
+ def analysis_engine
681
+ @analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
682
+ end
683
+
684
+ def using_ast_analysis?
685
+ true
686
+ end
687
+
688
+ def interpreter?
689
+ true
690
+ end
691
+
692
+ attr_writer :interpreter
693
+
874
694
  def error_bubbling(new_error_bubbling = nil)
875
695
  if !new_error_bubbling.nil?
876
696
  @error_bubbling = new_error_bubbling
877
697
  else
878
- @error_bubbling
698
+ @error_bubbling.nil? ? find_inherited_value(:error_bubbling) : @error_bubbling
879
699
  end
880
700
  end
881
701
 
702
+ attr_writer :error_bubbling
703
+
704
+ attr_writer :max_depth
705
+
882
706
  def max_depth(new_max_depth = nil)
883
707
  if new_max_depth
884
708
  @max_depth = new_max_depth
885
- else
709
+ elsif defined?(@max_depth)
886
710
  @max_depth
711
+ else
712
+ find_inherited_value(:max_depth)
713
+ end
714
+ end
715
+
716
+ def disable_introspection_entry_points
717
+ @disable_introspection_entry_points = true
718
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
719
+ @introspection_system = nil
720
+ end
721
+
722
+ def disable_schema_introspection_entry_point
723
+ @disable_schema_introspection_entry_point = true
724
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
725
+ @introspection_system = nil
726
+ end
727
+
728
+ def disable_type_introspection_entry_point
729
+ @disable_type_introspection_entry_point = true
730
+ # TODO: this clears the cache made in `def types`. But this is not a great solution.
731
+ @introspection_system = nil
732
+ end
733
+
734
+ def disable_introspection_entry_points?
735
+ if instance_variable_defined?(:@disable_introspection_entry_points)
736
+ @disable_introspection_entry_points
737
+ else
738
+ find_inherited_value(:disable_introspection_entry_points?, false)
739
+ end
740
+ end
741
+
742
+ def disable_schema_introspection_entry_point?
743
+ if instance_variable_defined?(:@disable_schema_introspection_entry_point)
744
+ @disable_schema_introspection_entry_point
745
+ else
746
+ find_inherited_value(:disable_schema_introspection_entry_point?, false)
747
+ end
748
+ end
749
+
750
+ def disable_type_introspection_entry_point?
751
+ if instance_variable_defined?(:@disable_type_introspection_entry_point)
752
+ @disable_type_introspection_entry_point
753
+ else
754
+ find_inherited_value(:disable_type_introspection_entry_point?, false)
887
755
  end
888
756
  end
889
757
 
890
758
  def orphan_types(*new_orphan_types)
891
759
  if new_orphan_types.any?
892
- @orphan_types = new_orphan_types.flatten
760
+ new_orphan_types = new_orphan_types.flatten
761
+ add_type_and_traverse(new_orphan_types, root: false)
762
+ own_orphan_types.concat(new_orphan_types.flatten)
763
+ end
764
+
765
+ inherited_ot = find_inherited_value(:orphan_types, nil)
766
+ if inherited_ot
767
+ if own_orphan_types.any?
768
+ inherited_ot + own_orphan_types
769
+ else
770
+ inherited_ot
771
+ end
893
772
  else
894
- @orphan_types || []
773
+ own_orphan_types
895
774
  end
896
775
  end
897
776
 
@@ -899,7 +778,15 @@ module GraphQL
899
778
  if superclass <= GraphQL::Schema
900
779
  superclass.default_execution_strategy
901
780
  else
902
- @default_execution_strategy ||= GraphQL::Execution::Execute
781
+ @default_execution_strategy ||= GraphQL::Execution::Interpreter
782
+ end
783
+ end
784
+
785
+ def default_analysis_engine
786
+ if superclass <= GraphQL::Schema
787
+ superclass.default_analysis_engine
788
+ else
789
+ @default_analysis_engine ||= GraphQL::Analysis::AST
903
790
  end
904
791
  end
905
792
 
@@ -907,14 +794,73 @@ module GraphQL
907
794
  if new_context_class
908
795
  @context_class = new_context_class
909
796
  else
910
- @context_class || GraphQL::Query::Context
797
+ @context_class || find_inherited_value(:context_class, GraphQL::Query::Context)
911
798
  end
912
799
  end
913
800
 
914
801
  def rescue_from(*err_classes, &handler_block)
915
- @rescues ||= {}
916
802
  err_classes.each do |err_class|
917
- @rescues[err_class] = handler_block
803
+ Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
804
+ end
805
+ end
806
+
807
+ NEW_HANDLER_HASH = ->(h, k) {
808
+ h[k] = {
809
+ class: k,
810
+ handler: nil,
811
+ subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
812
+ }
813
+ }
814
+
815
+ def error_handlers
816
+ @error_handlers ||= {
817
+ class: nil,
818
+ handler: nil,
819
+ subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
820
+ }
821
+ end
822
+
823
+ # @api private
824
+ def handle_or_reraise(context, err)
825
+ handler = Execution::Errors.find_handler_for(self, err.class)
826
+ if handler
827
+ obj = context[:current_object]
828
+ args = context[:current_arguments]
829
+ args = args && args.respond_to?(:keyword_arguments) ? args.keyword_arguments : nil
830
+ field = context[:current_field]
831
+ if obj.is_a?(GraphQL::Schema::Object)
832
+ obj = obj.object
833
+ end
834
+ handler[:handler].call(err, obj, args, context, field)
835
+ else
836
+ raise err
837
+ end
838
+ end
839
+
840
+ # rubocop:disable Lint/DuplicateMethods
841
+ module ResolveTypeWithType
842
+ def resolve_type(type, obj, ctx)
843
+ maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
844
+ type.resolve_type(obj, ctx)
845
+ else
846
+ super
847
+ end
848
+
849
+ after_lazy(maybe_lazy_resolve_type_result) do |resolve_type_result|
850
+ if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
851
+ resolved_type = resolve_type_result[0]
852
+ resolved_value = resolve_type_result[1]
853
+ else
854
+ resolved_type = resolve_type_result
855
+ resolved_value = obj
856
+ end
857
+
858
+ if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
859
+ [resolved_type, resolved_value]
860
+ else
861
+ raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
862
+ end
863
+ end
918
864
  end
919
865
  end
920
866
 
@@ -922,36 +868,38 @@ module GraphQL
922
868
  if type.kind.object?
923
869
  type
924
870
  else
925
- raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
871
+ 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})"
872
+ end
873
+ end
874
+ # rubocop:enable Lint/DuplicateMethods
875
+
876
+ def inherited(child_class)
877
+ if self == GraphQL::Schema
878
+ child_class.directives(default_directives.values)
926
879
  end
880
+ child_class.singleton_class.prepend(ResolveTypeWithType)
881
+ super
927
882
  end
928
883
 
929
884
  def object_from_id(node_id, ctx)
930
- raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
885
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
931
886
  end
932
887
 
933
888
  def id_from_object(object, type, ctx)
934
- raise NotImplementedError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
889
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.id_from_object(object, type, ctx) must be implemented to create global ids (tried to create an id for `#{object.inspect}`)"
935
890
  end
936
891
 
937
- def visible?(member, context)
938
- call_on_type_class(member, :visible?, context, default: true)
892
+ def visible?(member, ctx)
893
+ member.visible?(ctx)
939
894
  end
940
895
 
941
- def accessible?(member, context)
942
- call_on_type_class(member, :accessible?, context, default: true)
896
+ def schema_directive(dir_class, **options)
897
+ @own_schema_directives ||= []
898
+ Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
943
899
  end
944
900
 
945
- # This hook is called when a client tries to access one or more
946
- # fields that fail the `accessible?` check.
947
- #
948
- # By default, an error is added to the response. Override this hook to
949
- # track metrics or return a different error to the client.
950
- #
951
- # @param error [InaccessibleFieldsError] The analysis error for this check
952
- # @return [AnalysisError, nil] Return an error to skip the query
953
- def inaccessible_fields(error)
954
- error
901
+ def schema_directives
902
+ Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
955
903
  end
956
904
 
957
905
  # This hook is called when an object fails an `authorized?` check.
@@ -989,221 +937,400 @@ module GraphQL
989
937
  unauthorized_object(unauthorized_error)
990
938
  end
991
939
 
992
- def type_error(type_err, ctx)
993
- DefaultTypeError.call(type_err, ctx)
940
+ def type_error(type_error, ctx)
941
+ case type_error
942
+ when GraphQL::InvalidNullError
943
+ ctx.errors << type_error
944
+ when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
945
+ raise type_error
946
+ when GraphQL::IntegerDecodingError
947
+ nil
948
+ end
949
+ end
950
+
951
+ # A function to call when {#execute} receives an invalid query string
952
+ #
953
+ # The default is to add the error to `context.errors`
954
+ # @param parse_err [GraphQL::ParseError] The error encountered during parsing
955
+ # @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
956
+ # @return void
957
+ def parse_error(parse_err, ctx)
958
+ ctx.errors.push(parse_err)
994
959
  end
995
960
 
996
961
  def lazy_resolve(lazy_class, value_method)
997
- lazy_classes[lazy_class] = value_method
962
+ lazy_methods.set(lazy_class, value_method)
998
963
  end
999
964
 
1000
965
  def instrument(instrument_step, instrumenter, options = {})
1001
- step = if instrument_step == :field && options[:after_built_ins]
1002
- :field_after_built_ins
1003
- else
1004
- instrument_step
1005
- end
1006
- defined_instrumenters[step] << instrumenter
966
+ own_instrumenters[instrument_step] << instrumenter
1007
967
  end
1008
968
 
1009
- def directives(new_directives = nil)
1010
- if new_directives
1011
- @directives = new_directives.reduce({}) { |m, d| m[d.name] = d; m }
969
+ # Add several directives at once
970
+ # @param new_directives [Class]
971
+ def directives(*new_directives)
972
+ if new_directives.any?
973
+ new_directives.flatten.each { |d| directive(d) }
1012
974
  end
1013
975
 
1014
- @directives ||= default_directives
976
+ inherited_dirs = find_inherited_value(:directives, default_directives)
977
+ if own_directives.any?
978
+ inherited_dirs.merge(own_directives)
979
+ else
980
+ inherited_dirs
981
+ end
1015
982
  end
1016
983
 
984
+ # Attach a single directive to this schema
985
+ # @param new_directive [Class]
986
+ # @return void
1017
987
  def directive(new_directive)
1018
- directives[new_directive.graphql_name] = new_directive
988
+ add_type_and_traverse(new_directive, root: false)
1019
989
  end
1020
990
 
1021
991
  def default_directives
1022
- {
1023
- "include" => GraphQL::Directive::IncludeDirective,
1024
- "skip" => GraphQL::Directive::SkipDirective,
1025
- "deprecated" => GraphQL::Directive::DeprecatedDirective,
1026
- }
992
+ @default_directives ||= {
993
+ "include" => GraphQL::Schema::Directive::Include,
994
+ "skip" => GraphQL::Schema::Directive::Skip,
995
+ "deprecated" => GraphQL::Schema::Directive::Deprecated,
996
+ "oneOf" => GraphQL::Schema::Directive::OneOf,
997
+ "specifiedBy" => GraphQL::Schema::Directive::SpecifiedBy,
998
+ }.freeze
1027
999
  end
1028
1000
 
1029
1001
  def tracer(new_tracer)
1030
- defined_tracers << new_tracer
1002
+ if !(trace_class_for(:default) < GraphQL::Tracing::CallLegacyTracers)
1003
+ trace_with(GraphQL::Tracing::CallLegacyTracers)
1004
+ end
1005
+
1006
+ own_tracers << new_tracer
1031
1007
  end
1032
1008
 
1033
- def query_analyzer(new_analyzer)
1034
- if new_analyzer == GraphQL::Authorization::Analyzer
1035
- warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1036
- end
1037
- defined_query_analyzers << new_analyzer
1009
+ def tracers
1010
+ find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
1038
1011
  end
1039
1012
 
1040
- def middleware(new_middleware = nil)
1041
- if new_middleware
1042
- defined_middleware << new_middleware
1013
+ # Mix `trace_mod` into this schema's `Trace` class so that its methods
1014
+ # will be called at runtime.
1015
+ #
1016
+ # @param trace_mod [Module] A module that implements tracing methods
1017
+ # @param mode [Symbol] Trace module will only be used for this trade mode
1018
+ # @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
1019
+ # @return [void]
1020
+ def trace_with(trace_mod, mode: :default, **options)
1021
+ if mode.is_a?(Array)
1022
+ mode.each { |m| trace_with(trace_mod, mode: m, **options) }
1043
1023
  else
1044
- graphql_definition.middleware
1024
+ tc = trace_class_for(mode)
1025
+ tc.include(trace_mod)
1026
+ if mode != :default
1027
+ own_trace_modules[mode] << trace_mod
1028
+ end
1029
+ t_opts = trace_options_for(mode)
1030
+ t_opts.merge!(options)
1045
1031
  end
1032
+ nil
1046
1033
  end
1047
1034
 
1048
- def multiplex_analyzer(new_analyzer)
1049
- defined_multiplex_analyzers << new_analyzer
1035
+ # The options hash for this trace mode
1036
+ # @return [Hash]
1037
+ def trace_options_for(mode)
1038
+ @trace_options_for_mode ||= {}
1039
+ @trace_options_for_mode[mode] ||= begin
1040
+ if superclass.respond_to?(:trace_options_for)
1041
+ superclass.trace_options_for(mode).dup
1042
+ else
1043
+ {}
1044
+ end
1045
+ end
1050
1046
  end
1051
1047
 
1052
- private
1048
+ # Create a trace instance which will include the trace modules specified for the optional mode.
1049
+ #
1050
+ # @param mode [Symbol] Trace modules for this trade mode will be included
1051
+ # @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
1052
+ # @return [Tracing::Trace]
1053
+ def new_trace(mode: nil, **options)
1054
+ target = options[:query] || options[:multiplex]
1055
+ mode ||= target && target.context[:trace_mode]
1056
+
1057
+ trace_mode = if mode
1058
+ mode
1059
+ elsif target && target.context[:backtrace]
1060
+ :default_backtrace
1061
+ else
1062
+ :default
1063
+ end
1053
1064
 
1054
- def lazy_classes
1055
- @lazy_classes ||= {}
1065
+ base_trace_options = trace_options_for(trace_mode)
1066
+ trace_options = base_trace_options.merge(options)
1067
+ trace_class_for_mode = trace_class_for(trace_mode)
1068
+ trace_class_for_mode.new(**trace_options)
1056
1069
  end
1057
1070
 
1058
- def defined_instrumenters
1059
- @defined_instrumenters ||= Hash.new { |h,k| h[k] = [] }
1071
+ def query_analyzer(new_analyzer)
1072
+ own_query_analyzers << new_analyzer
1060
1073
  end
1061
1074
 
1062
- def defined_tracers
1063
- @defined_tracers ||= []
1075
+ def query_analyzers
1076
+ find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
1064
1077
  end
1065
1078
 
1066
- def defined_query_analyzers
1067
- @defined_query_analyzers ||= []
1079
+ def multiplex_analyzer(new_analyzer)
1080
+ own_multiplex_analyzers << new_analyzer
1068
1081
  end
1069
1082
 
1070
- def defined_middleware
1071
- @defined_middleware ||= []
1083
+ def multiplex_analyzers
1084
+ find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
1072
1085
  end
1073
1086
 
1074
- def defined_multiplex_analyzers
1075
- @defined_multiplex_analyzers ||= []
1087
+ def sanitized_printer(new_sanitized_printer = nil)
1088
+ if new_sanitized_printer
1089
+ @own_sanitized_printer = new_sanitized_printer
1090
+ else
1091
+ @own_sanitized_printer || GraphQL::Language::SanitizedPrinter
1092
+ end
1076
1093
  end
1077
1094
 
1078
- # Given this schema member, find the class-based definition object
1079
- # whose `method_name` should be treated as an application hook
1080
- # @see {.visible?}
1081
- # @see {.accessible?}
1082
- # @see {.authorized?}
1083
- def call_on_type_class(member, method_name, *args, default:)
1084
- member = if member.respond_to?(:metadata) && member.metadata
1085
- member.metadata[:type_class] || member
1095
+ # Execute a query on itself.
1096
+ # @see {Query#initialize} for arguments.
1097
+ # @return [Hash] query result, ready to be serialized as JSON
1098
+ def execute(query_str = nil, **kwargs)
1099
+ if query_str
1100
+ kwargs[:query] = query_str
1101
+ end
1102
+ # Some of the query context _should_ be passed to the multiplex, too
1103
+ multiplex_context = if (ctx = kwargs[:context])
1104
+ {
1105
+ backtrace: ctx[:backtrace],
1106
+ tracers: ctx[:tracers],
1107
+ trace: ctx[:trace],
1108
+ dataloader: ctx[:dataloader],
1109
+ trace_mode: ctx[:trace_mode],
1110
+ }
1086
1111
  else
1087
- member
1112
+ {}
1113
+ end
1114
+ # Since we're running one query, don't run a multiplex-level complexity analyzer
1115
+ all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
1116
+ all_results[0]
1117
+ end
1118
+
1119
+ # Execute several queries on itself, concurrently.
1120
+ #
1121
+ # @example Run several queries at once
1122
+ # context = { ... }
1123
+ # queries = [
1124
+ # { query: params[:query_1], variables: params[:variables_1], context: context },
1125
+ # { query: params[:query_2], variables: params[:variables_2], context: context },
1126
+ # ]
1127
+ # results = MySchema.multiplex(queries)
1128
+ # render json: {
1129
+ # result_1: results[0],
1130
+ # result_2: results[1],
1131
+ # }
1132
+ #
1133
+ # @see {Query#initialize} for query keyword arguments
1134
+ # @see {Execution::Multiplex#run_all} for multiplex keyword arguments
1135
+ # @param queries [Array<Hash>] Keyword arguments for each query
1136
+ # @param context [Hash] Multiplex-level context
1137
+ # @return [Array<Hash>] One result for each query in the input
1138
+ def multiplex(queries, **kwargs)
1139
+ GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
1140
+ end
1141
+
1142
+ def instrumenters
1143
+ inherited_instrumenters = find_inherited_value(:instrumenters) || Hash.new { |h,k| h[k] = [] }
1144
+ inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
1145
+ inherited + own
1088
1146
  end
1147
+ end
1089
1148
 
1090
- if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
1091
- member = t
1149
+ # @api private
1150
+ def add_subscription_extension_if_necessary
1151
+ if !defined?(@subscription_extension_added) && subscription && self.subscriptions
1152
+ @subscription_extension_added = true
1153
+ subscription.all_field_definitions.each do |field|
1154
+ if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
1155
+ field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1156
+ end
1157
+ end
1092
1158
  end
1159
+ end
1160
+
1161
+ def query_stack_error(query, err)
1162
+ query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
1163
+ end
1093
1164
 
1094
- if member.respond_to?(method_name)
1095
- member.public_send(method_name, *args)
1165
+ # Call the given block at the right time, either:
1166
+ # - Right away, if `value` is not registered with `lazy_resolve`
1167
+ # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
1168
+ # @api private
1169
+ def after_lazy(value, &block)
1170
+ if lazy?(value)
1171
+ GraphQL::Execution::Lazy.new do
1172
+ result = sync_lazy(value)
1173
+ # The returned result might also be lazy, so check it, too
1174
+ after_lazy(result, &block)
1175
+ end
1096
1176
  else
1097
- default
1177
+ yield(value) if block_given?
1098
1178
  end
1099
1179
  end
1100
- end
1101
1180
 
1181
+ # Override this method to handle lazy objects in a custom way.
1182
+ # @param value [Object] an instance of a class registered with {.lazy_resolve}
1183
+ # @return [Object] A GraphQL-ready (non-lazy) object
1184
+ # @api private
1185
+ def sync_lazy(value)
1186
+ lazy_method = lazy_method_name(value)
1187
+ if lazy_method
1188
+ synced_value = value.public_send(lazy_method)
1189
+ sync_lazy(synced_value)
1190
+ else
1191
+ value
1192
+ end
1193
+ end
1102
1194
 
1103
- def self.inherited(child_class)
1104
- child_class.singleton_class.class_eval do
1105
- prepend(MethodWrappers)
1195
+ # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
1196
+ def lazy_method_name(obj)
1197
+ lazy_methods.get(obj)
1106
1198
  end
1107
- end
1108
1199
 
1109
- module MethodWrappers
1110
- # Wrap the user-provided resolve-type in a correctness check
1111
- def resolve_type(type, obj, ctx = :__undefined__)
1112
- graphql_definition.check_resolved_type(type, obj, ctx) do |ok_type, ok_obj, ok_ctx|
1113
- super(ok_type, ok_obj, ok_ctx)
1114
- end
1200
+ # @return [Boolean] True if this object should be lazily resolved
1201
+ def lazy?(obj)
1202
+ !!lazy_method_name(obj)
1115
1203
  end
1116
- end
1117
1204
 
1118
- # Call the given block at the right time, either:
1119
- # - Right away, if `value` is not registered with `lazy_resolve`
1120
- # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
1121
- # @api private
1122
- def after_lazy(value)
1123
- if lazy?(value)
1124
- GraphQL::Execution::Lazy.new do
1125
- result = sync_lazy(value)
1126
- # The returned result might also be lazy, so check it, too
1127
- after_lazy(result) do |final_result|
1128
- yield(final_result) if block_given?
1205
+ # Return a lazy if any of `maybe_lazies` are lazy,
1206
+ # otherwise, call the block eagerly and return the result.
1207
+ # @param maybe_lazies [Array]
1208
+ # @api private
1209
+ def after_any_lazies(maybe_lazies)
1210
+ if maybe_lazies.any? { |l| lazy?(l) }
1211
+ GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
1212
+ yield result
1129
1213
  end
1214
+ else
1215
+ yield maybe_lazies
1130
1216
  end
1131
- else
1132
- yield(value) if block_given?
1133
1217
  end
1134
- end
1135
1218
 
1136
- # Override this method to handle lazy objects in a custom way.
1137
- # @param value [Object] an instance of a class registered with {.lazy_resolve}
1138
- # @param ctx [GraphQL::Query::Context] the context for this query
1139
- # @return [Object] A GraphQL-ready (non-lazy) object
1140
- def self.sync_lazy(value)
1141
- if block_given?
1142
- # This was already hit by the instance, just give it back
1143
- yield(value)
1144
- else
1145
- # This was called directly on the class, hit the instance
1146
- # which has the lazy method map
1147
- self.graphql_definition.sync_lazy(value)
1219
+ private
1220
+
1221
+ # @param t [Module, Array<Module>]
1222
+ # @return [void]
1223
+ def add_type_and_traverse(t, root:)
1224
+ if root
1225
+ @root_types ||= []
1226
+ @root_types << t
1227
+ end
1228
+ new_types = Array(t)
1229
+ addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
1230
+ addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
1231
+ if (prev_entry = own_types[name])
1232
+ prev_entries = case prev_entry
1233
+ when Array
1234
+ prev_entry
1235
+ when Module
1236
+ own_types[name] = [prev_entry]
1237
+ else
1238
+ raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
1239
+ end
1240
+
1241
+ case types_entry
1242
+ when Array
1243
+ prev_entries.concat(types_entry)
1244
+ prev_entries.uniq! # in case any are being re-visited
1245
+ when Module
1246
+ if !prev_entries.include?(types_entry)
1247
+ prev_entries << types_entry
1248
+ end
1249
+ else
1250
+ raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
1251
+ end
1252
+ else
1253
+ if types_entry.is_a?(Array)
1254
+ types_entry.uniq!
1255
+ end
1256
+ own_types[name] = types_entry
1257
+ end
1258
+ end
1259
+
1260
+ own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
1261
+ own_union_memberships.merge!(addition.union_memberships)
1262
+
1263
+ addition.references.each { |thing, pointers|
1264
+ pointers.each { |pointer| references_to(thing, from: pointer) }
1265
+ }
1266
+
1267
+ addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
1268
+
1269
+ addition.arguments_with_default_values.each do |arg|
1270
+ arg.validate_default_value
1271
+ end
1148
1272
  end
1149
- end
1150
1273
 
1151
- # @see Schema.sync_lazy for a hook to override
1152
- # @api private
1153
- def sync_lazy(value)
1154
- self.class.sync_lazy(value) { |v|
1155
- lazy_method = lazy_method_name(v)
1156
- if lazy_method
1157
- synced_value = value.public_send(lazy_method)
1158
- sync_lazy(synced_value)
1159
- else
1160
- v
1274
+ def lazy_methods
1275
+ if !defined?(@lazy_methods)
1276
+ if inherited_map = find_inherited_value(:lazy_methods)
1277
+ # this isn't _completely_ inherited :S (Things added after `dup` won't work)
1278
+ @lazy_methods = inherited_map.dup
1279
+ else
1280
+ @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
1281
+ @lazy_methods.set(GraphQL::Execution::Lazy, :value)
1282
+ @lazy_methods.set(GraphQL::Dataloader::Request, :load)
1283
+ end
1161
1284
  end
1162
- }
1163
- end
1285
+ @lazy_methods
1286
+ end
1164
1287
 
1165
- protected
1288
+ def own_types
1289
+ @own_types ||= {}
1290
+ end
1166
1291
 
1167
- def rescues?
1168
- !!@rescue_middleware
1169
- end
1292
+ def non_introspection_types
1293
+ find_inherited_value(:non_introspection_types, EMPTY_HASH).merge(own_types)
1294
+ end
1170
1295
 
1171
- # Lazily create a middleware and add it to the schema
1172
- # (Don't add it if it's not used)
1173
- def rescue_middleware
1174
- @rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
1175
- end
1296
+ def own_plugins
1297
+ @own_plugins ||= []
1298
+ end
1176
1299
 
1177
- private
1178
-
1179
- def rebuild_artifacts
1180
- if @rebuilding_artifacts
1181
- raise CyclicalDefinitionError, "Part of the schema build process re-triggered the schema build process, causing an infinite loop. Avoid using Schema#types, Schema#possible_types, and Schema#get_field during schema build."
1182
- else
1183
- @rebuilding_artifacts = true
1184
- @introspection_system = Schema::IntrospectionSystem.new(self)
1185
- traversal = Traversal.new(self)
1186
- @types = traversal.type_map
1187
- @root_types = [query, mutation, subscription]
1188
- @instrumented_field_map = traversal.instrumented_field_map
1189
- @type_reference_map = traversal.type_reference_map
1190
- @union_memberships = traversal.union_memberships
1191
- @find_cache = {}
1192
- @finder = Finder.new(self)
1193
- end
1194
- ensure
1195
- @rebuilding_artifacts = false
1196
- end
1300
+ def own_orphan_types
1301
+ @own_orphan_types ||= []
1302
+ end
1197
1303
 
1198
- class CyclicalDefinitionError < GraphQL::Error
1199
- end
1304
+ def own_possible_types
1305
+ @own_possible_types ||= {}
1306
+ end
1200
1307
 
1201
- def with_definition_error_check
1202
- if @definition_error
1203
- raise @definition_error
1204
- else
1205
- yield
1308
+ def own_union_memberships
1309
+ @own_union_memberships ||= {}
1310
+ end
1311
+
1312
+ def own_directives
1313
+ @own_directives ||= {}
1314
+ end
1315
+
1316
+ def own_instrumenters
1317
+ @own_instrumenters ||= Hash.new { |h,k| h[k] = [] }
1318
+ end
1319
+
1320
+ def own_tracers
1321
+ @own_tracers ||= []
1322
+ end
1323
+
1324
+ def own_query_analyzers
1325
+ @defined_query_analyzers ||= []
1326
+ end
1327
+
1328
+ def own_multiplex_analyzers
1329
+ @own_multiplex_analyzers ||= []
1206
1330
  end
1207
1331
  end
1332
+
1333
+ # Install these here so that subclasses will also install it.
1334
+ self.connections = GraphQL::Pagination::Connections.new(schema: self)
1208
1335
  end
1209
1336
  end