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
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ # These constants are interpreted as GraphQL types when defining fields or arguments
7
+ #
8
+ # @example
9
+ # field :is_draft, Boolean, null: false
10
+ # field :id, ID, null: false
11
+ # field :score, Int, null: false
12
+ #
13
+ # @api private
14
+ module GraphQLTypeNames
15
+ Boolean = "Boolean"
16
+ ID = "ID"
17
+ Int = "Int"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class Member
5
+ module HasArguments
6
+ def self.included(cls)
7
+ cls.extend(ArgumentClassAccessor)
8
+ end
9
+
10
+ def self.extended(cls)
11
+ cls.extend(ArgumentClassAccessor)
12
+ end
13
+
14
+ # @see {GraphQL::Schema::Argument#initialize} for parameters
15
+ # @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
16
+ def argument(*args, **kwargs, &block)
17
+ kwargs[:owner] = self
18
+ arg_defn = self.argument_class.new(*args, **kwargs, &block)
19
+ own_arguments[arg_defn.name] = arg_defn
20
+ end
21
+
22
+ # @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
23
+ def arguments
24
+ inherited_arguments = ((self.is_a?(Class) && superclass.respond_to?(:arguments)) ? superclass.arguments : {})
25
+ # Local definitions override inherited ones
26
+ inherited_arguments.merge(own_arguments)
27
+ end
28
+
29
+ # @param new_arg_class [Class] A class to use for building argument definitions
30
+ def argument_class(new_arg_class = nil)
31
+ self.class.argument_class(new_arg_class)
32
+ end
33
+
34
+ module ArgumentClassAccessor
35
+ def argument_class(new_arg_class = nil)
36
+ if new_arg_class
37
+ @argument_class = new_arg_class
38
+ else
39
+ @argument_class || (superclass.respond_to?(:argument_class) ? superclass.argument_class : GraphQL::Schema::Argument)
40
+ end
41
+ end
42
+ end
43
+
44
+ def own_arguments
45
+ @own_arguments ||= {}
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class Member
5
+ # Shared code for Object and Interface
6
+ module HasFields
7
+ class << self
8
+ # When this module is added to a class,
9
+ # add a place for that class's default behaviors
10
+ def self.extended(child_class)
11
+ add_default_resolve_module(child_class)
12
+ super
13
+ end
14
+
15
+ # Create a module which will have instance methods for implementing fields.
16
+ # These will be `super` methods for fields in interfaces, objects and mutations.
17
+ # Use an instance variable on the class instead of a constant
18
+ # so that module namespaces won't be an issue. (If we used constants,
19
+ # `child_class::DefaultResolve` might find a constant from an included module.)
20
+ def add_default_resolve_module(child_class)
21
+ if child_class.instance_variable_get(:@_default_resolve)
22
+ # This can happen when an object implements an interface,
23
+ # since that interface has the `included` hook above.
24
+ return
25
+ end
26
+
27
+ default_resolve_module = Module.new
28
+ child_class.instance_variable_set(:@_default_resolve, default_resolve_module)
29
+ child_class.include(default_resolve_module)
30
+ end
31
+ end
32
+
33
+ # When this is included into interfaces,
34
+ # add a place for default field behaviors
35
+ def included(child_class)
36
+ HasFields.add_default_resolve_module(child_class)
37
+ # Also, prepare a place for default field implementations
38
+ super
39
+ end
40
+
41
+ # When a subclass of objects are created,
42
+ # add a place for that subclass's default field behaviors
43
+ def inherited(child_class)
44
+ HasFields.add_default_resolve_module(child_class)
45
+ super
46
+ end
47
+
48
+ # Add a field to this object or interface with the given definition
49
+ # @see {GraphQL::Schema::Field#initialize} for method signature
50
+ # @return [void]
51
+ def field(*args, **kwargs, &block)
52
+ field_defn = field_class.from_options(*args, owner: self, **kwargs, &block)
53
+ add_field(field_defn)
54
+ nil
55
+ end
56
+
57
+ # @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
58
+ def fields
59
+ # Local overrides take precedence over inherited fields
60
+ all_fields = {}
61
+ ancestors.reverse_each do |ancestor|
62
+ if ancestor.respond_to?(:own_fields)
63
+ all_fields.merge!(ancestor.own_fields)
64
+ end
65
+ end
66
+ all_fields
67
+ end
68
+
69
+ # Register this field with the class, overriding a previous one if needed.
70
+ # Also, add a parent method for resolving this field.
71
+ # @param field_defn [GraphQL::Schema::Field]
72
+ # @return [void]
73
+ def add_field(field_defn)
74
+ own_fields[field_defn.name] = field_defn
75
+ if !method_defined?(field_defn.method_sym)
76
+ # Only add the super method if there isn't one already.
77
+ add_super_method(field_defn.name.inspect, field_defn.method_sym)
78
+ end
79
+ nil
80
+ end
81
+
82
+ # @return [Class] The class to initialize when adding fields to this kind of schema member
83
+ def field_class(new_field_class = nil)
84
+ if new_field_class
85
+ @field_class = new_field_class
86
+ elsif @field_class
87
+ @field_class
88
+ elsif self.is_a?(Class)
89
+ superclass.respond_to?(:field_class) ? superclass.field_class : GraphQL::Schema::Field
90
+ else
91
+ ancestor = ancestors[1..-1].find { |a| a.respond_to?(:field_class) && a.field_class }
92
+ ancestor ? ancestor.field_class : GraphQL::Schema::Field
93
+ end
94
+ end
95
+
96
+ def global_id_field(field_name)
97
+ field field_name, "ID", null: false, resolve: GraphQL::Relay::GlobalIdResolve.new(type: self)
98
+ end
99
+
100
+ # @return [Array<GraphQL::Schema::Field>] Fields defined on this class _specifically_, not parent classes
101
+ def own_fields
102
+ @own_fields ||= {}
103
+ end
104
+
105
+ private
106
+ # Find the magic module for holding super methods,
107
+ # and add a field named `method_name` for implementing the field
108
+ # called `field_name`.
109
+ # It will be the `super` method if the method is overwritten in the class definition.
110
+ def add_super_method(field_key, method_name)
111
+ default_resolve_module = @_default_resolve
112
+ if default_resolve_module.nil?
113
+ # This should have been set up in one of the inherited or included hooks above,
114
+ # if it wasn't, it's because those hooks weren't called because `super` wasn't present.
115
+ raise <<-ERR
116
+ Uh oh! #{self} doesn't have a default resolve module. This probably means that an `inherited` hook didn't call super.
117
+ Check `inherited` on #{self}'s superclasses.
118
+ ERR
119
+ end
120
+ default_resolve_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
121
+ def #{method_name}(**args)
122
+ field_inst = self.class.fields[#{field_key}] || raise(%|Failed to find field #{field_key} for \#{self.class} among \#{self.class.fields.keys}|)
123
+ field_inst.resolve_field_method(self, args, context)
124
+ end
125
+ RUBY
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+ # test_via: ../object.rb
3
+
4
+ module GraphQL
5
+ class Schema
6
+ class Member
7
+ module Instrumentation
8
+ module_function
9
+ def instrument(type, field)
10
+ return_type = field.type.unwrap
11
+ if (return_type.is_a?(GraphQL::ObjectType) && return_type.metadata[:type_class]) ||
12
+ return_type.is_a?(GraphQL::InterfaceType) ||
13
+ (return_type.is_a?(GraphQL::UnionType) && return_type.possible_types.any? { |t| t.metadata[:type_class] })
14
+ field = apply_proxy(field)
15
+ end
16
+
17
+ field
18
+ end
19
+
20
+ def before_query(query)
21
+ # Get the root type for this query
22
+ root_node = query.irep_selection
23
+ if root_node.nil?
24
+ # It's an invalid query, nothing to do here
25
+ else
26
+ root_type = query.irep_selection.return_type
27
+ # If it has a wrapper, apply it
28
+ wrapper_class = root_type.metadata[:type_class]
29
+ if wrapper_class
30
+ new_root_value = wrapper_class.new(query.root_value, query.context)
31
+ query.root_value = new_root_value
32
+ end
33
+ end
34
+ end
35
+
36
+ def after_query(_query)
37
+ end
38
+
39
+ private
40
+
41
+ module_function
42
+
43
+ def apply_proxy(field)
44
+ resolve_proc = field.resolve_proc
45
+ lazy_resolve_proc = field.lazy_resolve_proc
46
+ inner_return_type = field.type.unwrap
47
+ depth = list_depth(field.type)
48
+
49
+ field.redefine(
50
+ resolve: ProxiedResolve.new(inner_resolve: resolve_proc, list_depth: depth, inner_return_type: inner_return_type),
51
+ lazy_resolve: ProxiedResolve.new(inner_resolve: lazy_resolve_proc, list_depth: depth, inner_return_type: inner_return_type),
52
+ )
53
+ end
54
+
55
+ def list_depth(type, starting_at = 0)
56
+ case type
57
+ when GraphQL::ListType
58
+ list_depth(type.of_type, starting_at + 1)
59
+ when GraphQL::NonNullType
60
+ list_depth(type.of_type, starting_at)
61
+ else
62
+ starting_at
63
+ end
64
+ end
65
+
66
+ class ProxiedResolve
67
+ def initialize(inner_resolve:, list_depth:, inner_return_type:)
68
+ @inner_resolve = inner_resolve
69
+ @inner_return_type = inner_return_type
70
+ @list_depth = list_depth
71
+ end
72
+
73
+ def call(obj, args, ctx)
74
+ result = @inner_resolve.call(obj, args, ctx)
75
+ if ctx.schema.lazy?(result)
76
+ # Wrap it later
77
+ result
78
+ elsif ctx.skip == result
79
+ result
80
+ else
81
+ proxy_to_depth(result, @list_depth, @inner_return_type, ctx)
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def proxy_to_depth(obj, depth, type, ctx)
88
+ if obj.nil?
89
+ obj
90
+ elsif depth > 0
91
+ obj.map { |inner_obj| proxy_to_depth(inner_obj, depth - 1, type, ctx) }
92
+ else
93
+ concrete_type = case type
94
+ when GraphQL::UnionType, GraphQL::InterfaceType
95
+ ctx.query.resolve_type(type, obj)
96
+ when GraphQL::ObjectType
97
+ type
98
+ else
99
+ raise "unexpected proxying type #{type} for #{obj} at #{ctx.owner_type}.#{ctx.field.name}"
100
+ end
101
+
102
+ if concrete_type && (object_class = concrete_type.metadata[:type_class])
103
+ # use the query-level context here, since it won't be field-specific anyways
104
+ query_ctx = ctx.query.context
105
+ object_class.new(obj, query_ctx)
106
+ else
107
+ obj
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ module TypeSystemHelpers
7
+ # @return [Schema::NonNull] Make a non-null-type representation of this type
8
+ def to_non_null_type
9
+ GraphQL::Schema::NonNull.new(self)
10
+ end
11
+
12
+ # @return [Schema::List] Make a list-type representation of this type
13
+ def to_list_type
14
+ GraphQL::Schema::List.new(self)
15
+ end
16
+
17
+ # @return [Boolean] true if this is a non-nullable type. A nullable list of non-nullables is considered nullable.
18
+ def non_null?
19
+ false
20
+ end
21
+
22
+ # @return [Boolean] true if this is a list type. A non-nullable list is considered a list.
23
+ def list?
24
+ false
25
+ end
26
+
27
+ # @return [GraphQL::TypeKinds::TypeKind]
28
+ def kind
29
+ raise NotImplementedError
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ require 'graphql/schema/member/accepts_definition'
3
+ require 'graphql/schema/member/base_dsl_methods'
4
+ require 'graphql/schema/member/cached_graphql_definition'
5
+ require 'graphql/schema/member/graphql_type_names'
6
+ require 'graphql/schema/member/type_system_helpers'
7
+ require "graphql/relay/type_extensions"
8
+
9
+ module GraphQL
10
+ # The base class for things that make up the schema,
11
+ # eg objects, enums, scalars.
12
+ #
13
+ # @api private
14
+ class Schema
15
+ class Member
16
+ include GraphQLTypeNames
17
+ extend CachedGraphQLDefinition
18
+ extend GraphQL::Relay::TypeExtensions
19
+ extend BaseDSLMethods
20
+ extend TypeSystemHelpers
21
+ end
22
+ end
23
+ end
24
+
25
+ require 'graphql/schema/member/has_arguments'
26
+ require 'graphql/schema/member/has_fields'
27
+ require 'graphql/schema/member/instrumentation'
28
+ require 'graphql/schema/member/build_type'
@@ -5,7 +5,7 @@ module GraphQL
5
5
  #
6
6
  # Steps should call `next_step.call` to continue the chain, or _not_ call it to stop the chain.
7
7
  class MiddlewareChain
8
- extend GraphQL::Delegate
8
+ extend Forwardable
9
9
 
10
10
  # @return [Array<#call(*args)>] Steps in this chain, will be called with arguments and `next_middleware`
11
11
  attr_reader :steps, :final_step
@@ -38,6 +38,10 @@ module GraphQL
38
38
  invoke_core(0, arguments)
39
39
  end
40
40
 
41
+ def concat(callables)
42
+ callables.each { |c| add_middleware(c) }
43
+ end
44
+
41
45
  private
42
46
 
43
47
  def invoke_core(index, arguments)
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # This base class accepts configuration for a mutation root field,
6
+ # then it can be hooked up to your mutation root object type.
7
+ #
8
+ # If you want to customize how this class generates types, in your base class,
9
+ # override the various `generate_*` methods.
10
+ #
11
+ # @see {GraphQL::Schema::RelayClassicMutation} for an extension of this class with some conventions built-in.
12
+ #
13
+ # @example Creating a comment
14
+ # # Define the mutation:
15
+ # class Mutations::CreateComment < GraphQL::Schema::Mutation
16
+ # argument :body, String, required: true
17
+ # argument :post_id, ID, required: true
18
+ #
19
+ # field :comment, Types::Comment, null: true
20
+ # field :error_messages, [String], null: false
21
+ #
22
+ # def resolve(body:, post_id:)
23
+ # post = Post.find(post_id)
24
+ # comment = post.comments.build(body: body, author: context[:current_user])
25
+ # if comment.save
26
+ # # Successful creation, return the created object with no errors
27
+ # {
28
+ # comment: comment,
29
+ # errors: [],
30
+ # }
31
+ # else
32
+ # # Failed save, return the errors to the client
33
+ # {
34
+ # comment: nil,
35
+ # errors: comment.errors.full_messages
36
+ # }
37
+ # end
38
+ # end
39
+ # end
40
+ #
41
+ # # Hook it up to your mutation:
42
+ # class Types::Mutation < GraphQL::Schema::Object
43
+ # field :create_comment, mutation: Mutations::CreateComment
44
+ # end
45
+ #
46
+ # # Call it from GraphQL:
47
+ # result = MySchema.execute <<-GRAPHQL
48
+ # mutation {
49
+ # createComment(postId: "1", body: "Nice Post!") {
50
+ # errors
51
+ # comment {
52
+ # body
53
+ # author {
54
+ # login
55
+ # }
56
+ # }
57
+ # }
58
+ # }
59
+ # GRAPHQL
60
+ #
61
+ class Mutation < GraphQL::Schema::Resolver
62
+ extend GraphQL::Schema::Member::HasFields
63
+
64
+ class << self
65
+ # Override this method to handle legacy-style usages of `MyMutation.field`
66
+ def field(*args, &block)
67
+ if args.none?
68
+ raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ # Call this method to get the derived return type of the mutation,
75
+ # or use it as a configuration method to assign a return type
76
+ # instead of generating one.
77
+ # @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
78
+ # @return [Class] The object type which this mutation returns.
79
+ def payload_type(new_payload_type = nil)
80
+ if new_payload_type
81
+ @payload_type = new_payload_type
82
+ end
83
+ @payload_type ||= generate_payload_type
84
+ end
85
+
86
+ alias :type :payload_type
87
+ alias :type_expr :payload_type
88
+
89
+ # An object class to use for deriving payload types
90
+ # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
91
+ # @return [Class]
92
+ def object_class(new_class = nil)
93
+ if new_class
94
+ @object_class = new_class
95
+ end
96
+ @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
97
+ end
98
+
99
+ def field_class(new_class = nil)
100
+ if new_class
101
+ @field_class = new_class
102
+ else
103
+ @field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
104
+ end
105
+ end
106
+
107
+ # An object class to use for deriving return types
108
+ # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
109
+ # @return [Class]
110
+ def object_class(new_class = nil)
111
+ if new_class
112
+ @object_class = new_class
113
+ end
114
+ @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
115
+ end
116
+
117
+ private
118
+
119
+ # Build a subclass of {.object_class} based on `self`.
120
+ # This value will be cached as `{.payload_type}`.
121
+ # Override this hook to customize return type generation.
122
+ def generate_payload_type
123
+ mutation_name = graphql_name
124
+ mutation_fields = fields
125
+ mutation_class = self
126
+ Class.new(object_class) do
127
+ graphql_name("#{mutation_name}Payload")
128
+ description("Autogenerated return type of #{mutation_name}")
129
+ mutation(mutation_class)
130
+ mutation_fields.each do |name, f|
131
+ field(name, field: f)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # Wraps a {Schema::Member} when it is required.
6
+ # @see {Schema::Member::TypeSystemHelpers#to_non_null_type}
7
+ class NonNull
8
+ include GraphQL::Schema::Member::CachedGraphQLDefinition
9
+ include GraphQL::Schema::Member::TypeSystemHelpers
10
+ attr_reader :of_type
11
+ def initialize(of_type)
12
+ @of_type = of_type
13
+ end
14
+
15
+ def to_graphql
16
+ @of_type.graphql_definition.to_non_null_type
17
+ end
18
+
19
+ # @return [true]
20
+ def non_null?
21
+ true
22
+ end
23
+
24
+ # @return [Boolean] True if this type wraps a list type
25
+ def list?
26
+ @of_type.list?
27
+ end
28
+
29
+ def kind
30
+ GraphQL::TypeKinds::NON_NULL
31
+ end
32
+
33
+ def unwrap
34
+ @of_type.unwrap
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Object < GraphQL::Schema::Member
6
+ extend GraphQL::Schema::Member::AcceptsDefinition
7
+ extend GraphQL::Schema::Member::HasFields
8
+
9
+ # @return [Object] the application object this type is wrapping
10
+ attr_reader :object
11
+
12
+ # @return [GraphQL::Query::Context] the context instance for this query
13
+ attr_reader :context
14
+
15
+ def initialize(object, context)
16
+ @object = object
17
+ @context = context
18
+ end
19
+
20
+ class << self
21
+ def implements(*new_interfaces)
22
+ new_interfaces.each do |int|
23
+ if int.is_a?(Module)
24
+ # Include the methods here,
25
+ # `.fields` will use the inheritance chain
26
+ # to find inherited fields
27
+ include(int)
28
+ end
29
+ end
30
+ own_interfaces.concat(new_interfaces)
31
+ end
32
+
33
+ def interfaces
34
+ own_interfaces + (superclass <= GraphQL::Schema::Object ? superclass.interfaces : [])
35
+ end
36
+
37
+ def own_interfaces
38
+ @own_interfaces ||= []
39
+ end
40
+
41
+ # Include legacy-style interfaces, too
42
+ def fields
43
+ all_fields = super
44
+ interfaces.each do |int|
45
+ if int.is_a?(GraphQL::InterfaceType)
46
+ int_f = {}
47
+ int.fields.each do |name, legacy_field|
48
+ int_f[name] = field_class.from_options(name, field: legacy_field)
49
+ end
50
+ all_fields = int_f.merge(all_fields)
51
+ end
52
+ end
53
+ all_fields
54
+ end
55
+
56
+ # @return [GraphQL::ObjectType]
57
+ def to_graphql
58
+ obj_type = GraphQL::ObjectType.new
59
+ obj_type.name = graphql_name
60
+ obj_type.description = description
61
+ obj_type.interfaces = interfaces
62
+ obj_type.introspection = introspection
63
+ obj_type.mutation = mutation
64
+
65
+ fields.each do |field_name, field_inst|
66
+ field_defn = field_inst.to_graphql
67
+ obj_type.fields[field_defn.name] = field_defn
68
+ end
69
+
70
+ obj_type.metadata[:type_class] = self
71
+
72
+ obj_type
73
+ end
74
+
75
+ def kind
76
+ GraphQL::TypeKinds::OBJECT
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end