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
@@ -1,29 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class FragmentTypesExist
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- FRAGMENTS_ON_TYPES = [
8
- GraphQL::Language::Nodes::FragmentDefinition,
9
- GraphQL::Language::Nodes::InlineFragment,
10
- ]
4
+ module FragmentTypesExist
5
+ def on_fragment_definition(node, _parent)
6
+ if validate_type_exists(node)
7
+ super
8
+ end
9
+ end
11
10
 
12
- def validate(context)
13
- FRAGMENTS_ON_TYPES.each do |node_class|
14
- context.visitor[node_class] << ->(node, parent) { validate_type_exists(node, context) }
11
+ def on_inline_fragment(node, _parent)
12
+ if validate_type_exists(node)
13
+ super
15
14
  end
16
15
  end
17
16
 
18
17
  private
19
18
 
20
- def validate_type_exists(node, context)
21
- return unless node.type
22
- type_name = node.type.name
23
- type = context.warden.get_type(type_name)
24
- if type.nil?
25
- context.errors << message("No such type #{type_name}, so it can't be a fragment condition", node, context: context)
26
- GraphQL::Language::Visitor::SKIP
19
+ def validate_type_exists(fragment_node)
20
+ if !fragment_node.type
21
+ true
22
+ else
23
+ type_name = fragment_node.type.name
24
+ type = context.warden.get_type(type_name)
25
+ if type.nil?
26
+ add_error(GraphQL::StaticValidation::FragmentTypesExistError.new(
27
+ "No such type #{type_name}, so it can't be a fragment condition",
28
+ nodes: fragment_node,
29
+ type: type_name
30
+ ))
31
+ false
32
+ else
33
+ true
34
+ end
27
35
  end
28
36
  end
29
37
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentTypesExistError < StaticValidation::Error
5
+ attr_reader :type_name
6
+
7
+ def initialize(message, path: nil, nodes: [], type:)
8
+ super(message, path: path, nodes: nodes)
9
+ @type_name = type
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "typeName" => type_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "undefinedType"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,16 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class FragmentsAreFinite
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- context.visitor[GraphQL::Language::Nodes::Document].leave << ->(_n, _p) do
9
- dependency_map = context.dependencies
10
- dependency_map.cyclical_definitions.each do |defn|
11
- if defn.node.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
12
- context.errors << message("Fragment #{defn.name} contains an infinite loop", defn.node, path: defn.path)
13
- end
4
+ module FragmentsAreFinite
5
+ def on_document(_n, _p)
6
+ super
7
+ dependency_map = context.dependencies
8
+ dependency_map.cyclical_definitions.each do |defn|
9
+ if defn.node.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
10
+ context.errors << GraphQL::StaticValidation::FragmentsAreFiniteError.new(
11
+ "Fragment #{defn.name} contains an infinite loop",
12
+ nodes: defn.node,
13
+ path: defn.path,
14
+ name: defn.name
15
+ )
14
16
  end
15
17
  end
16
18
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreFiniteError < StaticValidation::Error
5
+ attr_reader :fragment_name
6
+
7
+ def initialize(message, path: nil, nodes: [], name:)
8
+ super(message, path: path, nodes: nodes)
9
+ @fragment_name = name
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "fragmentName" => fragment_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "infiniteLoop"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,19 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class FragmentsAreNamed
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- context.visitor[GraphQL::Language::Nodes::FragmentDefinition] << ->(node, parent) { validate_name_exists(node, context) }
9
- end
10
-
11
- private
12
-
13
- def validate_name_exists(node, context)
4
+ module FragmentsAreNamed
5
+ def on_fragment_definition(node, _parent)
14
6
  if node.name.nil?
15
- context.errors << message("Fragment definition has no name", node, context: context)
7
+ add_error(GraphQL::StaticValidation::FragmentsAreNamedError.new(
8
+ "Fragment definition has no name",
9
+ nodes: node
10
+ ))
16
11
  end
12
+ super
17
13
  end
18
14
  end
19
15
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreNamedError < 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
+ "anonymousFragment"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,34 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class FragmentsAreOnCompositeTypes
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- HAS_TYPE_CONDITION = [
8
- GraphQL::Language::Nodes::FragmentDefinition,
9
- GraphQL::Language::Nodes::InlineFragment,
10
- ]
4
+ module FragmentsAreOnCompositeTypes
5
+ def on_fragment_definition(node, parent)
6
+ validate_type_is_composite(node) && super
7
+ end
11
8
 
12
- def validate(context)
13
- HAS_TYPE_CONDITION.each do |node_class|
14
- context.visitor[node_class] << ->(node, parent) {
15
- validate_type_is_composite(node, context)
16
- }
17
- end
9
+ def on_inline_fragment(node, parent)
10
+ validate_type_is_composite(node) && super
18
11
  end
19
12
 
20
13
  private
21
14
 
22
- def validate_type_is_composite(node, context)
15
+ def validate_type_is_composite(node)
23
16
  node_type = node.type
24
17
  if node_type.nil?
25
18
  # Inline fragment on the same type
19
+ true
26
20
  else
27
21
  type_name = node_type.to_query_string
28
22
  type_def = context.warden.get_type(type_name)
29
23
  if type_def.nil? || !type_def.kind.composite?
30
- context.errors << message("Invalid fragment on type #{type_name} (must be Union, Interface or Object)", node, context: context)
31
- GraphQL::Language::Visitor::SKIP
24
+ add_error(GraphQL::StaticValidation::FragmentsAreOnCompositeTypesError.new(
25
+ "Invalid fragment on type #{type_name} (must be Union, Interface or Object)",
26
+ nodes: node,
27
+ type: type_name
28
+ ))
29
+ false
30
+ else
31
+ true
32
32
  end
33
33
  end
34
34
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreOnCompositeTypesError < StaticValidation::Error
5
+ attr_reader :type_name
6
+ attr_reader :argument_name
7
+
8
+ def initialize(message, path: nil, nodes: [], type:)
9
+ super(message, path: path, nodes: nodes)
10
+ @type_name = type
11
+ end
12
+
13
+ # A hash representation of this Message
14
+ def to_h
15
+ extensions = {
16
+ "code" => code,
17
+ "typeName" => type_name
18
+ }
19
+
20
+ super.merge({
21
+ "extensions" => extensions
22
+ })
23
+ end
24
+
25
+ def code
26
+ "fragmentOnNonCompositeType"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,22 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class FragmentsAreUsed
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- context.visitor[GraphQL::Language::Nodes::Document].leave << ->(_n, _p) do
9
- dependency_map = context.dependencies
10
- dependency_map.unmet_dependencies.each do |op_defn, spreads|
11
- spreads.each do |fragment_spread|
12
- context.errors << message("Fragment #{fragment_spread.name} was used, but not defined", fragment_spread.node, path: fragment_spread.path)
13
- end
4
+ module FragmentsAreUsed
5
+ def on_document(node, parent)
6
+ super
7
+ dependency_map = context.dependencies
8
+ dependency_map.unmet_dependencies.each do |op_defn, spreads|
9
+ spreads.each do |fragment_spread|
10
+ add_error(GraphQL::StaticValidation::FragmentsAreUsedError.new(
11
+ "Fragment #{fragment_spread.name} was used, but not defined",
12
+ nodes: fragment_spread.node,
13
+ path: fragment_spread.path,
14
+ fragment: fragment_spread.name
15
+ ))
14
16
  end
17
+ end
15
18
 
16
- dependency_map.unused_dependencies.each do |fragment|
17
- if !fragment.name.nil?
18
- context.errors << message("Fragment #{fragment.name} was defined, but not used", fragment.node, path: fragment.path)
19
- end
19
+ dependency_map.unused_dependencies.each do |fragment|
20
+ if fragment && !fragment.name.nil?
21
+ add_error(GraphQL::StaticValidation::FragmentsAreUsedError.new(
22
+ "Fragment #{fragment.name} was defined, but not used",
23
+ nodes: fragment.node,
24
+ path: fragment.path,
25
+ fragment: fragment.name
26
+ ))
20
27
  end
21
28
  end
22
29
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreUsedError < StaticValidation::Error
5
+ attr_reader :fragment_name
6
+
7
+ def initialize(message, path: nil, nodes: [], fragment:)
8
+ super(message, path: path, nodes: nodes)
9
+ @fragment_name = fragment
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "fragmentName" => fragment_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "useAndDefineFragment"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,20 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class MutationRootExists
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- return if context.warden.root_type_for_operation("mutation")
9
-
10
- visitor = context.visitor
11
-
12
- visitor[GraphQL::Language::Nodes::OperationDefinition].enter << ->(ast_node, prev_ast_node) {
13
- if ast_node.operation_type == 'mutation'
14
- context.errors << message('Schema is not configured for mutations', ast_node, context: context)
15
- return GraphQL::Language::Visitor::SKIP
16
- end
17
- }
4
+ module MutationRootExists
5
+ def on_operation_definition(node, _parent)
6
+ if node.operation_type == 'mutation' && context.warden.root_type_for_operation("mutation").nil?
7
+ add_error(GraphQL::StaticValidation::MutationRootExistsError.new(
8
+ 'Schema is not configured for mutations',
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 MutationRootExistsError < 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
+ "missingMutationConfiguration"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,40 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class NoDefinitionsArePresent
5
- include GraphQL::StaticValidation::Message::MessageHelper
4
+ module NoDefinitionsArePresent
5
+ include GraphQL::StaticValidation::Error::ErrorHelper
6
6
 
7
- def validate(context)
8
- schema_definition_nodes = []
9
- register_node = ->(node, _p) {
10
- schema_definition_nodes << node
11
- GraphQL::Language::Visitor::SKIP
12
- }
13
-
14
- visitor = context.visitor
7
+ def initialize(*)
8
+ super
9
+ @schema_definition_nodes = []
10
+ end
15
11
 
16
- visitor[GraphQL::Language::Nodes::DirectiveDefinition] << register_node
17
- visitor[GraphQL::Language::Nodes::SchemaDefinition] << register_node
18
- visitor[GraphQL::Language::Nodes::ScalarTypeDefinition] << register_node
19
- visitor[GraphQL::Language::Nodes::ObjectTypeDefinition] << register_node
20
- visitor[GraphQL::Language::Nodes::InputObjectTypeDefinition] << register_node
21
- visitor[GraphQL::Language::Nodes::InterfaceTypeDefinition] << register_node
22
- visitor[GraphQL::Language::Nodes::UnionTypeDefinition] << register_node
23
- visitor[GraphQL::Language::Nodes::EnumTypeDefinition] << register_node
12
+ def on_invalid_node(node, parent)
13
+ @schema_definition_nodes << node
14
+ nil
15
+ end
24
16
 
25
- visitor[GraphQL::Language::Nodes::SchemaExtension] << register_node
26
- visitor[GraphQL::Language::Nodes::ScalarTypeExtension] << register_node
27
- visitor[GraphQL::Language::Nodes::ObjectTypeExtension] << register_node
28
- visitor[GraphQL::Language::Nodes::InputObjectTypeExtension] << register_node
29
- visitor[GraphQL::Language::Nodes::InterfaceTypeExtension] << register_node
30
- visitor[GraphQL::Language::Nodes::UnionTypeExtension] << register_node
31
- visitor[GraphQL::Language::Nodes::EnumTypeExtension] << register_node
17
+ alias :on_directive_definition :on_invalid_node
18
+ alias :on_schema_definition :on_invalid_node
19
+ alias :on_scalar_type_definition :on_invalid_node
20
+ alias :on_object_type_definition :on_invalid_node
21
+ alias :on_input_object_type_definition :on_invalid_node
22
+ alias :on_interface_type_definition :on_invalid_node
23
+ alias :on_union_type_definition :on_invalid_node
24
+ alias :on_enum_type_definition :on_invalid_node
25
+ alias :on_schema_extension :on_invalid_node
26
+ alias :on_scalar_type_extension :on_invalid_node
27
+ alias :on_object_type_extension :on_invalid_node
28
+ alias :on_input_object_type_extension :on_invalid_node
29
+ alias :on_interface_type_extension :on_invalid_node
30
+ alias :on_union_type_extension :on_invalid_node
31
+ alias :on_enum_type_extension :on_invalid_node
32
32
 
33
- visitor[GraphQL::Language::Nodes::Document].leave << ->(node, _p) {
34
- if schema_definition_nodes.any?
35
- context.errors << message(%|Query cannot contain schema definitions|, schema_definition_nodes, context: context)
36
- end
37
- }
33
+ def on_document(node, parent)
34
+ super
35
+ if @schema_definition_nodes.any?
36
+ add_error(GraphQL::StaticValidation::NoDefinitionsArePresentError.new(%|Query cannot contain schema definitions|, nodes: @schema_definition_nodes))
37
+ end
38
38
  end
39
39
  end
40
40
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class NoDefinitionsArePresentError < StaticValidation::Error
5
+ def initialize(message, path: nil, nodes: [])
6
+ super(message, path: path, nodes: nodes)
7
+ end
8
+
9
+ # A hash representation of this Message
10
+ def to_h
11
+ extensions = {
12
+ "code" => code,
13
+ }
14
+
15
+ super.merge({
16
+ "extensions" => extensions
17
+ })
18
+ end
19
+
20
+ def code
21
+ "queryContainsSchemaDefinitions"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,27 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class OperationNamesAreValid
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- op_names = Hash.new { |h, k| h[k] = [] }
4
+ module OperationNamesAreValid
5
+ def initialize(*)
6
+ super
7
+ @operation_names = Hash.new { |h, k| h[k] = [] }
8
+ end
9
9
 
10
- context.visitor[GraphQL::Language::Nodes::OperationDefinition].enter << ->(node, _parent) {
11
- op_names[node.name] << node
12
- }
10
+ def on_operation_definition(node, parent)
11
+ @operation_names[node.name] << node
12
+ super
13
+ end
13
14
 
14
- context.visitor[GraphQL::Language::Nodes::Document].leave << ->(node, _parent) {
15
- op_count = op_names.values.inject(0) { |m, v| m + v.size }
15
+ def on_document(node, parent)
16
+ super
17
+ op_count = @operation_names.values.inject(0) { |m, v| m + v.size }
16
18
 
17
- op_names.each do |name, nodes|
18
- if name.nil? && op_count > 1
19
- context.errors << message(%|Operation name is required when multiple operations are present|, nodes, context: context)
20
- elsif nodes.length > 1
21
- context.errors << message(%|Operation name "#{name}" must be unique|, nodes, context: context)
22
- end
19
+ @operation_names.each do |name, nodes|
20
+ if name.nil? && op_count > 1
21
+ add_error(GraphQL::StaticValidation::OperationNamesAreValidError.new(
22
+ %|Operation name is required when multiple operations are present|,
23
+ nodes: nodes
24
+ ))
25
+ elsif nodes.length > 1
26
+ add_error(GraphQL::StaticValidation::OperationNamesAreValidError.new(
27
+ %|Operation name "#{name}" must be unique|,
28
+ nodes: nodes,
29
+ name: name
30
+ ))
23
31
  end
24
- }
32
+ end
25
33
  end
26
34
  end
27
35
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class OperationNamesAreValidError < StaticValidation::Error
5
+ attr_reader :operation_name
6
+
7
+ def initialize(message, path: nil, nodes: [], name: nil)
8
+ super(message, path: path, nodes: nodes)
9
+ @operation_name = name
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code
16
+ }.tap { |h| h["operationName"] = operation_name unless operation_name.nil? }
17
+
18
+ super.merge({
19
+ "extensions" => extensions
20
+ })
21
+ end
22
+
23
+ def code
24
+ "uniquelyNamedOperations"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,28 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module StaticValidation
4
- class RequiredArgumentsArePresent
5
- include GraphQL::StaticValidation::Message::MessageHelper
6
-
7
- def validate(context)
8
- v = context.visitor
9
- v[GraphQL::Language::Nodes::Field] << ->(node, parent) { validate_field(node, context) }
10
- v[GraphQL::Language::Nodes::Directive] << ->(node, parent) { validate_directive(node, context) }
4
+ module RequiredArgumentsArePresent
5
+ def on_field(node, _parent)
6
+ assert_required_args(node, field_definition)
7
+ super
11
8
  end
12
9
 
13
- private
14
-
15
- def validate_directive(ast_directive, context)
16
- directive_defn = context.schema.directives[ast_directive.name]
17
- assert_required_args(ast_directive, directive_defn, context)
10
+ def on_directive(node, _parent)
11
+ directive_defn = context.schema.directives[node.name]
12
+ assert_required_args(node, directive_defn)
13
+ super
18
14
  end
19
15
 
20
- def validate_field(ast_field, context)
21
- defn = context.field_definition
22
- assert_required_args(ast_field, defn, context)
23
- end
16
+ private
24
17
 
25
- def assert_required_args(ast_node, defn, context)
18
+ def assert_required_args(ast_node, defn)
26
19
  present_argument_names = ast_node.arguments.map(&:name)
27
20
  required_argument_names = defn.arguments.values
28
21
  .select { |a| a.type.kind.non_null? }
@@ -30,7 +23,13 @@ module GraphQL
30
23
 
31
24
  missing_names = required_argument_names - present_argument_names
32
25
  if missing_names.any?
33
- context.errors << message("#{ast_node.class.name.split("::").last} '#{ast_node.name}' is missing required arguments: #{missing_names.join(", ")}", ast_node, context: context)
26
+ add_error(GraphQL::StaticValidation::RequiredArgumentsArePresentError.new(
27
+ "#{ast_node.class.name.split("::").last} '#{ast_node.name}' is missing required arguments: #{missing_names.join(", ")}",
28
+ nodes: ast_node,
29
+ class_name: ast_node.class.name.split("::").last,
30
+ name: ast_node.name,
31
+ arguments: "#{missing_names.join(", ")}"
32
+ ))
34
33
  end
35
34
  end
36
35
  end