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
@@ -19,7 +19,6 @@ require "graphql/schema/validation"
19
19
  require "graphql/schema/warden"
20
20
  require "graphql/schema/build_from_definition"
21
21
 
22
-
23
22
  require "graphql/schema/member"
24
23
  require "graphql/schema/wrapper"
25
24
  require "graphql/schema/list"
@@ -27,15 +26,23 @@ require "graphql/schema/non_null"
27
26
  require "graphql/schema/argument"
28
27
  require "graphql/schema/enum_value"
29
28
  require "graphql/schema/enum"
29
+ require "graphql/schema/field_extension"
30
30
  require "graphql/schema/field"
31
31
  require "graphql/schema/input_object"
32
32
  require "graphql/schema/interface"
33
+ require "graphql/schema/scalar"
34
+ require "graphql/schema/object"
35
+ require "graphql/schema/union"
36
+ require "graphql/schema/directive"
37
+ require "graphql/schema/directive/include"
38
+ require "graphql/schema/directive/skip"
39
+ require "graphql/schema/directive/feature"
40
+ require "graphql/schema/directive/transform"
41
+
33
42
  require "graphql/schema/resolver"
34
43
  require "graphql/schema/mutation"
35
44
  require "graphql/schema/relay_classic_mutation"
36
- require "graphql/schema/object"
37
- require "graphql/schema/scalar"
38
- require "graphql/schema/union"
45
+ require "graphql/schema/subscription"
39
46
 
40
47
  module GraphQL
41
48
  # A GraphQL schema which may be queried with {GraphQL::Query}.
@@ -78,22 +85,29 @@ module GraphQL
78
85
  :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
79
86
  :max_depth, :max_complexity, :default_max_page_size,
80
87
  :orphan_types, :resolve_type, :type_error, :parse_error,
88
+ :error_bubbling,
81
89
  :raise_definition_error,
82
90
  :object_from_id, :id_from_object,
83
91
  :default_mask,
84
92
  :cursor_encoder,
85
- directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m }},
93
+ directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m } },
94
+ directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
86
95
  instrument: ->(schema, type, instrumenter, after_built_ins: false) {
87
96
  if type == :field && after_built_ins
88
97
  type = :field_after_built_ins
89
98
  end
90
99
  schema.instrumenters[type] << instrumenter
91
100
  },
92
- query_analyzer: ->(schema, analyzer) { schema.query_analyzers << analyzer },
101
+ query_analyzer: ->(schema, analyzer) {
102
+ if analyzer == GraphQL::Authorization::Analyzer
103
+ warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
104
+ end
105
+ schema.query_analyzers << analyzer
106
+ },
93
107
  multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
94
108
  middleware: ->(schema, middleware) { schema.middleware << middleware },
95
109
  lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
96
- rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block)},
110
+ rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
97
111
  tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
98
112
 
99
113
  attr_accessor \
@@ -105,7 +119,11 @@ module GraphQL
105
119
  :cursor_encoder,
106
120
  :ast_node,
107
121
  :raise_definition_error,
108
- :introspection_namespace
122
+ :introspection_namespace,
123
+ :analysis_engine
124
+
125
+ # [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
126
+ attr_accessor :error_bubbling
109
127
 
110
128
  # Single, long-lived instance of the provided subscriptions class, if there is one.
111
129
  # @return [GraphQL::Subscriptions]
@@ -134,9 +152,6 @@ module GraphQL
134
152
  # @see {Query#tracers} for query-specific tracers
135
153
  attr_reader :tracers
136
154
 
137
- self.default_execution_strategy = GraphQL::Execution::Execute
138
-
139
- DIRECTIVES = [GraphQL::Directive::IncludeDirective, GraphQL::Directive::SkipDirective, GraphQL::Directive::DeprecatedDirective]
140
155
  DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
141
156
 
142
157
  attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
@@ -145,7 +160,7 @@ module GraphQL
145
160
  @tracers = []
146
161
  @definition_error = nil
147
162
  @orphan_types = []
148
- @directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
163
+ @directives = self.class.default_directives
149
164
  @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
150
165
  @middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
151
166
  @query_analyzers = []
@@ -160,6 +175,7 @@ module GraphQL
160
175
  @lazy_methods.set(GraphQL::Execution::Lazy, :value)
161
176
  @cursor_encoder = Base64Encoder
162
177
  # Default to the built-in execution strategy:
178
+ @analysis_engine = GraphQL::Analysis
163
179
  @query_execution_strategy = self.class.default_execution_strategy
164
180
  @mutation_execution_strategy = self.class.default_execution_strategy
165
181
  @subscription_execution_strategy = self.class.default_execution_strategy
@@ -168,6 +184,20 @@ module GraphQL
168
184
  @context_class = GraphQL::Query::Context
169
185
  @introspection_namespace = nil
170
186
  @introspection_system = nil
187
+ @interpreter = false
188
+ @error_bubbling = false
189
+ end
190
+
191
+ # @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
192
+ def interpreter?
193
+ @interpreter
194
+ end
195
+
196
+ # @api private
197
+ attr_writer :interpreter
198
+
199
+ def inspect
200
+ "#<#{self.class.name} ...>"
171
201
  end
172
202
 
173
203
  def initialize_copy(other)
@@ -206,12 +236,16 @@ module GraphQL
206
236
  rescue_middleware.remove_handler(*args, &block)
207
237
  end
208
238
 
239
+ def using_ast_analysis?
240
+ @analysis_engine == GraphQL::Analysis::AST
241
+ end
242
+
209
243
  # For forwards-compatibility with Schema classes
210
244
  alias :graphql_definition :itself
211
245
 
212
246
  # Validate a query string according to this schema.
213
247
  # @param string_or_document [String, GraphQL::Language::Nodes::Document]
214
- # @return [Array<GraphQL::StaticValidation::Message>]
248
+ # @return [Array<GraphQL::StaticValidation::Error >]
215
249
  def validate(string_or_document, rules: nil)
216
250
  doc = if string_or_document.is_a?(String)
217
251
  GraphQL.parse(string_or_document)
@@ -389,7 +423,7 @@ module GraphQL
389
423
  # Fields for this type, after instrumentation is applied
390
424
  # @return [Hash<String, GraphQL::Field>]
391
425
  def get_fields(type)
392
- @instrumented_field_map[type.name]
426
+ @instrumented_field_map[type.graphql_name]
393
427
  end
394
428
 
395
429
  def type_from_ast(ast_node)
@@ -475,17 +509,20 @@ module GraphQL
475
509
  yield(type, object, ctx)
476
510
  end
477
511
 
478
- if type_result.respond_to?(:graphql_definition)
479
- type_result = type_result.graphql_definition
480
- end
481
-
482
512
  if type_result.nil?
483
513
  nil
484
- elsif !type_result.is_a?(GraphQL::BaseType)
485
- type_str = "#{type_result} (#{type_result.class.name})"
486
- raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
487
514
  else
488
- type_result
515
+ after_lazy(type_result) do |resolved_type_result|
516
+ if resolved_type_result.respond_to?(:graphql_definition)
517
+ resolved_type_result = resolved_type_result.graphql_definition
518
+ end
519
+ if !resolved_type_result.is_a?(GraphQL::BaseType)
520
+ type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
521
+ raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
522
+ else
523
+ resolved_type_result
524
+ end
525
+ end
489
526
  end
490
527
  end
491
528
 
@@ -542,7 +579,8 @@ module GraphQL
542
579
 
543
580
  # Can't delegate to `class`
544
581
  alias :_schema_class :class
545
- def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :inaccessible_fields
582
+ def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :unauthorized_field, :inaccessible_fields
583
+ def_delegators :_schema_class, :directive
546
584
 
547
585
  # A function to call when {#execute} receives an invalid query string
548
586
  #
@@ -656,10 +694,12 @@ module GraphQL
656
694
  :execute, :multiplex,
657
695
  :static_validator, :introspection_system,
658
696
  :query_analyzers, :tracers, :instrumenters,
659
- :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
660
- :validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy,
697
+ :execution_strategy_for_operation,
698
+ :validate, :multiplex_analyzers, :lazy?, :lazy_method_name, :after_lazy, :sync_lazy,
661
699
  # Configuration
700
+ :analysis_engine, :analysis_engine=, :using_ast_analysis?, :interpreter?,
662
701
  :max_complexity=, :max_depth=,
702
+ :error_bubbling=,
663
703
  :metadata,
664
704
  :default_mask,
665
705
  :default_filter, :redefine,
@@ -693,10 +733,14 @@ module GraphQL
693
733
  schema_defn.mutation = mutation
694
734
  schema_defn.subscription = subscription
695
735
  schema_defn.max_complexity = max_complexity
736
+ schema_defn.error_bubbling = error_bubbling
696
737
  schema_defn.max_depth = max_depth
697
738
  schema_defn.default_max_page_size = default_max_page_size
698
739
  schema_defn.orphan_types = orphan_types
699
- schema_defn.directives = directives
740
+
741
+ prepped_dirs = {}
742
+ directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
743
+ schema_defn.directives = prepped_dirs
700
744
  schema_defn.introspection_namespace = introspection
701
745
  schema_defn.resolve_type = method(:resolve_type)
702
746
  schema_defn.object_from_id = method(:object_from_id)
@@ -706,15 +750,17 @@ module GraphQL
706
750
  schema_defn.cursor_encoder = cursor_encoder
707
751
  schema_defn.tracers.concat(defined_tracers)
708
752
  schema_defn.query_analyzers.concat(defined_query_analyzers)
709
- schema_defn.query_analyzers << GraphQL::Authorization::Analyzer
753
+
710
754
  schema_defn.middleware.concat(defined_middleware)
711
755
  schema_defn.multiplex_analyzers.concat(defined_multiplex_analyzers)
756
+ schema_defn.query_execution_strategy = query_execution_strategy
757
+ schema_defn.mutation_execution_strategy = mutation_execution_strategy
758
+ schema_defn.subscription_execution_strategy = subscription_execution_strategy
712
759
  defined_instrumenters.each do |step, insts|
713
760
  insts.each do |inst|
714
761
  schema_defn.instrumenters[step] << inst
715
762
  end
716
763
  end
717
- schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
718
764
  lazy_classes.each do |lazy_class, value_method|
719
765
  schema_defn.lazy_methods.set(lazy_class, value_method)
720
766
  end
@@ -737,6 +783,10 @@ module GraphQL
737
783
  end
738
784
  end
739
785
  end
786
+ # Do this after `plugins` since Interpreter is a plugin
787
+ if schema_defn.query_execution_strategy != GraphQL::Execution::Interpreter
788
+ schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
789
+ end
740
790
  schema_defn.send(:rebuild_artifacts)
741
791
 
742
792
  schema_defn
@@ -789,6 +839,30 @@ module GraphQL
789
839
  end
790
840
  end
791
841
 
842
+ def query_execution_strategy(new_query_execution_strategy = nil)
843
+ if new_query_execution_strategy
844
+ @query_execution_strategy = new_query_execution_strategy
845
+ else
846
+ @query_execution_strategy || self.default_execution_strategy
847
+ end
848
+ end
849
+
850
+ def mutation_execution_strategy(new_mutation_execution_strategy = nil)
851
+ if new_mutation_execution_strategy
852
+ @mutation_execution_strategy = new_mutation_execution_strategy
853
+ else
854
+ @mutation_execution_strategy || self.default_execution_strategy
855
+ end
856
+ end
857
+
858
+ def subscription_execution_strategy(new_subscription_execution_strategy = nil)
859
+ if new_subscription_execution_strategy
860
+ @subscription_execution_strategy = new_subscription_execution_strategy
861
+ else
862
+ @subscription_execution_strategy || self.default_execution_strategy
863
+ end
864
+ end
865
+
792
866
  def max_complexity(max_complexity = nil)
793
867
  if max_complexity
794
868
  @max_complexity = max_complexity
@@ -797,6 +871,14 @@ module GraphQL
797
871
  end
798
872
  end
799
873
 
874
+ def error_bubbling(new_error_bubbling = nil)
875
+ if !new_error_bubbling.nil?
876
+ @error_bubbling = new_error_bubbling
877
+ else
878
+ @error_bubbling
879
+ end
880
+ end
881
+
800
882
  def max_depth(new_max_depth = nil)
801
883
  if new_max_depth
802
884
  @max_depth = new_max_depth
@@ -817,7 +899,7 @@ module GraphQL
817
899
  if superclass <= GraphQL::Schema
818
900
  superclass.default_execution_strategy
819
901
  else
820
- @default_execution_strategy
902
+ @default_execution_strategy ||= GraphQL::Execution::Execute
821
903
  end
822
904
  end
823
905
 
@@ -829,17 +911,23 @@ module GraphQL
829
911
  end
830
912
  end
831
913
 
832
- def rescue_from(err_class, &handler_block)
914
+ def rescue_from(*err_classes, &handler_block)
833
915
  @rescues ||= {}
834
- @rescues[err_class] = handler_block
916
+ err_classes.each do |err_class|
917
+ @rescues[err_class] = handler_block
918
+ end
835
919
  end
836
920
 
837
921
  def resolve_type(type, obj, ctx)
838
- raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
922
+ if type.kind.object?
923
+ type
924
+ else
925
+ raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
926
+ end
839
927
  end
840
928
 
841
929
  def object_from_id(node_id, ctx)
842
- raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to use the `node` field (tried to load from id `#{node_id}`)"
930
+ raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
843
931
  end
844
932
 
845
933
  def id_from_object(object, type, ctx)
@@ -873,7 +961,7 @@ module GraphQL
873
961
  # By default, this hook just replaces the unauthorized object with `nil`.
874
962
  #
875
963
  # Whatever value is returned from this method will be used instead of the
876
- # unauthorized object (accessible ass `unauthorized_error.object`). If an
964
+ # unauthorized object (accessible as `unauthorized_error.object`). If an
877
965
  # error is raised, then `nil` will be used.
878
966
  #
879
967
  # If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
@@ -885,6 +973,22 @@ module GraphQL
885
973
  nil
886
974
  end
887
975
 
976
+ # This hook is called when a field fails an `authorized?` check.
977
+ #
978
+ # By default, this hook implements the same behavior as unauthorized_object.
979
+ #
980
+ # Whatever value is returned from this method will be used instead of the
981
+ # unauthorized field . If an error is raised, then `nil` will be used.
982
+ #
983
+ # If you want to add an error to the `"errors"` key, raise a {GraphQL::ExecutionError}
984
+ # in this hook.
985
+ #
986
+ # @param unauthorized_error [GraphQL::UnauthorizedFieldError]
987
+ # @return [Field] The returned field will be put in the GraphQL response
988
+ def unauthorized_field(unauthorized_error)
989
+ unauthorized_object(unauthorized_error)
990
+ end
991
+
888
992
  def type_error(type_err, ctx)
889
993
  DefaultTypeError.call(type_err, ctx)
890
994
  end
@@ -907,7 +1011,19 @@ module GraphQL
907
1011
  @directives = new_directives.reduce({}) { |m, d| m[d.name] = d; m }
908
1012
  end
909
1013
 
910
- @directives ||= directives(DIRECTIVES)
1014
+ @directives ||= default_directives
1015
+ end
1016
+
1017
+ def directive(new_directive)
1018
+ directives[new_directive.graphql_name] = new_directive
1019
+ end
1020
+
1021
+ def default_directives
1022
+ {
1023
+ "include" => GraphQL::Directive::IncludeDirective,
1024
+ "skip" => GraphQL::Directive::SkipDirective,
1025
+ "deprecated" => GraphQL::Directive::DeprecatedDirective,
1026
+ }
911
1027
  end
912
1028
 
913
1029
  def tracer(new_tracer)
@@ -915,6 +1031,9 @@ module GraphQL
915
1031
  end
916
1032
 
917
1033
  def query_analyzer(new_analyzer)
1034
+ if new_analyzer == GraphQL::Authorization::Analyzer
1035
+ warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1036
+ end
918
1037
  defined_query_analyzers << new_analyzer
919
1038
  end
920
1039
 
@@ -962,7 +1081,7 @@ module GraphQL
962
1081
  # @see {.accessible?}
963
1082
  # @see {.authorized?}
964
1083
  def call_on_type_class(member, method_name, *args, default:)
965
- member = if member.respond_to?(:metadata)
1084
+ member = if member.respond_to?(:metadata) && member.metadata
966
1085
  member.metadata[:type_class] || member
967
1086
  else
968
1087
  member
@@ -1001,9 +1120,9 @@ module GraphQL
1001
1120
  # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
1002
1121
  # @api private
1003
1122
  def after_lazy(value)
1004
- if (lazy_method = lazy_method_name(value))
1123
+ if lazy?(value)
1005
1124
  GraphQL::Execution::Lazy.new do
1006
- result = value.public_send(lazy_method)
1125
+ result = sync_lazy(value)
1007
1126
  # The returned result might also be lazy, so check it, too
1008
1127
  after_lazy(result) do |final_result|
1009
1128
  yield(final_result) if block_given?
@@ -1014,6 +1133,35 @@ module GraphQL
1014
1133
  end
1015
1134
  end
1016
1135
 
1136
+ # Override this method to handle lazy objects in a custom way.
1137
+ # @param value [Object] an instance of a class registered with {.lazy_resolve}
1138
+ # @param ctx [GraphQL::Query::Context] the context for this query
1139
+ # @return [Object] A GraphQL-ready (non-lazy) object
1140
+ def self.sync_lazy(value)
1141
+ if block_given?
1142
+ # This was already hit by the instance, just give it back
1143
+ yield(value)
1144
+ else
1145
+ # This was called directly on the class, hit the instance
1146
+ # which has the lazy method map
1147
+ self.graphql_definition.sync_lazy(value)
1148
+ end
1149
+ end
1150
+
1151
+ # @see Schema.sync_lazy for a hook to override
1152
+ # @api private
1153
+ def sync_lazy(value)
1154
+ self.class.sync_lazy(value) { |v|
1155
+ lazy_method = lazy_method_name(v)
1156
+ if lazy_method
1157
+ synced_value = value.public_send(lazy_method)
1158
+ sync_lazy(synced_value)
1159
+ else
1160
+ v
1161
+ end
1162
+ }
1163
+ end
1164
+
1017
1165
  protected
1018
1166
 
1019
1167
  def rescues?
@@ -11,9 +11,10 @@ module GraphQL
11
11
  GraphQL::StaticValidation::DirectivesAreDefined,
12
12
  GraphQL::StaticValidation::DirectivesAreInValidLocations,
13
13
  GraphQL::StaticValidation::UniqueDirectivesPerLocation,
14
+ GraphQL::StaticValidation::OperationNamesAreValid,
15
+ GraphQL::StaticValidation::FragmentNamesAreUnique,
14
16
  GraphQL::StaticValidation::FragmentsAreFinite,
15
17
  GraphQL::StaticValidation::FragmentsAreNamed,
16
- GraphQL::StaticValidation::FragmentNamesAreUnique,
17
18
  GraphQL::StaticValidation::FragmentsAreUsed,
18
19
  GraphQL::StaticValidation::FragmentTypesExist,
19
20
  GraphQL::StaticValidation::FragmentsAreOnCompositeTypes,
@@ -24,6 +25,7 @@ module GraphQL
24
25
  GraphQL::StaticValidation::ArgumentsAreDefined,
25
26
  GraphQL::StaticValidation::ArgumentLiteralsAreCompatible,
26
27
  GraphQL::StaticValidation::RequiredArgumentsArePresent,
28
+ GraphQL::StaticValidation::RequiredInputObjectAttributesArePresent,
27
29
  GraphQL::StaticValidation::ArgumentNamesAreUnique,
28
30
  GraphQL::StaticValidation::VariableNamesAreUnique,
29
31
  GraphQL::StaticValidation::VariablesAreInputTypes,
@@ -32,7 +34,6 @@ module GraphQL
32
34
  GraphQL::StaticValidation::VariableUsagesAreAllowed,
33
35
  GraphQL::StaticValidation::MutationRootExists,
34
36
  GraphQL::StaticValidation::SubscriptionRootExists,
35
- GraphQL::StaticValidation::OperationNamesAreValid,
36
37
  ]
37
38
  end
38
39
  end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class BaseVisitor < GraphQL::Language::Visitor
5
+ def initialize(document, context)
6
+ @path = []
7
+ @object_types = []
8
+ @directives = []
9
+ @field_definitions = []
10
+ @argument_definitions = []
11
+ @directive_definitions = []
12
+ @context = context
13
+ @schema = context.schema
14
+ super(document)
15
+ end
16
+
17
+ # This will be overwritten by {InternalRepresentation::Rewrite} if it's included
18
+ def rewrite_document
19
+ nil
20
+ end
21
+
22
+ attr_reader :context
23
+
24
+ # @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
25
+ attr_reader :object_types
26
+
27
+ # @return [Array<String>] The nesting of the current position in the AST
28
+ def path
29
+ @path.dup
30
+ end
31
+
32
+ # Build a class to visit the AST and perform validation,
33
+ # or use a pre-built class if rules is `ALL_RULES` or empty.
34
+ # @param rules [Array<Module, Class>]
35
+ # @param rewrite [Boolean] if `false`, don't include rewrite
36
+ # @return [Class] A class for validating `rules` during visitation
37
+ def self.including_rules(rules, rewrite: true)
38
+ if rules.empty?
39
+ if rewrite
40
+ NoValidateVisitor
41
+ else
42
+ # It's not doing _anything?!?_
43
+ BaseVisitor
44
+ end
45
+ elsif rules == ALL_RULES
46
+ if rewrite
47
+ DefaultVisitor
48
+ else
49
+ InterpreterVisitor
50
+ end
51
+ else
52
+ visitor_class = Class.new(self) do
53
+ include(GraphQL::StaticValidation::DefinitionDependencies)
54
+ end
55
+
56
+ rules.reverse_each do |r|
57
+ # If it's a class, it gets attached later.
58
+ if !r.is_a?(Class)
59
+ visitor_class.include(r)
60
+ end
61
+ end
62
+
63
+ if rewrite
64
+ visitor_class.include(GraphQL::InternalRepresentation::Rewrite)
65
+ end
66
+ visitor_class.include(ContextMethods)
67
+ visitor_class
68
+ end
69
+ end
70
+
71
+ module ContextMethods
72
+ def on_operation_definition(node, parent)
73
+ object_type = @schema.root_type_for_operation(node.operation_type)
74
+ @object_types.push(object_type)
75
+ @path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
76
+ super
77
+ @object_types.pop
78
+ @path.pop
79
+ end
80
+
81
+ def on_fragment_definition(node, parent)
82
+ on_fragment_with_type(node) do
83
+ @path.push("fragment #{node.name}")
84
+ super
85
+ end
86
+ end
87
+
88
+ def on_inline_fragment(node, parent)
89
+ on_fragment_with_type(node) do
90
+ @path.push("...#{node.type ? " on #{node.type.to_query_string}" : ""}")
91
+ super
92
+ end
93
+ end
94
+
95
+ def on_field(node, parent)
96
+ parent_type = @object_types.last
97
+ field_definition = @schema.get_field(parent_type, node.name)
98
+ @field_definitions.push(field_definition)
99
+ if !field_definition.nil?
100
+ next_object_type = field_definition.type.unwrap
101
+ @object_types.push(next_object_type)
102
+ else
103
+ @object_types.push(nil)
104
+ end
105
+ @path.push(node.alias || node.name)
106
+ super
107
+ @field_definitions.pop
108
+ @object_types.pop
109
+ @path.pop
110
+ end
111
+
112
+ def on_directive(node, parent)
113
+ directive_defn = @schema.directives[node.name]
114
+ @directive_definitions.push(directive_defn)
115
+ super
116
+ @directive_definitions.pop
117
+ end
118
+
119
+ def on_argument(node, parent)
120
+ argument_defn = if (arg = @argument_definitions.last)
121
+ arg_type = arg.type.unwrap
122
+ if arg_type.kind.input_object?
123
+ arg_type.input_fields[node.name]
124
+ else
125
+ nil
126
+ end
127
+ elsif (directive_defn = @directive_definitions.last)
128
+ directive_defn.arguments[node.name]
129
+ elsif (field_defn = @field_definitions.last)
130
+ field_defn.arguments[node.name]
131
+ else
132
+ nil
133
+ end
134
+
135
+ @argument_definitions.push(argument_defn)
136
+ @path.push(node.name)
137
+ super
138
+ @argument_definitions.pop
139
+ @path.pop
140
+ end
141
+
142
+ def on_fragment_spread(node, parent)
143
+ @path.push("... #{node.name}")
144
+ super
145
+ @path.pop
146
+ end
147
+
148
+ # @return [GraphQL::BaseType] The current object type
149
+ def type_definition
150
+ @object_types.last
151
+ end
152
+
153
+ # @return [GraphQL::BaseType] The type which the current type came from
154
+ def parent_type_definition
155
+ @object_types[-2]
156
+ end
157
+
158
+ # @return [GraphQL::Field, nil] The most-recently-entered GraphQL::Field, if currently inside one
159
+ def field_definition
160
+ @field_definitions.last
161
+ end
162
+
163
+ # @return [GraphQL::Directive, nil] The most-recently-entered GraphQL::Directive, if currently inside one
164
+ def directive_definition
165
+ @directive_definitions.last
166
+ end
167
+
168
+ # @return [GraphQL::Argument, nil] The most-recently-entered GraphQL::Argument, if currently inside one
169
+ def argument_definition
170
+ # Don't get the _last_ one because that's the current one.
171
+ # Get the second-to-last one, which is the parent of the current one.
172
+ @argument_definitions[-2]
173
+ end
174
+
175
+ private
176
+
177
+ def on_fragment_with_type(node)
178
+ object_type = if node.type
179
+ @schema.types.fetch(node.type.name, nil)
180
+ else
181
+ @object_types.last
182
+ end
183
+ @object_types.push(object_type)
184
+ yield(node)
185
+ @object_types.pop
186
+ @path.pop
187
+ end
188
+ end
189
+
190
+ private
191
+
192
+ def add_error(error, path: nil)
193
+ error.path ||= (path || @path.dup)
194
+ context.errors << error
195
+ end
196
+
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class DefaultVisitor < BaseVisitor
5
+ include(GraphQL::StaticValidation::DefinitionDependencies)
6
+
7
+ StaticValidation::ALL_RULES.reverse_each do |r|
8
+ include(r)
9
+ end
10
+
11
+ include(GraphQL::InternalRepresentation::Rewrite)
12
+ include(ContextMethods)
13
+ end
14
+ end
15
+ end