graphql 1.7.6 → 1.8.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 (289) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/install_generator.rb +14 -8
  4. data/lib/generators/graphql/loader_generator.rb +1 -1
  5. data/lib/generators/graphql/mutation_generator.rb +6 -1
  6. data/lib/generators/graphql/templates/function.erb +2 -2
  7. data/lib/generators/graphql/templates/loader.erb +2 -2
  8. data/lib/generators/graphql/templates/schema.erb +1 -1
  9. data/lib/graphql/argument.rb +25 -19
  10. data/lib/graphql/backtrace/tracer.rb +16 -22
  11. data/lib/graphql/backtrace.rb +1 -1
  12. data/lib/graphql/backwards_compatibility.rb +2 -3
  13. data/lib/graphql/base_type.rb +31 -31
  14. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
  15. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  16. data/lib/graphql/define/assign_object_field.rb +5 -12
  17. data/lib/graphql/deprecated_dsl.rb +42 -0
  18. data/lib/graphql/directive.rb +1 -0
  19. data/lib/graphql/enum_type.rb +3 -1
  20. data/lib/graphql/execution/execute.rb +21 -13
  21. data/lib/graphql/execution/instrumentation.rb +82 -0
  22. data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
  23. data/lib/graphql/execution/lazy/resolve.rb +1 -3
  24. data/lib/graphql/execution/multiplex.rb +12 -29
  25. data/lib/graphql/execution.rb +1 -0
  26. data/lib/graphql/field.rb +21 -4
  27. data/lib/graphql/function.rb +14 -0
  28. data/lib/graphql/input_object_type.rb +3 -1
  29. data/lib/graphql/interface_type.rb +5 -3
  30. data/lib/graphql/internal_representation/node.rb +26 -14
  31. data/lib/graphql/internal_representation/visit.rb +3 -6
  32. data/lib/graphql/introspection/base_object.rb +16 -0
  33. data/lib/graphql/introspection/directive_location_enum.rb +11 -7
  34. data/lib/graphql/introspection/directive_type.rb +23 -16
  35. data/lib/graphql/introspection/dynamic_fields.rb +11 -0
  36. data/lib/graphql/introspection/entry_points.rb +29 -0
  37. data/lib/graphql/introspection/enum_value_type.rb +16 -11
  38. data/lib/graphql/introspection/field_type.rb +21 -12
  39. data/lib/graphql/introspection/input_value_type.rb +26 -23
  40. data/lib/graphql/introspection/schema_field.rb +7 -2
  41. data/lib/graphql/introspection/schema_type.rb +36 -22
  42. data/lib/graphql/introspection/type_by_name_field.rb +10 -2
  43. data/lib/graphql/introspection/type_kind_enum.rb +10 -6
  44. data/lib/graphql/introspection/type_type.rb +85 -23
  45. data/lib/graphql/introspection/typename_field.rb +1 -0
  46. data/lib/graphql/introspection.rb +3 -10
  47. data/lib/graphql/language/block_string.rb +47 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +280 -0
  49. data/lib/graphql/language/generation.rb +3 -182
  50. data/lib/graphql/language/lexer.rb +144 -69
  51. data/lib/graphql/language/lexer.rl +15 -4
  52. data/lib/graphql/language/nodes.rb +141 -78
  53. data/lib/graphql/language/parser.rb +677 -630
  54. data/lib/graphql/language/parser.y +18 -12
  55. data/lib/graphql/language/printer.rb +361 -0
  56. data/lib/graphql/language/token.rb +10 -3
  57. data/lib/graphql/language.rb +3 -0
  58. data/lib/graphql/non_null_type.rb +1 -1
  59. data/lib/graphql/object_type.rb +1 -6
  60. data/lib/graphql/query/arguments.rb +63 -32
  61. data/lib/graphql/query/context.rb +32 -2
  62. data/lib/graphql/query/literal_input.rb +4 -1
  63. data/lib/graphql/query/null_context.rb +1 -1
  64. data/lib/graphql/query/result.rb +1 -1
  65. data/lib/graphql/query/variables.rb +21 -3
  66. data/lib/graphql/query.rb +19 -6
  67. data/lib/graphql/railtie.rb +109 -0
  68. data/lib/graphql/relay/connection_resolve.rb +3 -0
  69. data/lib/graphql/relay/connection_type.rb +5 -3
  70. data/lib/graphql/relay/edge_type.rb +2 -1
  71. data/lib/graphql/relay/global_id_resolve.rb +5 -1
  72. data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
  73. data/lib/graphql/relay/mutation/instrumentation.rb +1 -1
  74. data/lib/graphql/relay/mutation/resolve.rb +5 -1
  75. data/lib/graphql/relay/relation_connection.rb +14 -19
  76. data/lib/graphql/relay/type_extensions.rb +30 -0
  77. data/lib/graphql/relay.rb +2 -0
  78. data/lib/graphql/scalar_type.rb +14 -2
  79. data/lib/graphql/schema/argument.rb +92 -0
  80. data/lib/graphql/schema/build_from_definition.rb +64 -18
  81. data/lib/graphql/schema/enum.rb +85 -0
  82. data/lib/graphql/schema/enum_value.rb +74 -0
  83. data/lib/graphql/schema/field.rb +372 -0
  84. data/lib/graphql/schema/finder.rb +153 -0
  85. data/lib/graphql/schema/input_object.rb +87 -0
  86. data/lib/graphql/schema/interface.rb +105 -0
  87. data/lib/graphql/schema/introspection_system.rb +93 -0
  88. data/lib/graphql/schema/late_bound_type.rb +32 -0
  89. data/lib/graphql/schema/list.rb +32 -0
  90. data/lib/graphql/schema/loader.rb +2 -2
  91. data/lib/graphql/schema/member/accepts_definition.rb +152 -0
  92. data/lib/graphql/schema/member/base_dsl_methods.rb +100 -0
  93. data/lib/graphql/schema/member/build_type.rb +137 -0
  94. data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
  95. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  96. data/lib/graphql/schema/member/has_arguments.rb +50 -0
  97. data/lib/graphql/schema/member/has_fields.rb +130 -0
  98. data/lib/graphql/schema/member/instrumentation.rb +115 -0
  99. data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
  100. data/lib/graphql/schema/member.rb +28 -0
  101. data/lib/graphql/schema/middleware_chain.rb +5 -1
  102. data/lib/graphql/schema/mutation.rb +138 -0
  103. data/lib/graphql/schema/non_null.rb +38 -0
  104. data/lib/graphql/schema/object.rb +81 -0
  105. data/lib/graphql/schema/printer.rb +33 -266
  106. data/lib/graphql/schema/relay_classic_mutation.rb +87 -0
  107. data/lib/graphql/schema/rescue_middleware.rb +8 -7
  108. data/lib/graphql/schema/resolver.rb +122 -0
  109. data/lib/graphql/schema/scalar.rb +35 -0
  110. data/lib/graphql/schema/traversal.rb +102 -22
  111. data/lib/graphql/schema/union.rb +36 -0
  112. data/lib/graphql/schema/validation.rb +3 -2
  113. data/lib/graphql/schema.rb +381 -12
  114. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  115. data/lib/graphql/static_validation/literal_validator.rb +16 -4
  116. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
  117. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
  118. data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
  119. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +11 -1
  120. data/lib/graphql/static_validation/validation_context.rb +1 -1
  121. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -5
  122. data/lib/graphql/subscriptions/instrumentation.rb +5 -1
  123. data/lib/graphql/subscriptions/serialize.rb +2 -0
  124. data/lib/graphql/subscriptions.rb +90 -16
  125. data/lib/graphql/tracing/data_dog_tracing.rb +49 -0
  126. data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
  127. data/lib/graphql/tracing/platform_tracing.rb +20 -7
  128. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  129. data/lib/graphql/tracing.rb +1 -0
  130. data/lib/graphql/unresolved_type_error.rb +3 -2
  131. data/lib/graphql/upgrader/member.rb +894 -0
  132. data/lib/graphql/upgrader/schema.rb +37 -0
  133. data/lib/graphql/version.rb +1 -1
  134. data/lib/graphql.rb +5 -25
  135. data/readme.md +2 -2
  136. data/spec/dummy/app/channels/graphql_channel.rb +23 -2
  137. data/spec/dummy/log/development.log +239 -0
  138. data/spec/dummy/log/test.log +410 -0
  139. data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
  140. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
  141. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
  142. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
  143. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
  144. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
  145. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
  146. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
  147. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
  148. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
  149. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
  150. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
  151. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
  152. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
  153. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
  154. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
  155. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
  156. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
  157. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
  158. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
  159. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
  160. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
  161. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
  162. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
  163. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
  164. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
  165. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
  166. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
  167. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
  168. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
  169. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
  170. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  171. data/spec/fixtures/upgrader/account.original.rb +19 -0
  172. data/spec/fixtures/upgrader/account.transformed.rb +20 -0
  173. data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
  174. data/spec/fixtures/upgrader/blame_range.transformed.rb +30 -0
  175. data/spec/fixtures/upgrader/date_time.original.rb +24 -0
  176. data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
  177. data/spec/fixtures/upgrader/delete_project.original.rb +28 -0
  178. data/spec/fixtures/upgrader/delete_project.transformed.rb +27 -0
  179. data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
  180. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
  181. data/spec/fixtures/upgrader/increment_count.original.rb +59 -0
  182. data/spec/fixtures/upgrader/increment_count.transformed.rb +50 -0
  183. data/spec/fixtures/upgrader/photo.original.rb +10 -0
  184. data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
  185. data/spec/fixtures/upgrader/release_order.original.rb +15 -0
  186. data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
  187. data/spec/fixtures/upgrader/starrable.original.rb +49 -0
  188. data/spec/fixtures/upgrader/starrable.transformed.rb +46 -0
  189. data/spec/fixtures/upgrader/subscribable.original.rb +55 -0
  190. data/spec/fixtures/upgrader/subscribable.transformed.rb +51 -0
  191. data/spec/fixtures/upgrader/type_x.original.rb +65 -0
  192. data/spec/fixtures/upgrader/type_x.transformed.rb +56 -0
  193. data/spec/generators/graphql/function_generator_spec.rb +26 -0
  194. data/spec/generators/graphql/install_generator_spec.rb +1 -1
  195. data/spec/generators/graphql/loader_generator_spec.rb +24 -0
  196. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  197. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  198. data/spec/graphql/argument_spec.rb +21 -0
  199. data/spec/graphql/backtrace_spec.rb +10 -0
  200. data/spec/graphql/base_type_spec.rb +42 -0
  201. data/spec/graphql/boolean_type_spec.rb +3 -3
  202. data/spec/graphql/directive_spec.rb +3 -1
  203. data/spec/graphql/enum_type_spec.rb +18 -5
  204. data/spec/graphql/execution/execute_spec.rb +4 -4
  205. data/spec/graphql/execution/instrumentation_spec.rb +165 -0
  206. data/spec/graphql/execution/multiplex_spec.rb +2 -2
  207. data/spec/graphql/execution_error_spec.rb +18 -0
  208. data/spec/graphql/float_type_spec.rb +2 -2
  209. data/spec/graphql/id_type_spec.rb +1 -1
  210. data/spec/graphql/input_object_type_spec.rb +15 -2
  211. data/spec/graphql/int_type_spec.rb +2 -2
  212. data/spec/graphql/interface_type_spec.rb +12 -0
  213. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  214. data/spec/graphql/introspection/schema_type_spec.rb +2 -0
  215. data/spec/graphql/language/block_string_spec.rb +70 -0
  216. data/spec/graphql/language/document_from_schema_definition_spec.rb +770 -0
  217. data/spec/graphql/language/generation_spec.rb +21 -186
  218. data/spec/graphql/language/lexer_spec.rb +21 -1
  219. data/spec/graphql/language/nodes_spec.rb +21 -12
  220. data/spec/graphql/language/parser_spec.rb +1 -1
  221. data/spec/graphql/language/printer_spec.rb +203 -0
  222. data/spec/graphql/object_type_spec.rb +22 -0
  223. data/spec/graphql/query/arguments_spec.rb +25 -15
  224. data/spec/graphql/query/context_spec.rb +18 -0
  225. data/spec/graphql/query/executor_spec.rb +2 -1
  226. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -8
  227. data/spec/graphql/query/variables_spec.rb +42 -1
  228. data/spec/graphql/query_spec.rb +31 -5
  229. data/spec/graphql/rake_task_spec.rb +3 -1
  230. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  231. data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
  232. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  233. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  234. data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
  235. data/spec/graphql/relay/mutation_spec.rb +9 -7
  236. data/spec/graphql/relay/range_add_spec.rb +5 -1
  237. data/spec/graphql/relay/relation_connection_spec.rb +65 -1
  238. data/spec/graphql/schema/argument_spec.rb +87 -0
  239. data/spec/graphql/schema/build_from_definition_spec.rb +89 -5
  240. data/spec/graphql/schema/enum_spec.rb +74 -0
  241. data/spec/graphql/schema/field_spec.rb +225 -0
  242. data/spec/graphql/schema/finder_spec.rb +135 -0
  243. data/spec/graphql/schema/input_object_spec.rb +111 -0
  244. data/spec/graphql/schema/instrumentation_spec.rb +40 -0
  245. data/spec/graphql/schema/interface_spec.rb +185 -0
  246. data/spec/graphql/schema/introspection_system_spec.rb +39 -0
  247. data/spec/graphql/schema/member/accepts_definition_spec.rb +111 -0
  248. data/spec/graphql/schema/member/build_type_spec.rb +17 -0
  249. data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
  250. data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
  251. data/spec/graphql/schema/mutation_spec.rb +148 -0
  252. data/spec/graphql/schema/object_spec.rb +175 -0
  253. data/spec/graphql/schema/printer_spec.rb +111 -15
  254. data/spec/graphql/schema/relay_classic_mutation_spec.rb +38 -0
  255. data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
  256. data/spec/graphql/schema/resolver_spec.rb +131 -0
  257. data/spec/graphql/schema/scalar_spec.rb +95 -0
  258. data/spec/graphql/schema/traversal_spec.rb +31 -0
  259. data/spec/graphql/schema/union_spec.rb +65 -0
  260. data/spec/graphql/schema/validation_spec.rb +1 -1
  261. data/spec/graphql/schema/warden_spec.rb +11 -11
  262. data/spec/graphql/schema_spec.rb +55 -12
  263. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
  264. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
  265. data/spec/graphql/string_type_spec.rb +3 -3
  266. data/spec/graphql/subscriptions_spec.rb +273 -184
  267. data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +1 -1
  268. data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
  269. data/spec/graphql/tracing/platform_tracing_spec.rb +60 -1
  270. data/spec/graphql/union_type_spec.rb +1 -1
  271. data/spec/graphql/upgrader/member_spec.rb +516 -0
  272. data/spec/graphql/upgrader/schema_spec.rb +82 -0
  273. data/spec/spec_helper.rb +8 -0
  274. data/spec/support/dummy/schema.rb +53 -24
  275. data/spec/support/jazz.rb +544 -0
  276. data/spec/support/lazy_helpers.rb +21 -23
  277. data/spec/support/new_relic.rb +24 -0
  278. data/spec/support/star_trek/data.rb +109 -0
  279. data/spec/support/star_trek/schema.rb +388 -0
  280. data/spec/support/star_wars/data.rb +6 -7
  281. data/spec/support/star_wars/schema.rb +127 -171
  282. metadata +233 -11
  283. data/lib/graphql/introspection/arguments_field.rb +0 -7
  284. data/lib/graphql/introspection/enum_values_field.rb +0 -18
  285. data/lib/graphql/introspection/fields_field.rb +0 -13
  286. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  287. data/lib/graphql/introspection/interfaces_field.rb +0 -11
  288. data/lib/graphql/introspection/of_type_field.rb +0 -6
  289. data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -70,10 +70,36 @@ module GraphQL
70
70
  def backtrace
71
71
  GraphQL::Backtrace.new(self)
72
72
  end
73
+
74
+ def execution_errors
75
+ @execution_errors ||= ExecutionErrors.new(self)
76
+ end
77
+ end
78
+
79
+ class ExecutionErrors
80
+ def initialize(ctx)
81
+ @context = ctx
82
+ end
83
+
84
+ def add(err_or_msg)
85
+ err = case err_or_msg
86
+ when String
87
+ GraphQL::ExecutionError.new(err_or_msg)
88
+ when GraphQL::ExecutionError
89
+ err_or_msg
90
+ else
91
+ raise ArgumentError, "expected String or GraphQL::ExecutionError, not #{err_or_msg.class} (#{err_or_msg.inspect})"
92
+ end
93
+ # This will assign ast_node and path
94
+ @context.add_error(err)
95
+ end
96
+
97
+ alias :>> :add
98
+ alias :push :add
73
99
  end
74
100
 
75
101
  include SharedMethods
76
- extend GraphQL::Delegate
102
+ extend Forwardable
77
103
 
78
104
  attr_reader :execution_strategy
79
105
  # `strategy` is required by GraphQL::Batch
@@ -129,6 +155,7 @@ module GraphQL
129
155
  attr_writer :value
130
156
 
131
157
  def_delegators :@provided_values, :[], :[]=, :to_h, :key?, :fetch
158
+ def_delegators :@query, :trace
132
159
 
133
160
  # @!method [](key)
134
161
  # Lookup `key` from the hash passed to {Schema#execute} as `context:`
@@ -162,7 +189,7 @@ module GraphQL
162
189
  class FieldResolutionContext
163
190
  include SharedMethods
164
191
  include Tracing::Traceable
165
- extend GraphQL::Delegate
192
+ extend Forwardable
166
193
 
167
194
  attr_reader :irep_node, :field, :parent_type, :query, :schema, :parent, :key, :type
168
195
  alias :selection :irep_node
@@ -267,3 +294,6 @@ module GraphQL
267
294
  end
268
295
  end
269
296
  end
297
+
298
+
299
+ GraphQL::Schema::Context = GraphQL::Query::Context
@@ -49,6 +49,8 @@ module GraphQL
49
49
  def self.from_arguments(ast_arguments, argument_owner, variables)
50
50
  context = variables ? variables.context : nil
51
51
  values_hash = {}
52
+ defaults_used = Set.new
53
+
52
54
  indexed_arguments = case ast_arguments
53
55
  when Hash
54
56
  ast_arguments
@@ -93,6 +95,7 @@ module GraphQL
93
95
  # then add the default value.
94
96
  if arg_defn.default_value? && !values_hash.key?(arg_name)
95
97
  value = arg_defn.default_value
98
+ defaults_used << arg_name
96
99
  # `context` isn't present when pre-calculating defaults
97
100
  if context
98
101
  value = arg_defn.prepare(value, context)
@@ -105,7 +108,7 @@ module GraphQL
105
108
  end
106
109
  end
107
110
 
108
- argument_owner.arguments_class.new(values_hash)
111
+ argument_owner.arguments_class.new(values_hash, context: context, defaults_used: defaults_used)
109
112
  end
110
113
  end
111
114
  end
@@ -22,7 +22,7 @@ module GraphQL
22
22
  end
23
23
 
24
24
  class << self
25
- extend GraphQL::Delegate
25
+ extend Forwardable
26
26
 
27
27
  def instance
28
28
  @instance = self.new
@@ -6,7 +6,7 @@ module GraphQL
6
6
  # It provides the requested data and
7
7
  # access to the {Query} and {Query::Context}.
8
8
  class Result
9
- extend GraphQL::Delegate
9
+ extend Forwardable
10
10
 
11
11
  def initialize(query:, values:)
12
12
  @query = query
@@ -3,7 +3,7 @@ module GraphQL
3
3
  class Query
4
4
  # Read-only access to query variables, applying default values if needed.
5
5
  class Variables
6
- extend GraphQL::Delegate
6
+ extend Forwardable
7
7
 
8
8
  # @return [Array<GraphQL::Query::VariableValidationError>] Any errors encountered when parsing the provided variables and literal values
9
9
  attr_reader :errors
@@ -13,7 +13,8 @@ module GraphQL
13
13
  def initialize(ctx, ast_variables, provided_variables)
14
14
  schema = ctx.schema
15
15
  @context = ctx
16
- @provided_variables = provided_variables
16
+
17
+ @provided_variables = deep_stringify(provided_variables)
17
18
  @errors = []
18
19
  @storage = ast_variables.each_with_object({}) do |ast_variable, memo|
19
20
  # Find the right value for this variable:
@@ -27,7 +28,7 @@ module GraphQL
27
28
  variable_name = ast_variable.name
28
29
  default_value = ast_variable.default_value
29
30
  provided_value = @provided_variables[variable_name]
30
- value_was_provided = @provided_variables.key?(variable_name)
31
+ value_was_provided = @provided_variables.key?(variable_name)
31
32
 
32
33
  validation_result = variable_type.validate_input(provided_value, ctx)
33
34
  if !validation_result.valid?
@@ -45,6 +46,23 @@ module GraphQL
45
46
  end
46
47
 
47
48
  def_delegators :@storage, :length, :key?, :[], :fetch, :to_h
49
+
50
+ private
51
+
52
+ def deep_stringify(val)
53
+ case val
54
+ when Array
55
+ val.map { |v| deep_stringify(v) }
56
+ when Hash
57
+ new_val = {}
58
+ val.each do |k, v|
59
+ new_val[k.to_s] = deep_stringify(v)
60
+ end
61
+ new_val
62
+ else
63
+ val
64
+ end
65
+ end
48
66
  end
49
67
  end
50
68
  end
data/lib/graphql/query.rb CHANGED
@@ -16,7 +16,7 @@ module GraphQL
16
16
  # A combination of query string and {Schema} instance which can be reduced to a {#result}.
17
17
  class Query
18
18
  include Tracing::Traceable
19
- extend GraphQL::Delegate
19
+ extend Forwardable
20
20
 
21
21
  class OperationNameMissingError < GraphQL::ExecutionError
22
22
  def initialize(name)
@@ -29,7 +29,10 @@ module GraphQL
29
29
  end
30
30
  end
31
31
 
32
- attr_reader :schema, :context, :root_value, :warden, :provided_variables
32
+ attr_reader :schema, :context, :warden, :provided_variables
33
+
34
+ # The value for root types
35
+ attr_accessor :root_value
33
36
 
34
37
  # @return [nil, String] The operation name provided by client or the one inferred from the document. Used to determine which operation to run.
35
38
  attr_accessor :operation_name
@@ -44,6 +47,10 @@ module GraphQL
44
47
  with_prepared_ast { @document }
45
48
  end
46
49
 
50
+ def inspect
51
+ "query ..."
52
+ end
53
+
47
54
  # @return [String, nil] The name of the operation to run (may be inferred)
48
55
  def selected_operation_name
49
56
  return nil unless selected_operation
@@ -72,7 +79,7 @@ module GraphQL
72
79
  def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: {}, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except: nil, only: nil)
73
80
  @schema = schema
74
81
  @filter = schema.default_filter.merge(except: except, only: only)
75
- @context = Context.new(query: self, object: root_value, values: context)
82
+ @context = schema.context_class.new(query: self, object: root_value, values: context)
76
83
  @subscription_topic = subscription_topic
77
84
  @root_value = root_value
78
85
  @fragments = nil
@@ -153,7 +160,7 @@ module GraphQL
153
160
  def result
154
161
  if !@executed
155
162
  with_prepared_ast {
156
- Execution::Multiplex.run_queries(@schema, [self])
163
+ Execution::Multiplex.run_queries(@schema, [self], context: @context)
157
164
  }
158
165
  end
159
166
  @result ||= Query::Result.new(query: self, values: @result_values)
@@ -190,8 +197,11 @@ module GraphQL
190
197
 
191
198
  def irep_selection
192
199
  @selection ||= begin
193
- return nil unless selected_operation
194
- internal_representation.operation_definitions[selected_operation.name]
200
+ if selected_operation && internal_representation
201
+ internal_representation.operation_definitions[selected_operation.name]
202
+ else
203
+ nil
204
+ end
195
205
  end
196
206
  end
197
207
 
@@ -234,6 +244,9 @@ module GraphQL
234
244
  value = abstract_type
235
245
  abstract_type = nil
236
246
  end
247
+ if value.is_a?(GraphQL::Schema::Object)
248
+ value = value.object
249
+ end
237
250
  @resolved_types_cache[abstract_type][value]
238
251
  end
239
252
 
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module GraphQL
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ # Defer this so that you only need the `parser` gem when you _run_ the upgrader
8
+ def load_upgraders
9
+ require_relative './upgrader/member'
10
+ require_relative './upgrader/schema'
11
+ end
12
+
13
+ namespace :graphql do
14
+ task :upgrade, [:dir] do |t, args|
15
+ unless (dir = args[:dir])
16
+ fail 'You have to give me a directory where your GraphQL schema and types live. ' \
17
+ 'For example: `bin/rake graphql:upgrade[app/graphql/**/*]`'
18
+ end
19
+
20
+ Dir[dir].each do |file|
21
+ # Members (types, interfaces, etc.)
22
+ if file =~ /.*_(type|interface|enum|union|)\.rb$/
23
+ Rake::Task["graphql:upgrade:member"].execute(Struct.new(:member_file).new(file))
24
+ end
25
+ end
26
+
27
+ puts "Upgrade complete! Note that this is a best-effort approach, and may very well contain some bugs."
28
+ puts "Don't forget to create the base objects. For example, you could run:"
29
+ puts "\tbin/rake graphql:upgrade:create_base_objects[app/graphql]"
30
+ end
31
+
32
+ namespace :upgrade do
33
+ task :create_base_objects, [:base_dir] do |t, args|
34
+ unless (base_dir = args[:base_dir])
35
+ fail 'You have to give me a directory where your GraphQL types live. ' \
36
+ 'For example: `bin/rake graphql:upgrade:create_base_objects[app/graphql]`'
37
+ end
38
+
39
+ destination_file = File.join(base_dir, "types", "base_scalar.rb")
40
+ unless File.exists?(destination_file)
41
+ FileUtils.mkdir_p(File.dirname(destination_file))
42
+ File.open(destination_file, 'w') do |f|
43
+ f.write "class Types::BaseScalar < GraphQL::Schema::Scalar\nend"
44
+ end
45
+ end
46
+
47
+ destination_file = File.join(base_dir, "types", "base_input_object.rb")
48
+ unless File.exists?(destination_file)
49
+ FileUtils.mkdir_p(File.dirname(destination_file))
50
+ File.open(destination_file, 'w') do |f|
51
+ f.write "class Types::BaseInputObject < GraphQL::Schema::InputObject\nend"
52
+ end
53
+ end
54
+
55
+ destination_file = File.join(base_dir, "types", "base_enum.rb")
56
+ unless File.exists?(destination_file)
57
+ FileUtils.mkdir_p(File.dirname(destination_file))
58
+ File.open(destination_file, 'w') do |f|
59
+ f.write "class Types::BaseEnum < GraphQL::Schema::Enum\nend"
60
+ end
61
+ end
62
+
63
+ destination_file = File.join(base_dir, "types", "base_union.rb")
64
+ unless File.exists?(destination_file)
65
+ FileUtils.mkdir_p(File.dirname(destination_file))
66
+ File.open(destination_file, 'w') do |f|
67
+ f.write "class Types::BaseUnion < GraphQL::Schema::Union\nend"
68
+ end
69
+ end
70
+
71
+ destination_file = File.join(base_dir, "types", "base_interface.rb")
72
+ unless File.exists?(destination_file)
73
+ FileUtils.mkdir_p(File.dirname(destination_file))
74
+ File.open(destination_file, 'w') do |f|
75
+ f.write "module Types::BaseInterface\n include GraphQL::Schema::Interface\nend"
76
+ end
77
+ end
78
+
79
+ destination_file = File.join(base_dir, "types", "base_object.rb")
80
+ unless File.exists?(destination_file)
81
+ File.open(destination_file, 'w') do |f|
82
+ f.write "class Types::BaseObject < GraphQL::Schema::Object\nend"
83
+ end
84
+ end
85
+ end
86
+
87
+ task :schema, [:schema_file] do |t, args|
88
+ schema_file = args.schema_file
89
+ load_upgraders
90
+ upgrader = GraphQL::Upgrader::Schema.new File.read(schema_file)
91
+
92
+ puts "- Transforming schema #{schema_file}"
93
+ File.open(schema_file, 'w') { |f| f.write upgrader.upgrade }
94
+ end
95
+
96
+ task :member, [:member_file] do |t, args|
97
+ member_file = args.member_file
98
+ load_upgraders
99
+ upgrader = GraphQL::Upgrader::Member.new File.read(member_file)
100
+ next unless upgrader.upgradeable?
101
+
102
+ puts "- Transforming member #{member_file}"
103
+ File.open(member_file, 'w') { |f| f.write upgrader.upgrade }
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -41,6 +41,9 @@ module GraphQL
41
41
  ctx.add_error(nodes)
42
42
  nil
43
43
  else
44
+ if parent.is_a?(GraphQL::Schema::Object)
45
+ parent = parent.object
46
+ end
44
47
  connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(nodes)
45
48
  connection_class.new(nodes, args, field: @field, max_page_size: @max_page_size, parent: parent, context: ctx)
46
49
  end
@@ -13,15 +13,17 @@ module GraphQL
13
13
  self.bidirectional_pagination = false
14
14
 
15
15
  # Create a connection which exposes edges of this type
16
- def self.create_type(wrapped_type, edge_type: wrapped_type.edge_type, edge_class: GraphQL::Relay::Edge, nodes_field: ConnectionType.default_nodes_field, &block)
16
+ def self.create_type(wrapped_type, edge_type: nil, edge_class: GraphQL::Relay::Edge, nodes_field: ConnectionType.default_nodes_field, &block)
17
17
  custom_edge_class = edge_class
18
18
 
19
19
  # Any call that would trigger `wrapped_type.ensure_defined`
20
20
  # must be inside this lazy block, otherwise we get weird
21
21
  # cyclical dependency errors :S
22
22
  ObjectType.define do
23
- name("#{wrapped_type.name}Connection")
24
- description("The connection type for #{wrapped_type.name}.")
23
+ type_name = wrapped_type.is_a?(GraphQL::BaseType) ? wrapped_type.name : wrapped_type.graphql_name
24
+ edge_type ||= wrapped_type.edge_type
25
+ name("#{type_name}Connection")
26
+ description("The connection type for #{type_name}.")
25
27
  field :edges, types[edge_type], "A list of edges.", edge_class: custom_edge_class, property: :edge_nodes
26
28
 
27
29
  if nodes_field
@@ -4,7 +4,8 @@ module GraphQL
4
4
  module EdgeType
5
5
  def self.create_type(wrapped_type, name: nil, &block)
6
6
  GraphQL::ObjectType.define do
7
- name("#{wrapped_type.name}Edge")
7
+ type_name = wrapped_type.is_a?(GraphQL::BaseType) ? wrapped_type.name : wrapped_type.graphql_name
8
+ name("#{type_name}Edge")
8
9
  description "An edge in a connection."
9
10
  field :node, wrapped_type, "The item at the end of the edge."
10
11
  field :cursor, !types.String, "A cursor for use in pagination."
@@ -7,7 +7,11 @@ module GraphQL
7
7
  end
8
8
 
9
9
  def call(obj, args, ctx)
10
- ctx.query.schema.id_from_object(obj, @type, ctx)
10
+ if obj.is_a?(GraphQL::Schema::Object)
11
+ obj = obj.object
12
+ end
13
+ type = @type.respond_to?(:graphql_definition) ? @type.graphql_definition : @type
14
+ ctx.query.schema.id_from_object(obj, type, ctx)
11
15
  end
12
16
  end
13
17
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Relay
4
+ # A connection implementation to expose MongoDB collection objects.
5
+ # It works for:
6
+ # - `Mongoid::Criteria`
7
+ class MongoRelationConnection < RelationConnection
8
+ private
9
+
10
+ def relation_offset(relation)
11
+ relation.options.skip
12
+ end
13
+
14
+ def relation_limit(relation)
15
+ relation.options.limit
16
+ end
17
+
18
+ def relation_count(relation)
19
+ # Must perform query (hence #to_a) to count results https://jira.mongodb.org/browse/MONGOID-2325
20
+ relation.to_a.count
21
+ end
22
+
23
+ def limit_nodes(sliced_nodes, limit)
24
+ if limit == 0
25
+ if sliced_nodes.respond_to?(:none) # added in Mongoid 4.0
26
+ sliced_nodes.without_options.none
27
+ else
28
+ sliced_nodes.where(id: nil) # trying to simulate #none for 3.1.7
29
+ end
30
+ else
31
+ sliced_nodes.limit(limit)
32
+ end
33
+ end
34
+ end
35
+
36
+ if defined?(Mongoid::Criteria)
37
+ BaseConnection.register_connection_implementation(Mongoid::Criteria, MongoRelationConnection)
38
+ end
39
+ end
40
+ end
@@ -10,7 +10,7 @@ module GraphQL
10
10
  # By using an instrumention, we can apply our wrapper _last_,
11
11
  # giving users access to the original resolve function in earlier instrumentation.
12
12
  def self.instrument(type, field)
13
- if field.mutation
13
+ if field.mutation.is_a?(GraphQL::Relay::Mutation) || (field.mutation.is_a?(Class) && field.mutation < GraphQL::Schema::RelayClassicMutation)
14
14
  new_resolve = Mutation::Resolve.new(field.mutation, field.resolve_proc)
15
15
  new_lazy_resolve = Mutation::Resolve.new(field.mutation, field.lazy_resolve_proc)
16
16
  field.redefine(resolve: new_resolve, lazy_resolve: new_lazy_resolve)
@@ -10,7 +10,8 @@ module GraphQL
10
10
  def initialize(mutation, resolve)
11
11
  @mutation = mutation
12
12
  @resolve = resolve
13
- @wrap_result = mutation.has_generated_return_type?
13
+ @wrap_result = mutation.is_a?(GraphQL::Relay::Mutation) && mutation.has_generated_return_type?
14
+ @class_based = mutation.is_a?(Class)
14
15
  end
15
16
 
16
17
  def call(obj, args, ctx)
@@ -44,6 +45,9 @@ module GraphQL
44
45
  end
45
46
 
46
47
  @mutation.result_class.new(client_mutation_id: args[:input][:clientMutationId], result: mutation_result)
48
+ elsif @class_based
49
+ mutation_result[:client_mutation_id] = args[:input][:client_mutation_id]
50
+ mutation_result
47
51
  else
48
52
  mutation_result
49
53
  end
@@ -7,11 +7,11 @@ module GraphQL
7
7
  # - `Sequel::Dataset`
8
8
  class RelationConnection < BaseConnection
9
9
  def cursor_from_node(item)
10
- item_index = paged_nodes_array.index(item)
10
+ item_index = paged_nodes.index(item)
11
11
  if item_index.nil?
12
12
  raise("Can't generate cursor, item not found in connection: #{item}")
13
13
  else
14
- offset = item_index + 1 + ((relation_offset(paged_nodes) || 0) - (relation_offset(sliced_nodes) || 0))
14
+ offset = item_index + 1 + ((paged_nodes_offset || 0) - (relation_offset(sliced_nodes) || 0))
15
15
 
16
16
  if after
17
17
  offset += offset_from_cursor(after)
@@ -25,9 +25,9 @@ module GraphQL
25
25
 
26
26
  def has_next_page
27
27
  if first
28
- paged_nodes_length >= first && sliced_nodes_count > first
28
+ paged_nodes.length >= first && sliced_nodes_count > first
29
29
  elsif GraphQL::Relay::ConnectionType.bidirectional_pagination && last
30
- sliced_nodes_count > last
30
+ sliced_nodes_count >= last
31
31
  else
32
32
  false
33
33
  end
@@ -35,7 +35,7 @@ module GraphQL
35
35
 
36
36
  def has_previous_page
37
37
  if last
38
- paged_nodes_length >= last && sliced_nodes_count > last
38
+ paged_nodes.length >= last && sliced_nodes_count > last
39
39
  elsif GraphQL::Relay::ConnectionType.bidirectional_pagination && after
40
40
  # We've already paginated through the collection a bit,
41
41
  # there are nodes behind us
@@ -64,6 +64,7 @@ module GraphQL
64
64
  private
65
65
 
66
66
  # apply first / last limit results
67
+ # @return [Array]
67
68
  def paged_nodes
68
69
  return @paged_nodes if defined? @paged_nodes
69
70
 
@@ -94,7 +95,14 @@ module GraphQL
94
95
  end
95
96
  end
96
97
 
97
- @paged_nodes = items
98
+ # Store this here so we can convert the relation to an Array
99
+ # (this avoids an extra DB call on Sequel)
100
+ @paged_nodes_offset = relation_offset(items)
101
+ @paged_nodes = items.to_a
102
+ end
103
+
104
+ def paged_nodes_offset
105
+ paged_nodes && @paged_nodes_offset
98
106
  end
99
107
 
100
108
  def relation_offset(relation)
@@ -166,19 +174,6 @@ module GraphQL
166
174
  def offset_from_cursor(cursor)
167
175
  decode(cursor).to_i
168
176
  end
169
-
170
- def paged_nodes_array
171
- return @paged_nodes_array if defined?(@paged_nodes_array)
172
- @paged_nodes_array = paged_nodes.to_a
173
- end
174
-
175
- def paged_nodes_length
176
- if paged_nodes.respond_to?(:length)
177
- paged_nodes.length
178
- else
179
- paged_nodes_array.length
180
- end
181
- end
182
177
  end
183
178
 
184
179
  if defined?(ActiveRecord::Relation)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Relay
4
+ # Mixin for Relay-related methods in type objects
5
+ # (used by BaseType and Schema::Member).
6
+ module TypeExtensions
7
+ # @return [GraphQL::ObjectType] The default connection type for this object type
8
+ def connection_type
9
+ @connection_type ||= define_connection
10
+ end
11
+
12
+ # Define a custom connection type for this object type
13
+ # @return [GraphQL::ObjectType]
14
+ def define_connection(**kwargs, &block)
15
+ GraphQL::Relay::ConnectionType.create_type(self, **kwargs, &block)
16
+ end
17
+
18
+ # @return [GraphQL::ObjectType] The default edge type for this object type
19
+ def edge_type
20
+ @edge_type ||= define_edge
21
+ end
22
+
23
+ # Define a custom edge type for this object type
24
+ # @return [GraphQL::ObjectType]
25
+ def define_edge(**kwargs, &block)
26
+ GraphQL::Relay::EdgeType.create_type(self, **kwargs, &block)
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/graphql/relay.rb CHANGED
@@ -9,9 +9,11 @@ require 'graphql/relay/base_connection'
9
9
  require 'graphql/relay/array_connection'
10
10
  require 'graphql/relay/range_add'
11
11
  require 'graphql/relay/relation_connection'
12
+ require 'graphql/relay/mongo_relation_connection'
12
13
  require 'graphql/relay/global_id_resolve'
13
14
  require 'graphql/relay/mutation'
14
15
  require 'graphql/relay/node'
15
16
  require 'graphql/relay/connection_instrumentation'
16
17
  require 'graphql/relay/connection_resolve'
17
18
  require 'graphql/relay/connection_type'
19
+ require 'graphql/relay/type_extensions'
@@ -56,7 +56,7 @@ module GraphQL
56
56
  # This will result in the message of the `GraphQL::CoercionError` being used in the error response:
57
57
  #
58
58
  # @example custom error response
59
- # {"message"=>"cannot coerce `"2"` to Float", "locations"=>[{"line"=>3, "column"=>9}], "fields"=>["arg"]}
59
+ # {"message"=>"cannot coerce `"2"` to Float", "locations"=>[{"line"=>3, "column"=>9}], "fields"=>["arg"]}
60
60
  #
61
61
  class ScalarType < GraphQL::BaseType
62
62
  accepts_definitions :coerce, :coerce_input, :coerce_result
@@ -109,7 +109,19 @@ module GraphQL
109
109
  end
110
110
 
111
111
  def coerce_non_null_input(value, ctx)
112
- @coerce_input_proc.call(value, ctx)
112
+ @coerce_input_proc.call(raw_coercion_input(value), ctx)
113
+ end
114
+
115
+ def raw_coercion_input(value)
116
+ if value.is_a?(GraphQL::Language::Nodes::InputObject)
117
+ value.to_h
118
+ elsif value.is_a?(Array)
119
+ value.map { |element| raw_coercion_input(element) }
120
+ elsif value.is_a?(GraphQL::Language::Nodes::Enum)
121
+ value.name
122
+ else
123
+ value
124
+ end
113
125
  end
114
126
 
115
127
  def validate_non_null_input(value, ctx)