graphql 1.8.7 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +2 -1
  3. data/lib/generators/graphql/scalar_generator.rb +20 -0
  4. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  5. data/lib/generators/graphql/templates/scalar.erb +13 -0
  6. data/lib/graphql/analysis/ast/analyzer.rb +62 -0
  7. data/lib/graphql/analysis/ast/field_usage.rb +28 -0
  8. data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
  9. data/lib/graphql/analysis/ast/max_query_depth.rb +18 -0
  10. data/lib/graphql/analysis/ast/query_complexity.rb +114 -0
  11. data/lib/graphql/analysis/ast/query_depth.rb +66 -0
  12. data/lib/graphql/analysis/ast/visitor.rb +255 -0
  13. data/lib/graphql/analysis/ast.rb +82 -0
  14. data/lib/graphql/analysis.rb +1 -0
  15. data/lib/graphql/argument.rb +5 -0
  16. data/lib/graphql/authorization.rb +1 -0
  17. data/lib/graphql/backwards_compatibility.rb +1 -1
  18. data/lib/graphql/base_type.rb +1 -1
  19. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -2
  20. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -6
  21. data/lib/graphql/dig.rb +19 -0
  22. data/lib/graphql/directive/include_directive.rb +1 -7
  23. data/lib/graphql/directive/skip_directive.rb +1 -8
  24. data/lib/graphql/directive.rb +13 -1
  25. data/lib/graphql/enum_type.rb +8 -0
  26. data/lib/graphql/execution/execute.rb +36 -17
  27. data/lib/graphql/execution/instrumentation.rb +2 -0
  28. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  29. data/lib/graphql/execution/interpreter/hash_response.rb +46 -0
  30. data/lib/graphql/execution/interpreter/resolve.rb +58 -0
  31. data/lib/graphql/execution/interpreter/runtime.rb +597 -0
  32. data/lib/graphql/execution/interpreter.rb +99 -0
  33. data/lib/graphql/execution/lazy.rb +8 -1
  34. data/lib/graphql/execution/lookahead.rb +351 -0
  35. data/lib/graphql/execution/multiplex.rb +37 -29
  36. data/lib/graphql/execution.rb +2 -0
  37. data/lib/graphql/execution_error.rb +1 -1
  38. data/lib/graphql/field.rb +1 -7
  39. data/lib/graphql/integer_encoding_error.rb +12 -0
  40. data/lib/graphql/internal_representation/rewrite.rb +127 -142
  41. data/lib/graphql/introspection/dynamic_fields.rb +8 -2
  42. data/lib/graphql/introspection/entry_points.rb +11 -6
  43. data/lib/graphql/introspection/enum_value_type.rb +4 -0
  44. data/lib/graphql/introspection/schema_type.rb +7 -2
  45. data/lib/graphql/introspection/type_type.rb +9 -5
  46. data/lib/graphql/invalid_null_error.rb +1 -1
  47. data/lib/graphql/language/block_string.rb +37 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +10 -7
  49. data/lib/graphql/language/lexer.rb +55 -36
  50. data/lib/graphql/language/lexer.rl +8 -3
  51. data/lib/graphql/language/nodes.rb +440 -362
  52. data/lib/graphql/language/parser.rb +56 -56
  53. data/lib/graphql/language/parser.y +12 -12
  54. data/lib/graphql/language/printer.rb +2 -2
  55. data/lib/graphql/language/visitor.rb +158 -15
  56. data/lib/graphql/language.rb +0 -1
  57. data/lib/graphql/literal_validation_error.rb +6 -0
  58. data/lib/graphql/query/arguments.rb +3 -2
  59. data/lib/graphql/query/arguments_cache.rb +1 -1
  60. data/lib/graphql/query/context.rb +14 -5
  61. data/lib/graphql/query/executor.rb +1 -1
  62. data/lib/graphql/query/result.rb +1 -1
  63. data/lib/graphql/query/validation_pipeline.rb +35 -11
  64. data/lib/graphql/query/variable_validation_error.rb +10 -1
  65. data/lib/graphql/query.rb +16 -2
  66. data/lib/graphql/relay/base_connection.rb +2 -0
  67. data/lib/graphql/relay/connection_instrumentation.rb +3 -1
  68. data/lib/graphql/relay/connection_resolve.rb +1 -1
  69. data/lib/graphql/relay/node.rb +2 -28
  70. data/lib/graphql/relay/relation_connection.rb +1 -1
  71. data/lib/graphql/schema/argument.rb +13 -5
  72. data/lib/graphql/schema/base_64_encoder.rb +4 -4
  73. data/lib/graphql/schema/build_from_definition.rb +2 -4
  74. data/lib/graphql/schema/default_type_error.rb +1 -1
  75. data/lib/graphql/schema/directive/feature.rb +66 -0
  76. data/lib/graphql/schema/directive/include.rb +25 -0
  77. data/lib/graphql/schema/directive/skip.rb +25 -0
  78. data/lib/graphql/schema/directive/transform.rb +48 -0
  79. data/lib/graphql/schema/directive.rb +103 -0
  80. data/lib/graphql/schema/enum_value.rb +3 -2
  81. data/lib/graphql/schema/field/connection_extension.rb +50 -0
  82. data/lib/graphql/schema/field/scope_extension.rb +18 -0
  83. data/lib/graphql/schema/field.rb +273 -64
  84. data/lib/graphql/schema/field_extension.rb +69 -0
  85. data/lib/graphql/schema/input_object.rb +16 -8
  86. data/lib/graphql/schema/interface.rb +1 -0
  87. data/lib/graphql/schema/loader.rb +22 -16
  88. data/lib/graphql/schema/member/base_dsl_methods.rb +8 -2
  89. data/lib/graphql/schema/member/build_type.rb +33 -1
  90. data/lib/graphql/schema/member/has_arguments.rb +6 -2
  91. data/lib/graphql/schema/member/has_fields.rb +18 -70
  92. data/lib/graphql/schema/member/has_path.rb +25 -0
  93. data/lib/graphql/schema/member/instrumentation.rb +10 -7
  94. data/lib/graphql/schema/member.rb +2 -0
  95. data/lib/graphql/schema/mutation.rb +6 -48
  96. data/lib/graphql/schema/non_null.rb +5 -1
  97. data/lib/graphql/schema/object.rb +18 -4
  98. data/lib/graphql/schema/printer.rb +1 -1
  99. data/lib/graphql/schema/relay_classic_mutation.rb +42 -9
  100. data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
  101. data/lib/graphql/schema/resolver.rb +45 -20
  102. data/lib/graphql/schema/subscription.rb +97 -0
  103. data/lib/graphql/schema/traversal.rb +11 -7
  104. data/lib/graphql/schema.rb +186 -38
  105. data/lib/graphql/static_validation/all_rules.rb +3 -2
  106. data/lib/graphql/static_validation/base_visitor.rb +199 -0
  107. data/lib/graphql/static_validation/default_visitor.rb +15 -0
  108. data/lib/graphql/static_validation/definition_dependencies.rb +62 -68
  109. data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
  110. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  111. data/lib/graphql/static_validation/literal_validator.rb +54 -11
  112. data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
  113. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +87 -16
  114. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
  115. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +11 -11
  116. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  117. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +52 -8
  118. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
  119. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -15
  120. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  121. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +19 -14
  122. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  123. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +17 -19
  124. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  125. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +30 -14
  126. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  127. data/lib/graphql/static_validation/rules/fields_will_merge.rb +356 -29
  128. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
  129. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +20 -13
  130. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  131. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +37 -29
  132. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  133. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +25 -17
  134. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  135. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +12 -10
  136. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  137. data/lib/graphql/static_validation/rules/fragments_are_named.rb +7 -11
  138. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  139. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +16 -16
  140. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  141. data/lib/graphql/static_validation/rules/fragments_are_used.rb +21 -14
  142. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  143. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +10 -14
  144. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  145. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +30 -30
  146. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  147. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +25 -17
  148. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  149. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +17 -18
  150. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  151. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
  152. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  153. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +10 -14
  154. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  155. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +28 -17
  156. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  157. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +35 -27
  158. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  159. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +15 -14
  160. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  161. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -30
  162. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  163. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +18 -14
  164. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  165. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +73 -65
  166. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  167. data/lib/graphql/static_validation/validation_context.rb +8 -51
  168. data/lib/graphql/static_validation/validator.rb +23 -15
  169. data/lib/graphql/static_validation.rb +5 -3
  170. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
  171. data/lib/graphql/subscriptions/event.rb +28 -5
  172. data/lib/graphql/subscriptions/subscription_root.rb +66 -0
  173. data/lib/graphql/subscriptions.rb +16 -2
  174. data/lib/graphql/tracing/active_support_notifications_tracing.rb +0 -1
  175. data/lib/graphql/tracing/appsignal_tracing.rb +1 -1
  176. data/lib/graphql/tracing/data_dog_tracing.rb +1 -1
  177. data/lib/graphql/tracing/new_relic_tracing.rb +3 -3
  178. data/lib/graphql/tracing/platform_tracing.rb +17 -1
  179. data/lib/graphql/tracing/prometheus_tracing.rb +1 -1
  180. data/lib/graphql/tracing/scout_tracing.rb +1 -1
  181. data/lib/graphql/tracing/skylight_tracing.rb +3 -3
  182. data/lib/graphql/tracing.rb +8 -8
  183. data/lib/graphql/types/float.rb +1 -1
  184. data/lib/graphql/types/int.rb +11 -2
  185. data/lib/graphql/types/iso_8601_date_time.rb +15 -1
  186. data/lib/graphql/types/relay/base_connection.rb +15 -1
  187. data/lib/graphql/types/relay/node.rb +0 -1
  188. data/lib/graphql/types/relay/node_field.rb +43 -0
  189. data/lib/graphql/types/relay/nodes_field.rb +45 -0
  190. data/lib/graphql/types/relay.rb +2 -0
  191. data/lib/graphql/unauthorized_error.rb +4 -0
  192. data/lib/graphql/unauthorized_field_error.rb +23 -0
  193. data/lib/graphql/upgrader/member.rb +5 -0
  194. data/lib/graphql/version.rb +1 -1
  195. data/lib/graphql.rb +6 -1
  196. data/readme.md +7 -7
  197. data/spec/dummy/Gemfile +1 -1
  198. data/spec/dummy/Gemfile.lock +157 -0
  199. data/spec/dummy/app/channels/graphql_channel.rb +22 -11
  200. data/spec/dummy/config/locales/en.yml +1 -1
  201. data/spec/dummy/log/test.log +199 -0
  202. data/spec/dummy/test/test_helper.rb +1 -0
  203. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  204. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
  205. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
  206. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
  207. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
  208. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  209. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
  210. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
  211. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  212. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  213. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
  214. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  215. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
  216. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
  217. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
  218. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
  219. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  220. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
  221. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  222. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  223. data/spec/graphql/analysis/analyze_query_spec.rb +1 -1
  224. data/spec/graphql/analysis/ast/field_usage_spec.rb +51 -0
  225. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +120 -0
  226. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +114 -0
  227. data/spec/graphql/analysis/ast/query_complexity_spec.rb +299 -0
  228. data/spec/graphql/analysis/ast/query_depth_spec.rb +108 -0
  229. data/spec/graphql/analysis/ast_spec.rb +269 -0
  230. data/spec/graphql/authorization_spec.rb +120 -23
  231. data/spec/graphql/base_type_spec.rb +6 -4
  232. data/spec/graphql/enum_type_spec.rb +6 -1
  233. data/spec/graphql/execution/execute_spec.rb +9 -9
  234. data/spec/graphql/execution/instrumentation_spec.rb +19 -0
  235. data/spec/graphql/execution/interpreter_spec.rb +485 -0
  236. data/spec/graphql/execution/lazy_spec.rb +67 -1
  237. data/spec/graphql/execution/lookahead_spec.rb +363 -0
  238. data/spec/graphql/execution/multiplex_spec.rb +31 -3
  239. data/spec/graphql/execution/typecast_spec.rb +20 -20
  240. data/spec/graphql/execution_error_spec.rb +110 -96
  241. data/spec/graphql/field_spec.rb +1 -1
  242. data/spec/graphql/input_object_type_spec.rb +13 -352
  243. data/spec/graphql/int_type_spec.rb +19 -0
  244. data/spec/graphql/interface_type_spec.rb +4 -4
  245. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
  246. data/spec/graphql/introspection/input_value_type_spec.rb +1 -1
  247. data/spec/graphql/introspection/type_type_spec.rb +1 -2
  248. data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
  249. data/spec/graphql/language/lexer_spec.rb +72 -3
  250. data/spec/graphql/language/nodes_spec.rb +20 -0
  251. data/spec/graphql/language/printer_spec.rb +18 -6
  252. data/spec/graphql/language/visitor_spec.rb +320 -14
  253. data/spec/graphql/non_null_type_spec.rb +1 -1
  254. data/spec/graphql/object_type_spec.rb +32 -27
  255. data/spec/graphql/query/arguments_spec.rb +21 -0
  256. data/spec/graphql/query/context_spec.rb +28 -0
  257. data/spec/graphql/query/executor_spec.rb +40 -36
  258. data/spec/graphql/query_spec.rb +12 -6
  259. data/spec/graphql/schema/argument_spec.rb +35 -1
  260. data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
  261. data/spec/graphql/schema/catchall_middleware_spec.rb +16 -15
  262. data/spec/graphql/schema/directive/feature_spec.rb +81 -0
  263. data/spec/graphql/schema/directive/transform_spec.rb +39 -0
  264. data/spec/graphql/schema/enum_spec.rb +12 -3
  265. data/spec/graphql/schema/enum_value_spec.rb +11 -0
  266. data/spec/graphql/schema/field_extension_spec.rb +115 -0
  267. data/spec/graphql/schema/field_spec.rb +47 -7
  268. data/spec/graphql/schema/input_object_spec.rb +95 -0
  269. data/spec/graphql/schema/instrumentation_spec.rb +3 -0
  270. data/spec/graphql/schema/interface_spec.rb +8 -2
  271. data/spec/graphql/schema/introspection_system_spec.rb +9 -1
  272. data/spec/graphql/schema/loader_spec.rb +5 -0
  273. data/spec/graphql/schema/member/accepts_definition_spec.rb +4 -0
  274. data/spec/graphql/schema/member/build_type_spec.rb +46 -0
  275. data/spec/graphql/schema/member/scoped_spec.rb +19 -3
  276. data/spec/graphql/schema/mutation_spec.rb +5 -3
  277. data/spec/graphql/schema/object_spec.rb +9 -1
  278. data/spec/graphql/schema/printer_spec.rb +255 -93
  279. data/spec/graphql/schema/relay_classic_mutation_spec.rb +133 -0
  280. data/spec/graphql/schema/resolver_spec.rb +173 -9
  281. data/spec/graphql/schema/scalar_spec.rb +6 -0
  282. data/spec/graphql/schema/subscription_spec.rb +416 -0
  283. data/spec/graphql/schema/traversal_spec.rb +10 -10
  284. data/spec/graphql/schema/type_expression_spec.rb +2 -2
  285. data/spec/graphql/schema/union_spec.rb +7 -0
  286. data/spec/graphql/schema/validation_spec.rb +1 -1
  287. data/spec/graphql/schema/warden_spec.rb +145 -88
  288. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +213 -73
  289. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
  290. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
  291. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
  292. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
  293. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
  294. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
  295. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +131 -5
  296. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
  297. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
  298. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
  299. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
  300. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
  301. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
  302. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
  303. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
  304. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
  305. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
  306. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
  307. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
  308. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
  309. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
  310. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
  311. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
  312. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +23 -3
  313. data/spec/graphql/static_validation/type_stack_spec.rb +10 -19
  314. data/spec/graphql/static_validation/validator_spec.rb +50 -2
  315. data/spec/graphql/subscriptions_spec.rb +27 -16
  316. data/spec/graphql/tracing/new_relic_tracing_spec.rb +16 -0
  317. data/spec/graphql/tracing/platform_tracing_spec.rb +59 -37
  318. data/spec/graphql/tracing/prometheus_tracing_spec.rb +3 -0
  319. data/spec/graphql/tracing/skylight_tracing_spec.rb +16 -0
  320. data/spec/graphql/types/iso_8601_date_time_spec.rb +29 -2
  321. data/spec/graphql/union_type_spec.rb +2 -2
  322. data/spec/graphql/upgrader/member_spec.rb +67 -0
  323. data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +11 -22
  324. data/spec/integration/mongoid/spec_helper.rb +2 -0
  325. data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
  326. data/spec/{support → integration/mongoid}/star_trek/schema.rb +56 -34
  327. data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
  328. data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
  329. data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
  330. data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +1 -1
  331. data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
  332. data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
  333. data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
  334. data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
  335. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +28 -0
  336. data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
  337. data/spec/integration/rails/graphql/input_object_type_spec.rb +364 -0
  338. data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +7 -7
  339. data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +9 -9
  340. data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +11 -3
  341. data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +19 -22
  342. data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +16 -0
  343. data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
  344. data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
  345. data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +48 -0
  346. data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
  347. data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +22 -22
  348. data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +4 -4
  349. data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +56 -27
  350. data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +15 -11
  351. data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +16 -9
  352. data/spec/integration/rails/spec_helper.rb +25 -0
  353. data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
  354. data/spec/spec_helper.rb +23 -39
  355. data/spec/support/dummy/data.rb +20 -17
  356. data/spec/support/dummy/schema.rb +315 -305
  357. data/spec/support/error_bubbling_helpers.rb +23 -0
  358. data/spec/support/jazz.rb +213 -46
  359. data/spec/support/lazy_helpers.rb +69 -27
  360. data/spec/support/new_relic.rb +3 -0
  361. data/spec/support/skylight.rb +3 -0
  362. data/spec/support/star_wars/schema.rb +131 -81
  363. data/spec/support/static_validation_helpers.rb +9 -5
  364. metadata +418 -261
  365. data/lib/graphql/language/comments.rb +0 -45
  366. data/lib/graphql/static_validation/arguments_validator.rb +0 -50
  367. data/spec/graphql/schema/member/has_fields_spec.rb +0 -129
  368. data/spec/rails_dependency_sanity_spec.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2aa5dc86bfb37cc0c46b7974618bddc91b203b0
4
- data.tar.gz: 92979d239d0fbd9a010261dec5d0b1285c617c3f
3
+ metadata.gz: fb79bf185d3d89d53f50ad5f0ae1cc93e3480acb
4
+ data.tar.gz: 46c04d4e296ea2b3b520d6df50f82d76da5ec641
5
5
  SHA512:
6
- metadata.gz: 26ccb7f54465c14158a933a4bbc52eaba9576725ea06ce1a5425128fd39ad133013383ffa650bc6bbbdf16030bf232ab021da6a1c39ee20933d294b49d5d8d57
7
- data.tar.gz: 7ec6717d6a3cf091189269e92d991cd49fdec20802d68cb7c83d60b9ab615535ad626c8163a5022e713f4c9f875bfaec1430b51098ec3e55eca5e91ff6e1a622
6
+ metadata.gz: 78e070c3df4abd9e2d649ba0e5f1e7fdcef9b0241572a30bf233d516fa28b7eee9afa0fd2d650db835556dff87f4eddb344aefce8825019569aa7e55ff28f780
7
+ data.tar.gz: eb138cb5d2274c815ea42ec2eff4371cf34023ad817e4009302cb6de6da7deea213ccfaa2169d86a6a8c2b684f9e4fc8bd0780060163a764960d22af1a48bb25
@@ -17,6 +17,7 @@ module Graphql
17
17
  # - base_input_object.rb
18
18
  # - base_interface.rb
19
19
  # - base_object.rb
20
+ # - base_scalar.rb
20
21
  # - base_union.rb
21
22
  # - query_type.rb
22
23
  # - loaders/
@@ -92,7 +93,7 @@ module Graphql
92
93
  create_dir("#{options[:directory]}/types")
93
94
  template("schema.erb", schema_file_path)
94
95
 
95
- ["base_object", "base_enum", "base_input_object", "base_interface", "base_union"].each do |base_type|
96
+ ["base_object", "base_enum", "base_input_object", "base_interface", "base_scalar", "base_union"].each do |base_type|
96
97
  template("#{base_type}.erb", "#{options[:directory]}/types/#{base_type}.rb")
97
98
  end
98
99
 
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'generators/graphql/type_generator'
3
+
4
+ module Graphql
5
+ module Generators
6
+ # Generate a scalar type by given name.
7
+ #
8
+ # ```
9
+ # rails g graphql:scalar Date
10
+ # ```
11
+ class ScalarGenerator < TypeGeneratorBase
12
+ desc "Create a GraphQL::ScalarType with the given name"
13
+ source_root File.expand_path('../templates', __FILE__)
14
+
15
+ def create_type_file
16
+ template "scalar.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module Types
2
+ class BaseScalar < GraphQL::Schema::Scalar
3
+ end
4
+ end
@@ -0,0 +1,13 @@
1
+ module Types
2
+ class <%= type_ruby_name.split('::')[-1] %> < Types::BaseScalar
3
+ def self.coerce_input(input_value, context)
4
+ # Override this to prepare a client-provided GraphQL value for your Ruby code
5
+ input_value
6
+ end
7
+
8
+ def self.coerce_result(ruby_value, context)
9
+ # Override this to serialize a Ruby value for the GraphQL response
10
+ ruby_value.to_s
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Analysis
4
+ module AST
5
+ # Query analyzer for query ASTs. Query analyzers respond to visitor style methods
6
+ # but are prefixed by `enter` and `leave`.
7
+ #
8
+ # @param [GraphQL::Query] The query to analyze
9
+ class Analyzer
10
+ def initialize(query)
11
+ @query = query
12
+ end
13
+
14
+ # Analyzer hook to decide at analysis time whether a query should
15
+ # be analyzed or not.
16
+ # @return [Boolean] If the query should be analyzed or not
17
+ def analyze?
18
+ true
19
+ end
20
+
21
+ # The result for this analyzer. Returning {GraphQL::AnalysisError} results
22
+ # in a query error.
23
+ # @return [Any] The analyzer result
24
+ def result
25
+ raise NotImplementedError
26
+ end
27
+
28
+ # Don't use make_visit_method because it breaks `super`
29
+ def self.build_visitor_hooks(member_name)
30
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
31
+ def on_enter_#{member_name}(node, parent, visitor)
32
+ end
33
+
34
+ def on_leave_#{member_name}(node, parent, visitor)
35
+ end
36
+ EOS
37
+ end
38
+
39
+ build_visitor_hooks :argument
40
+ build_visitor_hooks :directive
41
+ build_visitor_hooks :document
42
+ build_visitor_hooks :enum
43
+ build_visitor_hooks :field
44
+ build_visitor_hooks :fragment_spread
45
+ build_visitor_hooks :inline_fragment
46
+ build_visitor_hooks :input_object
47
+ build_visitor_hooks :list_type
48
+ build_visitor_hooks :non_null_type
49
+ build_visitor_hooks :null_value
50
+ build_visitor_hooks :operation_definition
51
+ build_visitor_hooks :type_name
52
+ build_visitor_hooks :variable_definition
53
+ build_visitor_hooks :variable_identifier
54
+ build_visitor_hooks :abstract_node
55
+
56
+ protected
57
+
58
+ attr_reader :query
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Analysis
4
+ module AST
5
+ class FieldUsage < Analyzer
6
+ def initialize(query)
7
+ super
8
+ @used_fields = Set.new
9
+ @used_deprecated_fields = Set.new
10
+ end
11
+
12
+ def on_leave_field(parent, node, visitor)
13
+ field_defn = visitor.field_definition
14
+ field = "#{visitor.parent_type_definition.name}.#{field_defn.name}"
15
+ @used_fields << field
16
+ @used_deprecated_fields << field if field_defn.deprecation_reason
17
+ end
18
+
19
+ def result
20
+ {
21
+ used_fields: @used_fields.to_a,
22
+ used_deprecated_fields: @used_deprecated_fields.to_a
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./query_complexity"
3
+ module GraphQL
4
+ module Analysis
5
+ module AST
6
+ # Used under the hood to implement complexity validation,
7
+ # see {Schema#max_complexity} and {Query#max_complexity}
8
+ class MaxQueryComplexity < QueryComplexity
9
+ def result
10
+ return if query.max_complexity.nil?
11
+
12
+ total_complexity = super
13
+
14
+ if total_complexity > query.max_complexity
15
+ GraphQL::AnalysisError.new("Query has complexity of #{total_complexity}, which exceeds max complexity of #{query.max_complexity}")
16
+ else
17
+ nil
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Analysis
4
+ module AST
5
+ class MaxQueryDepth < QueryDepth
6
+ def result
7
+ return unless query.max_depth
8
+
9
+ if @max_depth > query.max_depth
10
+ GraphQL::AnalysisError.new("Query has depth of #{@max_depth}, which exceeds max depth of #{query.max_depth}")
11
+ else
12
+ nil
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Analysis
4
+ # Calculate the complexity of a query, using {Field#complexity} values.
5
+ module AST
6
+ class QueryComplexity < Analyzer
7
+ # State for the query complexity calcuation:
8
+ # - `complexities_on_type` holds complexity scores for each type in an IRep node
9
+ def initialize(query)
10
+ super
11
+ @complexities_on_type = [TypeComplexity.new]
12
+ end
13
+
14
+ # Overide this method to use the complexity result
15
+ def result
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def on_enter_field(node, parent, visitor)
20
+ # We don't want to visit fragment definitions,
21
+ # we'll visit them when we hit the spreads instead
22
+ return if visitor.visiting_fragment_definition?
23
+ return if visitor.skipping?
24
+
25
+ @complexities_on_type.push(TypeComplexity.new)
26
+ end
27
+
28
+ def on_leave_field(node, parent, visitor)
29
+ # We don't want to visit fragment definitions,
30
+ # we'll visit them when we hit the spreads instead
31
+ return if visitor.visiting_fragment_definition?
32
+ return if visitor.skipping?
33
+
34
+ type_complexities = @complexities_on_type.pop
35
+ child_complexity = type_complexities.max_possible_complexity
36
+ own_complexity = get_complexity(node, visitor.field_definition, child_complexity, visitor)
37
+
38
+ parent_type = visitor.parent_type_definition
39
+ possible_types = if parent_type.kind.abstract?
40
+ query.possible_types(parent_type)
41
+ else
42
+ [parent_type]
43
+ end
44
+
45
+ key = selection_key(visitor.response_path, visitor.query)
46
+
47
+ possible_types.each do |type|
48
+ @complexities_on_type.last.merge(type, key, own_complexity)
49
+ end
50
+ end
51
+
52
+ def on_enter_fragment_spread(node, _, visitor)
53
+ visitor.enter_fragment_spread_inline(node)
54
+ end
55
+
56
+ def on_leave_fragment_spread(node, _, visitor)
57
+ visitor.leave_fragment_spread_inline(node)
58
+ end
59
+
60
+ def result
61
+ @complexities_on_type.last.max_possible_complexity
62
+ end
63
+
64
+ private
65
+
66
+ def selection_key(response_path, query)
67
+ # We add the query object id to support multiplex queries
68
+ # even if they have the same response path, they should
69
+ # always be added.
70
+ response_path.join(".") + "-#{query.object_id}"
71
+ end
72
+
73
+ # Get a complexity value for a field,
74
+ # by getting the number or calling its proc
75
+ def get_complexity(ast_node, field_defn, child_complexity, visitor)
76
+ # Return if we've visited this response path before (not counting duplicates)
77
+ defined_complexity = field_defn.complexity
78
+
79
+ arguments = visitor.arguments_for(ast_node, field_defn)
80
+
81
+ case defined_complexity
82
+ when Proc
83
+ defined_complexity.call(query.context, arguments, child_complexity)
84
+ when Numeric
85
+ defined_complexity + (child_complexity || 0)
86
+ else
87
+ raise("Invalid complexity: #{defined_complexity.inspect} on #{field_defn.name}")
88
+ end
89
+ end
90
+
91
+ # Selections on an object may apply differently depending on what is _actually_ returned by the resolve function.
92
+ # Find the maximum possible complexity among those combinations.
93
+ class TypeComplexity
94
+ def initialize
95
+ @types = Hash.new { |h, k| h[k] = {} }
96
+ end
97
+
98
+ # Return the max possible complexity for types in this selection
99
+ def max_possible_complexity
100
+ @types.map do |type, fields|
101
+ fields.values.inject(:+)
102
+ end.max
103
+ end
104
+
105
+ # Store the complexity for the branch on `type_defn`.
106
+ # Later we will see if this is the max complexity among branches.
107
+ def merge(type_defn, key, complexity)
108
+ @types[type_defn][key] = complexity
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Analysis
4
+ # A query reducer for measuring the depth of a given query.
5
+ #
6
+ # @example Logging the depth of a query
7
+ # class LogQueryDepth < GraphQL::Analysis::QueryDepth
8
+ # def on_analysis_end
9
+ # log("GraphQL query depth: #{@max_depth}")
10
+ # end
11
+ # end
12
+ #
13
+ # Schema.execute(query_str)
14
+ # # GraphQL query depth: 8
15
+ #
16
+ module AST
17
+ class QueryDepth < Analyzer
18
+ def initialize(query)
19
+ @max_depth = 0
20
+ @current_depth = 0
21
+ @skip_depth = 0
22
+ super
23
+ end
24
+
25
+ def on_enter_field(node, parent, visitor)
26
+ return if visitor.skipping? || visitor.visiting_fragment_definition?
27
+
28
+ # Don't validate introspection fields or skipped nodes
29
+ if GraphQL::Schema::DYNAMIC_FIELDS.include?(visitor.field_definition.name)
30
+ @skip_depth += 1
31
+ elsif @skip_depth > 0
32
+ # we're inside an introspection query or skipped node
33
+ else
34
+ @current_depth += 1
35
+ end
36
+ end
37
+
38
+ def on_leave_field(node, parent, visitor)
39
+ return if visitor.skipping? || visitor.visiting_fragment_definition?
40
+
41
+ # Don't validate introspection fields or skipped nodes
42
+ if GraphQL::Schema::DYNAMIC_FIELDS.include?(visitor.field_definition.name)
43
+ @skip_depth -= 1
44
+ else
45
+ if @max_depth < @current_depth
46
+ @max_depth = @current_depth
47
+ end
48
+ @current_depth -= 1
49
+ end
50
+ end
51
+
52
+ def on_enter_fragment_spread(node, _, visitor)
53
+ visitor.enter_fragment_spread_inline(node)
54
+ end
55
+
56
+ def on_leave_fragment_spread(node, _, visitor)
57
+ visitor.leave_fragment_spread_inline(node)
58
+ end
59
+
60
+ def result
61
+ @max_depth
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Analysis
4
+ module AST
5
+ # Depth first traversal through a query AST, calling AST analyzers
6
+ # along the way.
7
+ #
8
+ # The visitor is a special case of GraphQL::Language::Visitor, visiting
9
+ # only the selected operation, providing helpers for common use cases such
10
+ # as skipped fields and visiting fragment spreads.
11
+ #
12
+ # @see {GraphQL::Analysis::AST::Analyzer} AST Analyzers for queries
13
+ class Visitor < GraphQL::Language::Visitor
14
+ def initialize(query:, analyzers:)
15
+ @analyzers = analyzers
16
+ @path = []
17
+ @object_types = []
18
+ @directives = []
19
+ @field_definitions = []
20
+ @argument_definitions = []
21
+ @directive_definitions = []
22
+ @query = query
23
+ @schema = query.schema
24
+ @response_path = []
25
+ @skip_stack = [false]
26
+ super(query.selected_operation)
27
+ end
28
+
29
+ # @return [GraphQL::Query] the query being visited
30
+ attr_reader :query
31
+
32
+ # @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
33
+ attr_reader :object_types
34
+
35
+ def visit
36
+ return unless @document
37
+ super
38
+ end
39
+
40
+ # Visit Helpers
41
+
42
+ # @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
43
+ # @see {GraphQL::Query#arguments_for}
44
+ def arguments_for(ast_node, field_definition)
45
+ @query.arguments_for(ast_node, field_definition)
46
+ end
47
+
48
+ # @return [Boolean] If the visitor is currently inside a fragment definition
49
+ def visiting_fragment_definition?
50
+ @in_fragment_def
51
+ end
52
+
53
+ # @return [Boolean] If the current node should be skipped because of a skip or include directive
54
+ def skipping?
55
+ @skipping
56
+ end
57
+
58
+ # @return [Array<String>] The path to the response key for the current field
59
+ def response_path
60
+ @response_path.dup
61
+ end
62
+
63
+ # Visitor Hooks
64
+
65
+ def on_operation_definition(node, parent)
66
+ object_type = @schema.root_type_for_operation(node.operation_type)
67
+ @object_types.push(object_type)
68
+ @path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
69
+ call_analyzers(:on_enter_operation_definition, node, parent)
70
+ super
71
+ call_analyzers(:on_leave_operation_definition, node, parent)
72
+ @object_types.pop
73
+ @path.pop
74
+ end
75
+
76
+ def on_fragment_definition(node, parent)
77
+ on_fragment_with_type(node) do
78
+ @path.push("fragment #{node.name}")
79
+ @in_fragment_def = false
80
+ call_analyzers(:on_enter_fragment_definition, node, parent)
81
+ super
82
+ @in_fragment_def = false
83
+ call_analyzers(:on_leave_fragment_definition, node, parent)
84
+ end
85
+ end
86
+
87
+ def on_inline_fragment(node, parent)
88
+ on_fragment_with_type(node) do
89
+ @path.push("...#{node.type ? " on #{node.type.name}" : ""}")
90
+ call_analyzers(:on_enter_inline_fragment, node, parent)
91
+ super
92
+ call_analyzers(:on_leave_inline_fragment, node, parent)
93
+ end
94
+ end
95
+
96
+ def on_field(node, parent)
97
+ @response_path.push(node.alias || node.name)
98
+ parent_type = @object_types.last
99
+ field_definition = @schema.get_field(parent_type, node.name)
100
+ @field_definitions.push(field_definition)
101
+ if !field_definition.nil?
102
+ next_object_type = field_definition.type.unwrap
103
+ @object_types.push(next_object_type)
104
+ else
105
+ @object_types.push(nil)
106
+ end
107
+ @path.push(node.alias || node.name)
108
+
109
+ @skipping = @skip_stack.last || skip?(node)
110
+ @skip_stack << @skipping
111
+
112
+ call_analyzers(:on_enter_field, node, parent)
113
+ super
114
+
115
+ @skipping = @skip_stack.pop
116
+
117
+ call_analyzers(:on_leave_field, node, parent)
118
+ @response_path.pop
119
+ @field_definitions.pop
120
+ @object_types.pop
121
+ @path.pop
122
+ end
123
+
124
+ def on_directive(node, parent)
125
+ directive_defn = @schema.directives[node.name]
126
+ @directive_definitions.push(directive_defn)
127
+ call_analyzers(:on_enter_directive, node, parent)
128
+ super
129
+ call_analyzers(:on_leave_directive, node, parent)
130
+ @directive_definitions.pop
131
+ end
132
+
133
+ def on_argument(node, parent)
134
+ argument_defn = if (arg = @argument_definitions.last)
135
+ arg_type = arg.type.unwrap
136
+ if arg_type.kind.input_object?
137
+ arg_type.input_fields[node.name]
138
+ else
139
+ nil
140
+ end
141
+ elsif (directive_defn = @directive_definitions.last)
142
+ directive_defn.arguments[node.name]
143
+ elsif (field_defn = @field_definitions.last)
144
+ field_defn.arguments[node.name]
145
+ else
146
+ nil
147
+ end
148
+
149
+ @argument_definitions.push(argument_defn)
150
+ @path.push(node.name)
151
+ call_analyzers(:on_enter_argument, node, parent)
152
+ super
153
+ call_analyzers(:on_leave_argument, node, parent)
154
+ @argument_definitions.pop
155
+ @path.pop
156
+ end
157
+
158
+ def on_fragment_spread(node, parent)
159
+ @path.push("... #{node.name}")
160
+ call_analyzers(:on_enter_fragment_spread, node, parent)
161
+ super
162
+ call_analyzers(:on_leave_fragment_spread, node, parent)
163
+ @path.pop
164
+ end
165
+
166
+ def on_abstract_node(node, parent)
167
+ call_analyzers(:on_enter_abstract_node, node, parent)
168
+ super
169
+ call_analyzers(:on_leave_abstract_node, node, parent)
170
+ end
171
+
172
+ # Visit a fragment spread inline instead of visiting the definition
173
+ # by itself.
174
+ def enter_fragment_spread_inline(fragment_spread)
175
+ fragment_def = query.fragments[fragment_spread.name]
176
+
177
+ object_type = if fragment_def.type
178
+ query.schema.types.fetch(fragment_def.type.name, nil)
179
+ else
180
+ object_types.last
181
+ end
182
+
183
+ object_types << object_type
184
+
185
+ fragment_def.selections.each do |selection|
186
+ visit_node(selection, fragment_def)
187
+ end
188
+ end
189
+
190
+ # Visit a fragment spread inline instead of visiting the definition
191
+ # by itself.
192
+ def leave_fragment_spread_inline(_fragment_spread)
193
+ object_types.pop
194
+ end
195
+
196
+ # @return [GraphQL::BaseType] The current object type
197
+ def type_definition
198
+ @object_types.last
199
+ end
200
+
201
+ # @return [GraphQL::BaseType] The type which the current type came from
202
+ def parent_type_definition
203
+ @object_types[-2]
204
+ end
205
+
206
+ # @return [GraphQL::Field, nil] The most-recently-entered GraphQL::Field, if currently inside one
207
+ def field_definition
208
+ @field_definitions.last
209
+ end
210
+
211
+ # @return [GraphQL::Field, nil] The GraphQL field which returned the object that the current field belongs to
212
+ def previous_field_definition
213
+ @field_definitions[-2]
214
+ end
215
+
216
+ # @return [GraphQL::Directive, nil] The most-recently-entered GraphQL::Directive, if currently inside one
217
+ def directive_definition
218
+ @directive_definitions.last
219
+ end
220
+
221
+ # @return [GraphQL::Argument, nil] The most-recently-entered GraphQL::Argument, if currently inside one
222
+ def argument_definition
223
+ # Don't get the _last_ one because that's the current one.
224
+ # Get the second-to-last one, which is the parent of the current one.
225
+ @argument_definitions[-2]
226
+ end
227
+
228
+ private
229
+
230
+ def skip?(ast_node)
231
+ dir = ast_node.directives
232
+ dir.any? && !GraphQL::Execution::DirectiveChecks.include?(dir, query)
233
+ end
234
+
235
+ def call_analyzers(method, node, parent)
236
+ @analyzers.each do |analyzer|
237
+ analyzer.public_send(method, node, parent, self)
238
+ end
239
+ end
240
+
241
+ def on_fragment_with_type(node)
242
+ object_type = if node.type
243
+ @schema.types.fetch(node.type.name, nil)
244
+ else
245
+ @object_types.last
246
+ end
247
+ @object_types.push(object_type)
248
+ yield(node)
249
+ @object_types.pop
250
+ @path.pop
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end