graphql 1.8.7 → 1.9.0

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