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
@@ -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