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
@@ -149,6 +149,15 @@ module Dummy
149
149
  field :cheese, CheeseType
150
150
  end
151
151
 
152
+ TracingScalarType = GraphQL::ObjectType.define do
153
+ name "TracingScalar"
154
+ description "An object which has traced scalars"
155
+
156
+ field :traceNil, types.Int
157
+ field :traceFalse, types.Int, trace: false
158
+ field :traceTrue, types.Int, trace: true
159
+ end
160
+
152
161
  DairyProductUnion = GraphQL::UnionType.define do
153
162
  name "DairyProduct"
154
163
  description "Kinds of food made from milk"
@@ -214,10 +223,7 @@ module Dummy
214
223
  description "Where it came from"
215
224
  end
216
225
 
217
- input_field :originDairy, types.String, "Dairy which produced it", default_value: "Sugar Hollow Dairy" do
218
- description "Ignored because arg takes precedence"
219
- default_value "Ignored because keyword arg takes precedence"
220
- end
226
+ input_field :originDairy, types.String, "Dairy which produced it", default_value: "Sugar Hollow Dairy"
221
227
 
222
228
  input_field :fatContent, types.Float, "How much fat it has" do
223
229
  # ensure we can define default in block
@@ -360,6 +366,14 @@ module Dummy
360
366
  }
361
367
  end
362
368
 
369
+ field :multipleErrorsOnNonNullableField do
370
+ type !GraphQL::STRING_TYPE
371
+ resolve ->(t, a, c) {
372
+ [GraphQL::ExecutionError.new("This is an error message for some error."),
373
+ GraphQL::ExecutionError.new("This is another error message for a different error.")]
374
+ }
375
+ end
376
+
363
377
  field :executionErrorWithOptions do
364
378
  type GraphQL::INT_TYPE
365
379
  resolve ->(t, a, c) {
@@ -372,6 +386,16 @@ module Dummy
372
386
  resolve ->(t, a, c) { OpenStruct.new(cheese: nil) }
373
387
  end
374
388
 
389
+ field :tracingScalar, TracingScalarType do
390
+ resolve ->(o, a, c) do
391
+ OpenStruct.new(
392
+ traceNil: 2,
393
+ traceFalse: 3,
394
+ tracetrue: 5,
395
+ )
396
+ end
397
+ end
398
+
375
399
  field :deepNonNull, !DeepNonNullType do
376
400
  resolve ->(o, a, c) { :deepNonNull }
377
401
  end
@@ -384,26 +408,31 @@ module Dummy
384
408
  input_field :values, !types[!types.Int]
385
409
  end
386
410
 
387
- DairyAppMutationType = GraphQL::ObjectType.define do
388
- name "Mutation"
411
+ PushValueField = GraphQL::Field.define do
412
+ name :pushValue
413
+ type !types[!types.Int]
414
+ description("Push a value onto a global array :D")
415
+ argument :value, !types.Int, as: :val
416
+ resolve ->(o, args, ctx) {
417
+ GLOBAL_VALUES << args.val
418
+ GLOBAL_VALUES
419
+ }
420
+ end
421
+
422
+ class DairyAppMutationType < GraphQL::Schema::Object
423
+ graphql_name "Mutation"
389
424
  description "The root for mutations in this schema"
390
- field :pushValue, !types[!types.Int] do
391
- description("Push a value onto a global array :D")
392
- argument :value, !types.Int, as: :val
393
- resolve ->(o, args, ctx) {
394
- GLOBAL_VALUES << args.val
395
- GLOBAL_VALUES
396
- }
425
+ # Test the `field:` compatibility option
426
+ field :pushValue, field: PushValueField
427
+
428
+ field :replaceValues, [Integer], "Replace the global array with new values", null: false do
429
+ argument :input, ReplaceValuesInputType, required: true
397
430
  end
398
431
 
399
- field :replaceValues, !types[!types.Int] do
400
- description("Replace the global array with new values")
401
- argument :input, !ReplaceValuesInputType
402
- resolve ->(o, args, ctx) {
403
- GLOBAL_VALUES.clear
404
- GLOBAL_VALUES.push(*args.input[:values])
405
- GLOBAL_VALUES
406
- }
432
+ def replace_values(input:)
433
+ GLOBAL_VALUES.clear
434
+ GLOBAL_VALUES.concat(input["values"])
435
+ GLOBAL_VALUES
407
436
  end
408
437
  end
409
438
 
@@ -414,7 +443,7 @@ module Dummy
414
443
  end
415
444
  end
416
445
 
417
- Schema = GraphQL::Schema.define do
446
+ class Schema < GraphQL::Schema
418
447
  query DairyAppQueryType
419
448
  mutation DairyAppMutationType
420
449
  subscription SubscriptionType
@@ -423,8 +452,8 @@ module Dummy
423
452
 
424
453
  rescue_from(NoSuchDairyError) { |err| err.message }
425
454
 
426
- resolve_type ->(type, obj, ctx) {
455
+ def self.resolve_type(type, obj, ctx)
427
456
  Schema.types[obj.class.name.split("::").last]
428
- }
457
+ end
429
458
  end
430
459
  end
@@ -0,0 +1,544 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Here's the "application"
4
+ module Jazz
5
+ module Models
6
+ Instrument = Struct.new(:name, :family)
7
+ Ensemble = Struct.new(:name)
8
+ Musician = Struct.new(:name, :favorite_key)
9
+ Key = Struct.new(:root, :sharp, :flat) do
10
+ def self.from_notation(key_str)
11
+ key, sharp_or_flat = key_str.split("")
12
+ sharp = sharp_or_flat == "♯"
13
+ flat = sharp_or_flat == "♭"
14
+ Models::Key.new(key, sharp, flat)
15
+ end
16
+
17
+ def to_notation
18
+ "#{root}#{sharp ? "♯" : ""}#{flat ? "♭" : ""}"
19
+ end
20
+ end
21
+
22
+ def self.reset
23
+ @data = {
24
+ "Instrument" => [
25
+ Models::Instrument.new("Banjo", :str),
26
+ Models::Instrument.new("Flute", "WOODWIND"),
27
+ Models::Instrument.new("Trumpet", "BRASS"),
28
+ Models::Instrument.new("Piano", "KEYS"),
29
+ Models::Instrument.new("Organ", "KEYS"),
30
+ Models::Instrument.new("Drum Kit", "PERCUSSION"),
31
+ ],
32
+ "Ensemble" => [
33
+ Models::Ensemble.new("Bela Fleck and the Flecktones"),
34
+ Models::Ensemble.new("Robert Glasper Experiment"),
35
+ ],
36
+ "Musician" => [
37
+ Models::Musician.new("Herbie Hancock", Models::Key.from_notation("B♭")),
38
+ ]
39
+ }
40
+ end
41
+
42
+ def self.data
43
+ @data || reset
44
+ end
45
+ end
46
+
47
+ class BaseArgument < GraphQL::Schema::Argument
48
+ def initialize(name, type, desc = nil, custom: nil, **kwargs)
49
+ @custom = custom
50
+ super(name, type, desc, **kwargs)
51
+ end
52
+
53
+ def to_graphql
54
+ arg_defn = super
55
+ arg_defn.metadata[:custom] = @custom
56
+ arg_defn
57
+ end
58
+ end
59
+
60
+ # A custom field class that supports the `upcase:` option
61
+ class BaseField < GraphQL::Schema::Field
62
+ argument_class BaseArgument
63
+ def initialize(*args, **options, &block)
64
+ @upcase = options.delete(:upcase)
65
+ super(*args, **options, &block)
66
+ end
67
+
68
+ def resolve_field(*)
69
+ result = super
70
+ if @upcase && result
71
+ result.upcase
72
+ else
73
+ result
74
+ end
75
+ end
76
+ end
77
+
78
+ class BaseObject < GraphQL::Schema::Object
79
+ # Use this overridden field class
80
+ field_class BaseField
81
+
82
+ class << self
83
+ def config(key, value)
84
+ configs[key] = value
85
+ end
86
+
87
+ def configs
88
+ @configs ||= {}
89
+ end
90
+
91
+ def to_graphql
92
+ type_defn = super
93
+ configs.each do |k,v|
94
+ type_defn.metadata[k] = v
95
+ end
96
+ type_defn
97
+ end
98
+ end
99
+ end
100
+
101
+ module BaseInterface
102
+ include GraphQL::Schema::Interface
103
+ # Use this overridden field class
104
+ field_class BaseField
105
+
106
+ # These methods are available to child interfaces
107
+ definition_methods do
108
+ def upcased_field(*args, **kwargs, &block)
109
+ field(*args, upcase: true, **kwargs, &block)
110
+ end
111
+ end
112
+ end
113
+
114
+ class BaseEnumValue < GraphQL::Schema::EnumValue
115
+ def initialize(*args, custom_setting: nil, **kwargs, &block)
116
+ @custom_setting = custom_setting
117
+ super(*args, **kwargs, &block)
118
+ end
119
+
120
+ def to_graphql
121
+ enum_value_defn = super
122
+ enum_value_defn.metadata[:custom_setting] = @custom_setting
123
+ enum_value_defn
124
+ end
125
+ end
126
+
127
+ class BaseEnum < GraphQL::Schema::Enum
128
+ enum_value_class BaseEnumValue
129
+ end
130
+
131
+ # Some arbitrary global ID scheme
132
+ # *Type suffix is removed automatically
133
+ module GloballyIdentifiableType
134
+ include BaseInterface
135
+ description "A fetchable object in the system"
136
+ field(
137
+ name: :id,
138
+ type: ID,
139
+ null: false,
140
+ description: "A unique identifier for this object",
141
+ )
142
+ upcased_field :upcased_id, ID, null: false, method: :id # upcase: true added by helper
143
+
144
+ def id
145
+ GloballyIdentifiableType.to_id(@object)
146
+ end
147
+
148
+ def self.to_id(object)
149
+ "#{object.class.name.split("::").last}/#{object.name}"
150
+ end
151
+
152
+ def self.find(id)
153
+ class_name, object_name = id.split("/")
154
+ Models.data[class_name].find { |obj| obj.name == object_name }
155
+ end
156
+ end
157
+
158
+ # A legacy-style interface used by new-style types
159
+ NamedEntity = GraphQL::InterfaceType.define do
160
+ name "NamedEntity"
161
+ field :name, !types.String
162
+ end
163
+
164
+ # test field inheritance
165
+ class ObjectWithUpcasedName < BaseObject
166
+ # Test extra arguments:
167
+ field :upcase_name, String, null: false, upcase: true
168
+
169
+ def upcase_name
170
+ object.name # upcase is applied by the superclass
171
+ end
172
+ end
173
+
174
+ module HasMusicians
175
+ include BaseInterface
176
+ field :musicians, "[Jazz::Musician]", null: false
177
+ end
178
+
179
+
180
+ # Here's a new-style GraphQL type definition
181
+ class Ensemble < ObjectWithUpcasedName
182
+ # Test string type names
183
+ # This method should override inherited one
184
+ field :name, "String", null: false, method: :overridden_name
185
+ implements GloballyIdentifiableType, NamedEntity, HasMusicians
186
+ description "A group of musicians playing together"
187
+ config :config, :configged
188
+ field :formed_at, String, null: true, hash_key: "formedAtDate"
189
+
190
+ def overridden_name
191
+ @object.name.sub("Robert Glasper", "ROBERT GLASPER")
192
+ end
193
+ end
194
+
195
+ class Family < BaseEnum
196
+ description "Groups of musical instruments"
197
+ # support string and symbol
198
+ value "STRING", "Makes a sound by vibrating strings", value: :str, custom_setting: 1
199
+ value :WOODWIND, "Makes a sound by vibrating air in a pipe"
200
+ value :BRASS, "Makes a sound by amplifying the sound of buzzing lips"
201
+ value "PERCUSSION", "Makes a sound by hitting something that vibrates"
202
+ value "DIDGERIDOO", "Makes a sound by amplifying the sound of buzzing lips", deprecation_reason: "Merged into BRASS"
203
+ value "KEYS" do
204
+ description "Neither here nor there, really"
205
+ end
206
+ end
207
+
208
+ # Lives side-by-side with an old-style definition
209
+ using GraphQL::DeprecatedDSL # for ! and types[]
210
+ InstrumentType = GraphQL::ObjectType.define do
211
+ name "Instrument"
212
+ interfaces [NamedEntity]
213
+ implements GloballyIdentifiableType
214
+
215
+ field :id, !types.ID, "A unique identifier for this object", resolve: ->(obj, args, ctx) { GloballyIdentifiableType.to_id(obj) }
216
+ field :upcasedId, !types.ID, resolve: ->(obj, args, ctx) { GloballyIdentifiableType.to_id(obj).upcase }
217
+ if RUBY_ENGINE == "jruby"
218
+ # JRuby doesn't support refinements, so the `using` above won't work
219
+ field :family, Family.to_non_null_type
220
+ else
221
+ field :family, !Family
222
+ end
223
+ end
224
+
225
+ class Key < GraphQL::Schema::Scalar
226
+ description "A musical key"
227
+ def self.coerce_input(val, ctx)
228
+ Models::Key.from_notation(val)
229
+ end
230
+
231
+ def self.coerce_result(val, ctx)
232
+ val.to_notation
233
+ end
234
+ end
235
+
236
+ class RawJson < GraphQL::Schema::Scalar
237
+ def self.coerce_input(val, ctx)
238
+ val
239
+ end
240
+
241
+ def self.coerce_result(val, ctx)
242
+ val
243
+ end
244
+ end
245
+
246
+ class Musician < BaseObject
247
+ implements GloballyIdentifiableType
248
+ implements NamedEntity
249
+ description "Someone who plays an instrument"
250
+ field :instrument, InstrumentType, null: false do
251
+ description "An object played in order to produce music"
252
+ end
253
+ field :favorite_key, Key, null: true
254
+ # Test lists with nullable members:
255
+ field :inspect_context, [String, null: true], null: false
256
+ field :add_error, String, null: false, extras: [:execution_errors]
257
+ def inspect_context
258
+ [
259
+ @context.custom_method,
260
+ @context[:magic_key],
261
+ @context[:normal_key],
262
+ nil,
263
+ ]
264
+ end
265
+
266
+ def add_error(execution_errors:)
267
+ execution_errors.add("this has a path")
268
+ "done"
269
+ end
270
+ end
271
+
272
+ LegacyInputType = GraphQL::InputObjectType.define do
273
+ name "LegacyInput"
274
+ argument :intValue, !types.Int
275
+ end
276
+
277
+ class InspectableInput < GraphQL::Schema::InputObject
278
+ argument :string_value, String, required: true, description: "Test description kwarg"
279
+ argument :nested_input, InspectableInput, required: false
280
+ argument :legacy_input, LegacyInputType, required: false
281
+ def helper_method
282
+ [
283
+ # Context is available in the InputObject
284
+ context[:message],
285
+ # A GraphQL::Query::Arguments instance is available
286
+ arguments[:stringValue],
287
+ # Legacy inputs have underscored method access too
288
+ legacy_input ? legacy_input.int_value : "-",
289
+ # Access by method call is available
290
+ "(#{nested_input ? nested_input.helper_method : "-"})",
291
+ ].join(", ")
292
+ end
293
+ end
294
+
295
+ class InspectableKey < BaseObject
296
+ field :root, String, null: false
297
+ field :is_sharp, Boolean, null: false, method: :sharp
298
+ field :is_flat, Boolean, null: false, method: :flat
299
+ end
300
+
301
+ class PerformingAct < GraphQL::Schema::Union
302
+ possible_types Musician, Ensemble
303
+
304
+ def self.resolve_type(object, context)
305
+ if object.is_a?(Models::Ensemble)
306
+ Ensemble
307
+ else
308
+ Musician
309
+ end
310
+ end
311
+ end
312
+
313
+ class HashKeyTest < BaseObject
314
+ field :falsey, Boolean, null: false
315
+ end
316
+
317
+ # Another new-style definition, with method overrides
318
+ class Query < BaseObject
319
+ field :ensembles, [Ensemble], null: false
320
+ field :find, GloballyIdentifiableType, null: true do
321
+ argument :id, ID, required: true
322
+ end
323
+ field :instruments, [InstrumentType], null: false do
324
+ argument :family, Family, required: false
325
+ end
326
+ field :inspect_input, [String], null: false do
327
+ argument :input, InspectableInput, required: true, custom: :ok
328
+ end
329
+ field :inspect_key, InspectableKey, null: false do
330
+ argument :key, Key, required: true
331
+ end
332
+ field :nowPlaying, PerformingAct, null: false, resolve: ->(o, a, c) { Models.data["Ensemble"].first }
333
+ # For asserting that the object is initialized once:
334
+ field :object_id, Integer, null: false
335
+ field :inspect_context, [String], null: false
336
+ field :hashyEnsemble, Ensemble, null: false
337
+
338
+ field :echo_json, RawJson, null: false do
339
+ argument :input, RawJson, required: true
340
+ end
341
+
342
+ field :echo_first_json, RawJson, null: false do
343
+ argument :input, [RawJson], required: true
344
+ end
345
+
346
+ def ensembles
347
+ Models.data["Ensemble"]
348
+ end
349
+
350
+ def find(id:)
351
+ if id == "MagicalSkipId"
352
+ context.skip
353
+ else
354
+ GloballyIdentifiableType.find(id)
355
+ end
356
+ end
357
+
358
+ def instruments(family: nil)
359
+ objs = Models.data["Instrument"]
360
+ if family
361
+ objs = objs.select { |i| i.family == family }
362
+ end
363
+ objs
364
+ end
365
+
366
+ # This is for testing input object behavior
367
+ def inspect_input(input:)
368
+ [
369
+ input.class.name,
370
+ input.helper_method,
371
+ # Access by method
372
+ input.string_value,
373
+ # Access by key:
374
+ input[:string_value],
375
+ input.key?(:string_value).to_s,
376
+ # Access by legacy key
377
+ input[:stringValue],
378
+ ]
379
+ end
380
+
381
+ def inspect_key(key:)
382
+ key
383
+ end
384
+
385
+ def inspect_context
386
+ [
387
+ context.custom_method,
388
+ context[:magic_key],
389
+ context[:normal_key]
390
+ ]
391
+ end
392
+
393
+ def hashy_ensemble
394
+ # Both string and symbol keys are supported:
395
+
396
+ {
397
+ name: "The Grateful Dead",
398
+ "musicians" => [
399
+ OpenStruct.new(name: "Jerry Garcia"),
400
+ ],
401
+ "formedAtDate" => "May 5, 1965",
402
+ }
403
+ end
404
+
405
+ def echo_json(input:)
406
+ input
407
+ end
408
+
409
+ def echo_first_json(input:)
410
+ input.first
411
+ end
412
+
413
+ field :hash_by_string, HashKeyTest, null: false
414
+ field :hash_by_sym, HashKeyTest, null: false
415
+ def hash_by_string
416
+ { "falsey" => false }
417
+ end
418
+
419
+ def hash_by_sym
420
+ { falsey: false }
421
+ end
422
+ end
423
+
424
+ class EnsembleInput < GraphQL::Schema::InputObject
425
+ argument :name, String, required: true
426
+ end
427
+
428
+ class AddInstrument < GraphQL::Schema::Mutation
429
+ null true
430
+ description "Register a new musical instrument in the database"
431
+
432
+ argument :name, String, required: true
433
+ argument :family, Family, required: true
434
+
435
+ field :instrument, InstrumentType, null: false
436
+ # This is meaningless, but it's to test the conflict with `Hash#entries`
437
+ field :entries, [InstrumentType], null: false
438
+ # Test `extras` injection
439
+
440
+ field :ee, String, null: false
441
+ extras [:execution_errors]
442
+ def resolve(name:, family:, execution_errors:)
443
+ instrument = Jazz::Models::Instrument.new(name, family)
444
+ Jazz::Models.data["Instrument"] << instrument
445
+ { instrument: instrument, entries: Jazz::Models.data["Instrument"], ee: execution_errors.class.name}
446
+ end
447
+ end
448
+
449
+ class Mutation < BaseObject
450
+ field :add_ensemble, Ensemble, null: false do
451
+ argument :input, EnsembleInput, required: true
452
+ end
453
+
454
+ field :add_instrument, mutation: AddInstrument
455
+
456
+ def add_ensemble(input:)
457
+ ens = Models::Ensemble.new(input.name)
458
+ Models.data["Ensemble"] << ens
459
+ ens
460
+ end
461
+
462
+ field :prepare_input, Integer, null: false do
463
+ argument :input, Integer, required: true, prepare: :square, as: :squared_input
464
+ end
465
+
466
+ def prepare_input(squared_input:)
467
+ # Test that `square` is called
468
+ squared_input
469
+ end
470
+
471
+ def square(value)
472
+ value ** 2
473
+ end
474
+ end
475
+
476
+ class MetadataPlugin
477
+ def self.use(schema_defn, value:)
478
+ schema_defn.target.metadata[:plugin_key] = value
479
+ end
480
+ end
481
+
482
+ class CustomContext < GraphQL::Query::Context
483
+ def [](key)
484
+ if key == :magic_key
485
+ "magic_value"
486
+ else
487
+ super
488
+ end
489
+ end
490
+
491
+ def custom_method
492
+ "custom_method"
493
+ end
494
+ end
495
+
496
+ module Introspection
497
+ class TypeType < GraphQL::Introspection::TypeType
498
+ def name
499
+ object.name.upcase
500
+ end
501
+ end
502
+
503
+ class SchemaType < GraphQL::Introspection::SchemaType
504
+ graphql_name "__Schema"
505
+
506
+ field :is_jazzy, Boolean, null: false
507
+ def is_jazzy
508
+ true
509
+ end
510
+ end
511
+
512
+ class DynamicFields < GraphQL::Introspection::DynamicFields
513
+ field :__typename_length, Int, null: false, extras: [:irep_node]
514
+ field :__ast_node_class, String, null: false, extras: [:ast_node]
515
+ def __typename_length(irep_node:)
516
+ __typename(irep_node: irep_node).length
517
+ end
518
+
519
+ def __ast_node_class(ast_node:)
520
+ ast_node.class.name
521
+ end
522
+ end
523
+
524
+ class EntryPoints < GraphQL::Introspection::EntryPoints
525
+ field :__classname, String, "The Ruby class name of the root object", null: false
526
+ def __classname
527
+ object.class.name
528
+ end
529
+ end
530
+ end
531
+
532
+ # New-style Schema definition
533
+ class Schema < GraphQL::Schema
534
+ query(Query)
535
+ mutation(Mutation)
536
+ context_class CustomContext
537
+ introspection(Introspection)
538
+ use MetadataPlugin, value: "xyz"
539
+ def self.resolve_type(type, obj, ctx)
540
+ class_name = obj.class.name.split("::").last
541
+ ctx.schema.types[class_name] || raise("No type for #{obj.inspect}")
542
+ end
543
+ end
544
+ end