graphql 1.7.6 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
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