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
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class RequiredArgumentsArePresentError < StaticValidation::Error
5
+ attr_reader :class_name
6
+ attr_reader :name
7
+ attr_reader :arguments
8
+
9
+ def initialize(message, path: nil, nodes: [], class_name:, name:, arguments:)
10
+ super(message, path: path, nodes: nodes)
11
+ @class_name = class_name
12
+ @name = name
13
+ @arguments = arguments
14
+ end
15
+
16
+ # A hash representation of this Message
17
+ def to_h
18
+ extensions = {
19
+ "code" => code,
20
+ "className" => class_name,
21
+ "name" => name,
22
+ "arguments" => arguments
23
+ }
24
+
25
+ super.merge({
26
+ "extensions" => extensions
27
+ })
28
+ end
29
+
30
+ def code
31
+ "missingRequiredArguments"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ module RequiredInputObjectAttributesArePresent
5
+ def on_input_object(node, parent)
6
+ if parent.is_a? GraphQL::Language::Nodes::Argument
7
+ validate_input_object(node, context, parent)
8
+ end
9
+ super
10
+ end
11
+
12
+ private
13
+
14
+ def get_parent_type(context, parent)
15
+ defn = context.field_definition
16
+ parent_type = context.warden.arguments(defn)
17
+ .find{|f| f.name == parent_name(parent, defn) }
18
+ parent_type ? parent_type.type.unwrap : nil
19
+ end
20
+
21
+ def validate_input_object(ast_node, context, parent)
22
+ parent_type = get_parent_type(context, parent)
23
+ return unless parent_type && parent_type.kind.input_object?
24
+
25
+ required_fields = parent_type.arguments
26
+ .select{|k,v| v.type.kind.non_null?}
27
+ .keys
28
+
29
+ present_fields = ast_node.arguments.map(&:name)
30
+ missing_fields = required_fields - present_fields
31
+
32
+ missing_fields.each do |missing_field|
33
+ path = [*context.path, missing_field]
34
+ missing_field_type = parent_type.arguments[missing_field].type
35
+ add_error(RequiredInputObjectAttributesArePresentError.new(
36
+ "Argument '#{missing_field}' on InputObject '#{parent_type}' is required. Expected type #{missing_field_type}",
37
+ argument_name: missing_field,
38
+ argument_type: missing_field_type.to_s,
39
+ input_object_type: parent_type.to_s,
40
+ path: path,
41
+ nodes: ast_node,
42
+ ))
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class RequiredInputObjectAttributesArePresentError < StaticValidation::Error
5
+ attr_reader :argument_type
6
+ attr_reader :argument_name
7
+ attr_reader :input_object_type
8
+
9
+ def initialize(message, path:, nodes:, argument_type:, argument_name:, input_object_type:)
10
+ super(message, path: path, nodes: nodes)
11
+ @argument_type = argument_type
12
+ @argument_name = argument_name
13
+ @input_object_type = input_object_type
14
+ end
15
+
16
+ # A hash representation of this Message
17
+ def to_h
18
+ extensions = {
19
+ "code" => code,
20
+ "argumentName" => argument_name,
21
+ "argumentType" => argument_type,
22
+ "inputObjectType" => input_object_type,
23
+ }
24
+
25
+ super.merge({
26
+ "extensions" => extensions
27
+ })
28
+ end
29
+
30
+ def code
31
+ "missingRequiredInputObjectAttribute"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,20 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class SubscriptionRootExists
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- return if context.warden.root_type_for_operation("subscription")
9
-
10
- visitor = context.visitor
11
-
12
- visitor[GraphQL::Language::Nodes::OperationDefinition].enter << ->(ast_node, prev_ast_node) {
13
- if ast_node.operation_type == 'subscription'
14
- context.errors << message('Schema is not configured for subscriptions', ast_node, context: context)
15
- return GraphQL::Language::Visitor::SKIP
16
- end
17
- }
4
+ module SubscriptionRootExists
5
+ def on_operation_definition(node, _parent)
6
+ if node.operation_type == "subscription" && context.warden.root_type_for_operation("subscription").nil?
7
+ add_error(GraphQL::StaticValidation::SubscriptionRootExistsError.new(
8
+ 'Schema is not configured for subscriptions',
9
+ nodes: node
10
+ ))
11
+ else
12
+ super
13
+ end
18
14
  end
19
15
  end
20
16
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class SubscriptionRootExistsError < StaticValidation::Error
5
+
6
+ def initialize(message, path: nil, nodes: [])
7
+ super(message, path: path, nodes: nodes)
8
+ end
9
+
10
+ # A hash representation of this Message
11
+ def to_h
12
+ extensions = {
13
+ "code" => code,
14
+ }
15
+
16
+ super.merge({
17
+ "extensions" => extensions
18
+ })
19
+ end
20
+
21
+ def code
22
+ "missingSubscriptionConfiguration"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,34 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class UniqueDirectivesPerLocation
5
- include GraphQL::StaticValidation::Message::MessageHelper
4
+ module UniqueDirectivesPerLocation
5
+ DIRECTIVE_NODE_HOOKS = [
6
+ :on_fragment_definition,
7
+ :on_fragment_spread,
8
+ :on_inline_fragment,
9
+ :on_operation_definition,
10
+ :on_scalar_type_definition,
11
+ :on_object_type_definition,
12
+ :on_input_value_definition,
13
+ :on_field_definition,
14
+ :on_interface_type_definition,
15
+ :on_union_type_definition,
16
+ :on_enum_type_definition,
17
+ :on_enum_value_definition,
18
+ :on_input_object_type_definition,
19
+ :on_field,
20
+ ]
6
21
 
7
- NODES_WITH_DIRECTIVES = GraphQL::Language::Nodes.constants
8
- .map{|c| GraphQL::Language::Nodes.const_get(c)}
9
- .select{|c| c.is_a?(Class) && c.instance_methods.include?(:directives)}
10
-
11
- def validate(context)
12
- NODES_WITH_DIRECTIVES.each do |node_class|
13
- context.visitor[node_class] << ->(node, _) {
14
- validate_directives(node, context) unless node.directives.empty?
15
- }
22
+ DIRECTIVE_NODE_HOOKS.each do |method_name|
23
+ define_method(method_name) do |node, parent|
24
+ if node.directives.any?
25
+ validate_directive_location(node)
26
+ end
27
+ super(node, parent)
16
28
  end
17
29
  end
18
30
 
19
31
  private
20
32
 
21
- def validate_directives(node, context)
33
+ def validate_directive_location(node)
22
34
  used_directives = {}
23
-
24
35
  node.directives.each do |ast_directive|
25
36
  directive_name = ast_directive.name
26
37
  if used_directives[directive_name]
27
- context.errors << message(
38
+ add_error(GraphQL::StaticValidation::UniqueDirectivesPerLocationError.new(
28
39
  "The directive \"#{directive_name}\" can only be used once at this location.",
29
- [used_directives[directive_name], ast_directive],
30
- context: context
31
- )
40
+ nodes: [used_directives[directive_name], ast_directive],
41
+ directive: directive_name,
42
+ ))
32
43
  else
33
44
  used_directives[directive_name] = ast_directive
34
45
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class UniqueDirectivesPerLocationError < StaticValidation::Error
5
+ attr_reader :directive_name
6
+
7
+ def initialize(message, path: nil, nodes: [], directive:)
8
+ super(message, path: path, nodes: nodes)
9
+ @directive_name = directive
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "directiveName" => directive_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "directiveNotUniqueForLocation"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,38 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class VariableDefaultValuesAreCorrectlyTyped
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- context.visitor[GraphQL::Language::Nodes::VariableDefinition] << ->(node, parent) {
9
- if !node.default_value.nil?
10
- validate_default_value(node, context)
11
- end
12
- }
13
- end
14
-
15
- def validate_default_value(node, context)
16
- value = node.default_value
17
- if node.type.is_a?(GraphQL::Language::Nodes::NonNullType)
18
- context.errors << message("Non-null variable $#{node.name} can't have a default value", node, context: context)
19
- else
20
- type = context.schema.type_from_ast(node.type)
21
- if type.nil?
22
- # This is handled by another validator
4
+ module VariableDefaultValuesAreCorrectlyTyped
5
+ def on_variable_definition(node, parent)
6
+ if !node.default_value.nil?
7
+ value = node.default_value
8
+ if node.type.is_a?(GraphQL::Language::Nodes::NonNullType)
9
+ add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
10
+ "Non-null variable $#{node.name} can't have a default value",
11
+ nodes: node,
12
+ name: node.name,
13
+ error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_ON_NON_NULL]
14
+ ))
23
15
  else
24
- begin
25
- valid = context.valid_literal?(value, type)
26
- rescue GraphQL::CoercionError => err
27
- error_message = err.message
28
- end
16
+ type = context.schema.type_from_ast(node.type)
17
+ if type.nil?
18
+ # This is handled by another validator
19
+ else
20
+ begin
21
+ valid = context.valid_literal?(value, type)
22
+ rescue GraphQL::CoercionError => err
23
+ error_message = err.message
24
+ rescue GraphQL::LiteralValidationError
25
+ # noop, we just want to stop any LiteralValidationError from propagating
26
+ end
29
27
 
30
- if !valid
31
- error_message ||= "Default value for $#{node.name} doesn't match type #{type}"
32
- context.errors << message(error_message, node, context: context)
28
+ if !valid
29
+ error_message ||= "Default value for $#{node.name} doesn't match type #{type}"
30
+ VariableDefaultValuesAreCorrectlyTypedError
31
+ add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
32
+ error_message,
33
+ nodes: node,
34
+ name: node.name,
35
+ type: type.to_s,
36
+ error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE]
37
+ ))
38
+ end
33
39
  end
34
40
  end
35
41
  end
42
+
43
+ super
36
44
  end
37
45
  end
38
46
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class VariableDefaultValuesAreCorrectlyTypedError < StaticValidation::Error
5
+ attr_reader :variable_name
6
+ attr_reader :type_name
7
+ attr_reader :violation
8
+
9
+ VIOLATIONS = {
10
+ :INVALID_TYPE => "defaultValueInvalidType",
11
+ :INVALID_ON_NON_NULL => "defaultValueInvalidOnNonNullVariable",
12
+ }
13
+
14
+ def initialize(message, path: nil, nodes: [], name:, type: nil, error_type:)
15
+ super(message, path: path, nodes: nodes)
16
+ @variable_name = name
17
+ @type_name = type
18
+ raise("Unexpected error type: #{error_type}") if !VIOLATIONS.values.include?(error_type)
19
+ @violation = error_type
20
+ end
21
+
22
+ # A hash representation of this Message
23
+ def to_h
24
+ extensions = {
25
+ "code" => code,
26
+ "variableName" => variable_name
27
+ }.tap { |h| h["typeName"] = type_name unless type_name.nil? }
28
+
29
+ super.merge({
30
+ "extensions" => extensions
31
+ })
32
+ end
33
+
34
+ def code
35
+ @violation
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,22 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class VariableNamesAreUnique
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- context.visitor[GraphQL::Language::Nodes::OperationDefinition] << ->(node, parent) {
9
- var_defns = node.variables
10
- if var_defns.any?
11
- vars_by_name = Hash.new { |h, k| h[k] = [] }
12
- var_defns.each { |v| vars_by_name[v.name] << v }
13
- vars_by_name.each do |name, defns|
14
- if defns.size > 1
15
- context.errors << message("There can only be one variable named \"#{name}\"", defns, context: context)
16
- end
4
+ module VariableNamesAreUnique
5
+ def on_operation_definition(node, parent)
6
+ var_defns = node.variables
7
+ if var_defns.any?
8
+ vars_by_name = Hash.new { |h, k| h[k] = [] }
9
+ var_defns.each { |v| vars_by_name[v.name] << v }
10
+ vars_by_name.each do |name, defns|
11
+ if defns.size > 1
12
+ add_error(GraphQL::StaticValidation::VariableNamesAreUniqueError.new(
13
+ "There can only be one variable named \"#{name}\"",
14
+ nodes: defns,
15
+ name: name
16
+ ))
17
17
  end
18
18
  end
19
- }
19
+ end
20
+ super
20
21
  end
21
22
  end
22
23
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class VariableNamesAreUniqueError < StaticValidation::Error
5
+ attr_reader :variable_name
6
+
7
+ def initialize(message, path: nil, nodes: [], name:)
8
+ super(message, path: path, nodes: nodes)
9
+ @variable_name = name
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "variableName" => variable_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "variableNotUnique"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,53 +1,57 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class VariableUsagesAreAllowed
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
4
+ module VariableUsagesAreAllowed
5
+ def initialize(*)
6
+ super
8
7
  # holds { name => ast_node } pairs
9
- declared_variables = {}
10
- context.visitor[GraphQL::Language::Nodes::OperationDefinition] << ->(node, parent) {
11
- declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = var }
12
- }
13
-
14
- context.visitor[GraphQL::Language::Nodes::Argument] << ->(node, parent) {
15
- node_values = if node.value.is_a?(Array)
16
- node.value
17
- else
18
- [node.value]
19
- end
20
- node_values = node_values.select { |value| value.is_a? GraphQL::Language::Nodes::VariableIdentifier }
8
+ @declared_variables = {}
9
+ end
21
10
 
22
- return if node_values.none?
11
+ def on_operation_definition(node, parent)
12
+ @declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = var }
13
+ super
14
+ end
23
15
 
24
- arguments = nil
25
- case parent
16
+ def on_argument(node, parent)
17
+ node_values = if node.value.is_a?(Array)
18
+ node.value
19
+ else
20
+ [node.value]
21
+ end
22
+ node_values = node_values.select { |value| value.is_a? GraphQL::Language::Nodes::VariableIdentifier }
23
+
24
+ if node_values.any?
25
+ arguments = case parent
26
26
  when GraphQL::Language::Nodes::Field
27
- arguments = context.field_definition.arguments
27
+ context.field_definition.arguments
28
28
  when GraphQL::Language::Nodes::Directive
29
- arguments = context.directive_definition.arguments
29
+ context.directive_definition.arguments
30
30
  when GraphQL::Language::Nodes::InputObject
31
31
  arg_type = context.argument_definition.type.unwrap
32
32
  if arg_type.is_a?(GraphQL::InputObjectType)
33
33
  arguments = arg_type.input_fields
34
+ else
35
+ # This is some kind of error
36
+ nil
34
37
  end
35
38
  else
36
39
  raise("Unexpected argument parent: #{parent}")
37
40
  end
38
41
 
39
42
  node_values.each do |node_value|
40
- var_defn_ast = declared_variables[node_value.name]
43
+ var_defn_ast = @declared_variables[node_value.name]
41
44
  # Might be undefined :(
42
45
  # VariablesAreUsedAndDefined can't finalize its search until the end of the document.
43
- var_defn_ast && arguments && validate_usage(arguments, node, var_defn_ast, context)
46
+ var_defn_ast && arguments && validate_usage(arguments, node, var_defn_ast)
44
47
  end
45
- }
48
+ end
49
+ super
46
50
  end
47
51
 
48
52
  private
49
53
 
50
- def validate_usage(arguments, arg_node, ast_var, context)
54
+ def validate_usage(arguments, arg_node, ast_var)
51
55
  var_type = context.schema.type_from_ast(ast_var.type)
52
56
  if var_type.nil?
53
57
  return
@@ -71,16 +75,23 @@ module GraphQL
71
75
  var_type = wrap_var_type_with_depth_of_arg(var_type, arg_node)
72
76
 
73
77
  if var_inner_type != arg_inner_type
74
- context.errors << create_error("Type mismatch", var_type, ast_var, arg_defn, arg_node, context)
78
+ create_error("Type mismatch", var_type, ast_var, arg_defn, arg_node)
75
79
  elsif list_dimension(var_type) != list_dimension(arg_defn_type)
76
- context.errors << create_error("List dimension mismatch", var_type, ast_var, arg_defn, arg_node, context)
80
+ create_error("List dimension mismatch", var_type, ast_var, arg_defn, arg_node)
77
81
  elsif !non_null_levels_match(arg_defn_type, var_type)
78
- context.errors << create_error("Nullability mismatch", var_type, ast_var, arg_defn, arg_node, context)
82
+ create_error("Nullability mismatch", var_type, ast_var, arg_defn, arg_node)
79
83
  end
80
84
  end
81
85
 
82
- def create_error(error_message, var_type, ast_var, arg_defn, arg_node, context)
83
- message("#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_s} / #{arg_defn.type.to_s})", arg_node, context: context)
86
+ def create_error(error_message, var_type, ast_var, arg_defn, arg_node)
87
+ add_error(GraphQL::StaticValidation::VariableUsagesAreAllowedError.new(
88
+ "#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_s} / #{arg_defn.type.to_s})",
89
+ nodes: arg_node,
90
+ name: ast_var.name,
91
+ type: var_type.to_s,
92
+ argument: arg_node.name,
93
+ error: error_message
94
+ ))
84
95
  end
85
96
 
86
97
  def wrap_var_type_with_depth_of_arg(var_type, arg_node)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class VariableUsagesAreAllowedError < StaticValidation::Error
5
+ attr_reader :type_name
6
+ attr_reader :variable_name
7
+ attr_reader :argument_name
8
+ attr_reader :error_message
9
+
10
+ def initialize(message, path: nil, nodes: [], type:, name:, argument:, error:)
11
+ super(message, path: path, nodes: nodes)
12
+ @type_name = type
13
+ @variable_name = name
14
+ @argument_name = argument
15
+ @error_message = error
16
+ end
17
+
18
+ # A hash representation of this Message
19
+ def to_h
20
+ extensions = {
21
+ "code" => code,
22
+ "variableName" => variable_name,
23
+ "typeName" => type_name,
24
+ "argumentName" => argument_name,
25
+ "errorMessage" => error_message
26
+ }
27
+
28
+ super.merge({
29
+ "extensions" => extensions
30
+ })
31
+ end
32
+
33
+ def code
34
+ "variableMismatch"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,28 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class VariablesAreInputTypes
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- context.visitor[GraphQL::Language::Nodes::VariableDefinition] << ->(node, parent) {
9
- validate_is_input_type(node, context)
10
- }
11
- end
12
-
13
- private
14
-
15
- def validate_is_input_type(node, context)
4
+ module VariablesAreInputTypes
5
+ def on_variable_definition(node, parent)
16
6
  type_name = get_type_name(node.type)
17
7
  type = context.warden.get_type(type_name)
18
8
 
19
9
  if type.nil?
20
- context.errors << message("#{type_name} isn't a defined input type (on $#{node.name})", node, context: context)
10
+ add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
11
+ "#{type_name} isn't a defined input type (on $#{node.name})",
12
+ nodes: node,
13
+ name: node.name,
14
+ type: type_name
15
+ ))
21
16
  elsif !type.kind.input?
22
- context.errors << message("#{type.name} isn't a valid input type (on $#{node.name})", node, context: context)
17
+ add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
18
+ "#{type.name} isn't a valid input type (on $#{node.name})",
19
+ nodes: node,
20
+ name: node.name,
21
+ type: type_name
22
+ ))
23
23
  end
24
+
25
+ super
24
26
  end
25
27
 
28
+ private
29
+
26
30
  def get_type_name(ast_type)
27
31
  if ast_type.respond_to?(:of_type)
28
32
  get_type_name(ast_type.of_type)