graphql 1.7.6 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/install_generator.rb +14 -8
  4. data/lib/generators/graphql/loader_generator.rb +1 -1
  5. data/lib/generators/graphql/mutation_generator.rb +6 -1
  6. data/lib/generators/graphql/templates/function.erb +2 -2
  7. data/lib/generators/graphql/templates/loader.erb +2 -2
  8. data/lib/generators/graphql/templates/schema.erb +1 -1
  9. data/lib/graphql/argument.rb +25 -19
  10. data/lib/graphql/backtrace/tracer.rb +16 -22
  11. data/lib/graphql/backtrace.rb +1 -1
  12. data/lib/graphql/backwards_compatibility.rb +2 -3
  13. data/lib/graphql/base_type.rb +31 -31
  14. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
  15. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  16. data/lib/graphql/define/assign_object_field.rb +5 -12
  17. data/lib/graphql/deprecated_dsl.rb +42 -0
  18. data/lib/graphql/directive.rb +1 -0
  19. data/lib/graphql/enum_type.rb +3 -1
  20. data/lib/graphql/execution/execute.rb +21 -13
  21. data/lib/graphql/execution/instrumentation.rb +82 -0
  22. data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
  23. data/lib/graphql/execution/lazy/resolve.rb +1 -3
  24. data/lib/graphql/execution/multiplex.rb +12 -29
  25. data/lib/graphql/execution.rb +1 -0
  26. data/lib/graphql/field.rb +21 -4
  27. data/lib/graphql/function.rb +14 -0
  28. data/lib/graphql/input_object_type.rb +3 -1
  29. data/lib/graphql/interface_type.rb +5 -3
  30. data/lib/graphql/internal_representation/node.rb +26 -14
  31. data/lib/graphql/internal_representation/visit.rb +3 -6
  32. data/lib/graphql/introspection/base_object.rb +16 -0
  33. data/lib/graphql/introspection/directive_location_enum.rb +11 -7
  34. data/lib/graphql/introspection/directive_type.rb +23 -16
  35. data/lib/graphql/introspection/dynamic_fields.rb +11 -0
  36. data/lib/graphql/introspection/entry_points.rb +29 -0
  37. data/lib/graphql/introspection/enum_value_type.rb +16 -11
  38. data/lib/graphql/introspection/field_type.rb +21 -12
  39. data/lib/graphql/introspection/input_value_type.rb +26 -23
  40. data/lib/graphql/introspection/schema_field.rb +7 -2
  41. data/lib/graphql/introspection/schema_type.rb +36 -22
  42. data/lib/graphql/introspection/type_by_name_field.rb +10 -2
  43. data/lib/graphql/introspection/type_kind_enum.rb +10 -6
  44. data/lib/graphql/introspection/type_type.rb +85 -23
  45. data/lib/graphql/introspection/typename_field.rb +1 -0
  46. data/lib/graphql/introspection.rb +3 -10
  47. data/lib/graphql/language/block_string.rb +47 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +280 -0
  49. data/lib/graphql/language/generation.rb +3 -182
  50. data/lib/graphql/language/lexer.rb +144 -69
  51. data/lib/graphql/language/lexer.rl +15 -4
  52. data/lib/graphql/language/nodes.rb +141 -78
  53. data/lib/graphql/language/parser.rb +677 -630
  54. data/lib/graphql/language/parser.y +18 -12
  55. data/lib/graphql/language/printer.rb +361 -0
  56. data/lib/graphql/language/token.rb +10 -3
  57. data/lib/graphql/language.rb +3 -0
  58. data/lib/graphql/non_null_type.rb +1 -1
  59. data/lib/graphql/object_type.rb +1 -6
  60. data/lib/graphql/query/arguments.rb +63 -32
  61. data/lib/graphql/query/context.rb +32 -2
  62. data/lib/graphql/query/literal_input.rb +4 -1
  63. data/lib/graphql/query/null_context.rb +1 -1
  64. data/lib/graphql/query/result.rb +1 -1
  65. data/lib/graphql/query/variables.rb +21 -3
  66. data/lib/graphql/query.rb +19 -6
  67. data/lib/graphql/railtie.rb +109 -0
  68. data/lib/graphql/relay/connection_resolve.rb +3 -0
  69. data/lib/graphql/relay/connection_type.rb +5 -3
  70. data/lib/graphql/relay/edge_type.rb +2 -1
  71. data/lib/graphql/relay/global_id_resolve.rb +5 -1
  72. data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
  73. data/lib/graphql/relay/mutation/instrumentation.rb +1 -1
  74. data/lib/graphql/relay/mutation/resolve.rb +5 -1
  75. data/lib/graphql/relay/relation_connection.rb +14 -19
  76. data/lib/graphql/relay/type_extensions.rb +30 -0
  77. data/lib/graphql/relay.rb +2 -0
  78. data/lib/graphql/scalar_type.rb +14 -2
  79. data/lib/graphql/schema/argument.rb +92 -0
  80. data/lib/graphql/schema/build_from_definition.rb +64 -18
  81. data/lib/graphql/schema/enum.rb +85 -0
  82. data/lib/graphql/schema/enum_value.rb +74 -0
  83. data/lib/graphql/schema/field.rb +372 -0
  84. data/lib/graphql/schema/finder.rb +153 -0
  85. data/lib/graphql/schema/input_object.rb +87 -0
  86. data/lib/graphql/schema/interface.rb +105 -0
  87. data/lib/graphql/schema/introspection_system.rb +93 -0
  88. data/lib/graphql/schema/late_bound_type.rb +32 -0
  89. data/lib/graphql/schema/list.rb +32 -0
  90. data/lib/graphql/schema/loader.rb +2 -2
  91. data/lib/graphql/schema/member/accepts_definition.rb +152 -0
  92. data/lib/graphql/schema/member/base_dsl_methods.rb +100 -0
  93. data/lib/graphql/schema/member/build_type.rb +137 -0
  94. data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
  95. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  96. data/lib/graphql/schema/member/has_arguments.rb +50 -0
  97. data/lib/graphql/schema/member/has_fields.rb +130 -0
  98. data/lib/graphql/schema/member/instrumentation.rb +115 -0
  99. data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
  100. data/lib/graphql/schema/member.rb +28 -0
  101. data/lib/graphql/schema/middleware_chain.rb +5 -1
  102. data/lib/graphql/schema/mutation.rb +138 -0
  103. data/lib/graphql/schema/non_null.rb +38 -0
  104. data/lib/graphql/schema/object.rb +81 -0
  105. data/lib/graphql/schema/printer.rb +33 -266
  106. data/lib/graphql/schema/relay_classic_mutation.rb +87 -0
  107. data/lib/graphql/schema/rescue_middleware.rb +8 -7
  108. data/lib/graphql/schema/resolver.rb +122 -0
  109. data/lib/graphql/schema/scalar.rb +35 -0
  110. data/lib/graphql/schema/traversal.rb +102 -22
  111. data/lib/graphql/schema/union.rb +36 -0
  112. data/lib/graphql/schema/validation.rb +3 -2
  113. data/lib/graphql/schema.rb +381 -12
  114. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  115. data/lib/graphql/static_validation/literal_validator.rb +16 -4
  116. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
  117. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
  118. data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
  119. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +11 -1
  120. data/lib/graphql/static_validation/validation_context.rb +1 -1
  121. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -5
  122. data/lib/graphql/subscriptions/instrumentation.rb +5 -1
  123. data/lib/graphql/subscriptions/serialize.rb +2 -0
  124. data/lib/graphql/subscriptions.rb +90 -16
  125. data/lib/graphql/tracing/data_dog_tracing.rb +49 -0
  126. data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
  127. data/lib/graphql/tracing/platform_tracing.rb +20 -7
  128. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  129. data/lib/graphql/tracing.rb +1 -0
  130. data/lib/graphql/unresolved_type_error.rb +3 -2
  131. data/lib/graphql/upgrader/member.rb +894 -0
  132. data/lib/graphql/upgrader/schema.rb +37 -0
  133. data/lib/graphql/version.rb +1 -1
  134. data/lib/graphql.rb +5 -25
  135. data/readme.md +2 -2
  136. data/spec/dummy/app/channels/graphql_channel.rb +23 -2
  137. data/spec/dummy/log/development.log +239 -0
  138. data/spec/dummy/log/test.log +410 -0
  139. data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
  140. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
  141. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
  142. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
  143. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
  144. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
  145. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
  146. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
  147. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
  148. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
  149. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
  150. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
  151. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
  152. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
  153. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
  154. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
  155. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
  156. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
  157. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
  158. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
  159. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
  160. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
  161. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
  162. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
  163. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
  164. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
  165. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
  166. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
  167. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
  168. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
  169. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
  170. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  171. data/spec/fixtures/upgrader/account.original.rb +19 -0
  172. data/spec/fixtures/upgrader/account.transformed.rb +20 -0
  173. data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
  174. data/spec/fixtures/upgrader/blame_range.transformed.rb +30 -0
  175. data/spec/fixtures/upgrader/date_time.original.rb +24 -0
  176. data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
  177. data/spec/fixtures/upgrader/delete_project.original.rb +28 -0
  178. data/spec/fixtures/upgrader/delete_project.transformed.rb +27 -0
  179. data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
  180. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
  181. data/spec/fixtures/upgrader/increment_count.original.rb +59 -0
  182. data/spec/fixtures/upgrader/increment_count.transformed.rb +50 -0
  183. data/spec/fixtures/upgrader/photo.original.rb +10 -0
  184. data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
  185. data/spec/fixtures/upgrader/release_order.original.rb +15 -0
  186. data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
  187. data/spec/fixtures/upgrader/starrable.original.rb +49 -0
  188. data/spec/fixtures/upgrader/starrable.transformed.rb +46 -0
  189. data/spec/fixtures/upgrader/subscribable.original.rb +55 -0
  190. data/spec/fixtures/upgrader/subscribable.transformed.rb +51 -0
  191. data/spec/fixtures/upgrader/type_x.original.rb +65 -0
  192. data/spec/fixtures/upgrader/type_x.transformed.rb +56 -0
  193. data/spec/generators/graphql/function_generator_spec.rb +26 -0
  194. data/spec/generators/graphql/install_generator_spec.rb +1 -1
  195. data/spec/generators/graphql/loader_generator_spec.rb +24 -0
  196. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  197. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  198. data/spec/graphql/argument_spec.rb +21 -0
  199. data/spec/graphql/backtrace_spec.rb +10 -0
  200. data/spec/graphql/base_type_spec.rb +42 -0
  201. data/spec/graphql/boolean_type_spec.rb +3 -3
  202. data/spec/graphql/directive_spec.rb +3 -1
  203. data/spec/graphql/enum_type_spec.rb +18 -5
  204. data/spec/graphql/execution/execute_spec.rb +4 -4
  205. data/spec/graphql/execution/instrumentation_spec.rb +165 -0
  206. data/spec/graphql/execution/multiplex_spec.rb +2 -2
  207. data/spec/graphql/execution_error_spec.rb +18 -0
  208. data/spec/graphql/float_type_spec.rb +2 -2
  209. data/spec/graphql/id_type_spec.rb +1 -1
  210. data/spec/graphql/input_object_type_spec.rb +15 -2
  211. data/spec/graphql/int_type_spec.rb +2 -2
  212. data/spec/graphql/interface_type_spec.rb +12 -0
  213. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  214. data/spec/graphql/introspection/schema_type_spec.rb +2 -0
  215. data/spec/graphql/language/block_string_spec.rb +70 -0
  216. data/spec/graphql/language/document_from_schema_definition_spec.rb +770 -0
  217. data/spec/graphql/language/generation_spec.rb +21 -186
  218. data/spec/graphql/language/lexer_spec.rb +21 -1
  219. data/spec/graphql/language/nodes_spec.rb +21 -12
  220. data/spec/graphql/language/parser_spec.rb +1 -1
  221. data/spec/graphql/language/printer_spec.rb +203 -0
  222. data/spec/graphql/object_type_spec.rb +22 -0
  223. data/spec/graphql/query/arguments_spec.rb +25 -15
  224. data/spec/graphql/query/context_spec.rb +18 -0
  225. data/spec/graphql/query/executor_spec.rb +2 -1
  226. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -8
  227. data/spec/graphql/query/variables_spec.rb +42 -1
  228. data/spec/graphql/query_spec.rb +31 -5
  229. data/spec/graphql/rake_task_spec.rb +3 -1
  230. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  231. data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
  232. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  233. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  234. data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
  235. data/spec/graphql/relay/mutation_spec.rb +9 -7
  236. data/spec/graphql/relay/range_add_spec.rb +5 -1
  237. data/spec/graphql/relay/relation_connection_spec.rb +65 -1
  238. data/spec/graphql/schema/argument_spec.rb +87 -0
  239. data/spec/graphql/schema/build_from_definition_spec.rb +89 -5
  240. data/spec/graphql/schema/enum_spec.rb +74 -0
  241. data/spec/graphql/schema/field_spec.rb +225 -0
  242. data/spec/graphql/schema/finder_spec.rb +135 -0
  243. data/spec/graphql/schema/input_object_spec.rb +111 -0
  244. data/spec/graphql/schema/instrumentation_spec.rb +40 -0
  245. data/spec/graphql/schema/interface_spec.rb +185 -0
  246. data/spec/graphql/schema/introspection_system_spec.rb +39 -0
  247. data/spec/graphql/schema/member/accepts_definition_spec.rb +111 -0
  248. data/spec/graphql/schema/member/build_type_spec.rb +17 -0
  249. data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
  250. data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
  251. data/spec/graphql/schema/mutation_spec.rb +148 -0
  252. data/spec/graphql/schema/object_spec.rb +175 -0
  253. data/spec/graphql/schema/printer_spec.rb +111 -15
  254. data/spec/graphql/schema/relay_classic_mutation_spec.rb +38 -0
  255. data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
  256. data/spec/graphql/schema/resolver_spec.rb +131 -0
  257. data/spec/graphql/schema/scalar_spec.rb +95 -0
  258. data/spec/graphql/schema/traversal_spec.rb +31 -0
  259. data/spec/graphql/schema/union_spec.rb +65 -0
  260. data/spec/graphql/schema/validation_spec.rb +1 -1
  261. data/spec/graphql/schema/warden_spec.rb +11 -11
  262. data/spec/graphql/schema_spec.rb +55 -12
  263. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
  264. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
  265. data/spec/graphql/string_type_spec.rb +3 -3
  266. data/spec/graphql/subscriptions_spec.rb +273 -184
  267. data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +1 -1
  268. data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
  269. data/spec/graphql/tracing/platform_tracing_spec.rb +60 -1
  270. data/spec/graphql/union_type_spec.rb +1 -1
  271. data/spec/graphql/upgrader/member_spec.rb +516 -0
  272. data/spec/graphql/upgrader/schema_spec.rb +82 -0
  273. data/spec/spec_helper.rb +8 -0
  274. data/spec/support/dummy/schema.rb +53 -24
  275. data/spec/support/jazz.rb +544 -0
  276. data/spec/support/lazy_helpers.rb +21 -23
  277. data/spec/support/new_relic.rb +24 -0
  278. data/spec/support/star_trek/data.rb +109 -0
  279. data/spec/support/star_trek/schema.rb +388 -0
  280. data/spec/support/star_wars/data.rb +6 -7
  281. data/spec/support/star_wars/schema.rb +127 -171
  282. metadata +233 -11
  283. data/lib/graphql/introspection/arguments_field.rb +0 -7
  284. data/lib/graphql/introspection/enum_values_field.rb +0 -18
  285. data/lib/graphql/introspection/fields_field.rb +0 -13
  286. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  287. data/lib/graphql/introspection/interfaces_field.rb +0 -11
  288. data/lib/graphql/introspection/of_type_field.rb +0 -6
  289. data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -0,0 +1,280 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Language
4
+ # @api private
5
+ #
6
+ # {GraphQL::Language::DocumentFromSchemaDefinition} is used to convert a {GraphQL::Schema} object
7
+ # To a {GraphQL::Language::Document} AST node.
8
+ #
9
+ # @param context [Hash]
10
+ # @param only [<#call(member, ctx)>]
11
+ # @param except [<#call(member, ctx)>]
12
+ # @param include_introspection_types [Boolean] Whether or not to include introspection types in the AST
13
+ # @param include_built_in_scalars [Boolean] Whether or not to include built in scalars in the AST
14
+ # @param include_built_in_directives [Boolean] Whether or not to include built in diirectives in the AST
15
+ class DocumentFromSchemaDefinition
16
+ def initialize(
17
+ schema, context: nil, only: nil, except: nil, include_introspection_types: false,
18
+ include_built_in_directives: false, include_built_in_scalars: false, always_include_schema: false
19
+ )
20
+ @schema = schema
21
+ @always_include_schema = always_include_schema
22
+ @include_introspection_types = include_introspection_types
23
+ @include_built_in_scalars = include_built_in_scalars
24
+ @include_built_in_directives = include_built_in_directives
25
+
26
+ @warden = GraphQL::Schema::Warden.new(
27
+ GraphQL::Filter.new(only: only, except: except),
28
+ schema: @schema,
29
+ context: context,
30
+ )
31
+ end
32
+
33
+ def document
34
+ GraphQL::Language::Nodes::Document.new(
35
+ definitions: build_definition_nodes
36
+ )
37
+ end
38
+
39
+ def build_schema_node
40
+ GraphQL::Language::Nodes::SchemaDefinition.new(
41
+ query: warden.root_type_for_operation("query"),
42
+ mutation: warden.root_type_for_operation("mutation"),
43
+ subscription: warden.root_type_for_operation("subscription"),
44
+ # This only supports directives from parsing,
45
+ # use a custom printer to add to this list.
46
+ directives: @schema.ast_node ? @schema.ast_node.directives : [],
47
+ )
48
+ end
49
+
50
+ def build_object_type_node(object_type)
51
+ GraphQL::Language::Nodes::ObjectTypeDefinition.new(
52
+ name: object_type.name,
53
+ interfaces: warden.interfaces(object_type).sort_by(&:name).map { |iface| build_type_name_node(iface) },
54
+ fields: build_field_nodes(warden.fields(object_type)),
55
+ description: object_type.description,
56
+ )
57
+ end
58
+
59
+ def build_field_node(field)
60
+ field_node = GraphQL::Language::Nodes::FieldDefinition.new(
61
+ name: field.name,
62
+ arguments: build_argument_nodes(warden.arguments(field)),
63
+ type: build_type_name_node(field.type),
64
+ description: field.description,
65
+ )
66
+
67
+ if field.deprecation_reason
68
+ field_node.directives << GraphQL::Language::Nodes::Directive.new(
69
+ name: GraphQL::Directive::DeprecatedDirective.name,
70
+ arguments: [GraphQL::Language::Nodes::Argument.new(name: "reason", value: field.deprecation_reason)]
71
+ )
72
+ end
73
+
74
+ field_node
75
+ end
76
+
77
+ def build_union_type_node(union_type)
78
+ GraphQL::Language::Nodes::UnionTypeDefinition.new(
79
+ name: union_type.name,
80
+ description: union_type.description,
81
+ types: warden.possible_types(union_type).sort_by(&:name).map { |type| build_type_name_node(type) }
82
+ )
83
+ end
84
+
85
+ def build_interface_type_node(interface_type)
86
+ GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
87
+ name: interface_type.name,
88
+ description: interface_type.description,
89
+ fields: build_field_nodes(warden.fields(interface_type))
90
+ )
91
+ end
92
+
93
+ def build_enum_type_node(enum_type)
94
+ GraphQL::Language::Nodes::EnumTypeDefinition.new(
95
+ name: enum_type.name,
96
+ values: warden.enum_values(enum_type).sort_by(&:name).map do |enum_value|
97
+ build_enum_value_node(enum_value)
98
+ end,
99
+ description: enum_type.description,
100
+ )
101
+ end
102
+
103
+ def build_enum_value_node(enum_value)
104
+ enum_value_node = GraphQL::Language::Nodes::EnumValueDefinition.new(
105
+ name: enum_value.name,
106
+ description: enum_value.description,
107
+ )
108
+
109
+ if enum_value.deprecation_reason
110
+ enum_value_node.directives << GraphQL::Language::Nodes::Directive.new(
111
+ name: GraphQL::Directive::DeprecatedDirective.name,
112
+ arguments: [GraphQL::Language::Nodes::Argument.new(name: "reason", value: enum_value.deprecation_reason)]
113
+ )
114
+ end
115
+
116
+ enum_value_node
117
+ end
118
+
119
+ def build_scalar_type_node(scalar_type)
120
+ GraphQL::Language::Nodes::ScalarTypeDefinition.new(
121
+ name: scalar_type.name,
122
+ description: scalar_type.description,
123
+ )
124
+ end
125
+
126
+ def build_argument_node(argument)
127
+ argument_node = GraphQL::Language::Nodes::InputValueDefinition.new(
128
+ name: argument.name,
129
+ description: argument.description,
130
+ type: build_type_name_node(argument.type),
131
+ )
132
+
133
+ if argument.default_value?
134
+ argument_node.default_value = build_default_value(argument.default_value, argument.type)
135
+ end
136
+
137
+ argument_node
138
+ end
139
+
140
+ def build_input_object_node(input_object)
141
+ GraphQL::Language::Nodes::InputObjectTypeDefinition.new(
142
+ name: input_object.name,
143
+ fields: build_argument_nodes(warden.arguments(input_object)),
144
+ description: input_object.description,
145
+ )
146
+ end
147
+
148
+ def build_directive_node(directive)
149
+ GraphQL::Language::Nodes::DirectiveDefinition.new(
150
+ name: directive.name,
151
+ arguments: build_argument_nodes(warden.arguments(directive)),
152
+ locations: directive.locations.map(&:to_s),
153
+ description: directive.description,
154
+ )
155
+ end
156
+
157
+ def build_type_name_node(type)
158
+ case type
159
+ when GraphQL::ListType
160
+ GraphQL::Language::Nodes::ListType.new(
161
+ of_type: build_type_name_node(type.of_type)
162
+ )
163
+ when GraphQL::NonNullType
164
+ GraphQL::Language::Nodes::NonNullType.new(
165
+ of_type: build_type_name_node(type.of_type)
166
+ )
167
+ else
168
+ GraphQL::Language::Nodes::TypeName.new(name: type.name)
169
+ end
170
+ end
171
+
172
+ def build_default_value(default_value, type)
173
+ if default_value.nil?
174
+ return GraphQL::Language::Nodes::NullValue.new(name: "null")
175
+ end
176
+
177
+ case type
178
+ when GraphQL::ScalarType
179
+ type.coerce_isolated_result(default_value)
180
+ when EnumType
181
+ GraphQL::Language::Nodes::Enum.new(name: type.coerce_isolated_result(default_value))
182
+ when InputObjectType
183
+ GraphQL::Language::Nodes::InputObject.new(
184
+ arguments: default_value.to_h.map do |arg_name, arg_value|
185
+ arg_type = type.input_fields.fetch(arg_name.to_s).type
186
+ GraphQL::Language::Nodes::Argument.new(
187
+ name: arg_name,
188
+ value: build_default_value(arg_value, arg_type)
189
+ )
190
+ end
191
+ )
192
+ when NonNullType
193
+ build_default_value(default_value, type.of_type)
194
+ when ListType
195
+ default_value.to_a.map { |v| build_default_value(v, type.of_type) }
196
+ else
197
+ raise NotImplementedError, "Unexpected default value type #{type.inspect}"
198
+ end
199
+ end
200
+
201
+ def build_type_definition_node(type)
202
+ case type
203
+ when GraphQL::ObjectType
204
+ build_object_type_node(type)
205
+ when GraphQL::UnionType
206
+ build_union_type_node(type)
207
+ when GraphQL::InterfaceType
208
+ build_interface_type_node(type)
209
+ when GraphQL::ScalarType
210
+ build_scalar_type_node(type)
211
+ when GraphQL::EnumType
212
+ build_enum_type_node(type)
213
+ when GraphQL::InputObjectType
214
+ build_input_object_node(type)
215
+ else
216
+ raise TypeError
217
+ end
218
+ end
219
+
220
+ def build_argument_nodes(arguments)
221
+ arguments
222
+ .map { |arg| build_argument_node(arg) }
223
+ .sort_by(&:name)
224
+ end
225
+
226
+ def build_directive_nodes(directives)
227
+ if !include_built_in_directives
228
+ directives = directives.reject { |directive| directive.default_directive? }
229
+ end
230
+
231
+ directives
232
+ .map { |directive| build_directive_node(directive) }
233
+ .sort_by(&:name)
234
+ end
235
+
236
+ def build_definition_nodes
237
+ definitions = []
238
+ definitions << build_schema_node if include_schema_node?
239
+ definitions += build_directive_nodes(warden.directives)
240
+ definitions += build_type_definition_nodes(warden.types)
241
+ definitions
242
+ end
243
+
244
+ def build_type_definition_nodes(types)
245
+ if !include_introspection_types
246
+ types = types.reject { |type| type.introspection? }
247
+ end
248
+
249
+ if !include_built_in_scalars
250
+ types = types.reject { |type| type.default_scalar? }
251
+ end
252
+
253
+ types
254
+ .map { |type| build_type_definition_node(type) }
255
+ .sort_by(&:name)
256
+ end
257
+
258
+ def build_field_nodes(fields)
259
+ fields
260
+ .map { |field| build_field_node(field) }
261
+ .sort_by(&:name)
262
+ end
263
+
264
+ private
265
+
266
+ def include_schema_node?
267
+ always_include_schema || !schema_respects_root_name_conventions?(schema)
268
+ end
269
+
270
+ def schema_respects_root_name_conventions?(schema)
271
+ (schema.query.nil? || schema.query.name == 'Query') &&
272
+ (schema.mutation.nil? || schema.mutation.name == 'Mutation') &&
273
+ (schema.subscription.nil? || schema.subscription.name == 'Subscription')
274
+ end
275
+
276
+ attr_reader :schema, :warden, :always_include_schema,
277
+ :include_introspection_types, :include_built_in_directives, :include_built_in_scalars
278
+ end
279
+ end
280
+ end
@@ -14,189 +14,10 @@ module GraphQL
14
14
  #
15
15
  # @param node [GraphQL::Language::Nodes::AbstractNode] an AST node to recursively stringify
16
16
  # @param indent [String] Whitespace to add to each printed node
17
+ # @param printer [GraphQL::Language::Printer] An optional custom printer for printing AST nodes. Defaults to GraphQL::Language::Printer
17
18
  # @return [String] Valid GraphQL for `node`
18
- def generate(node, indent: "")
19
- case node
20
- when Nodes::Document
21
- node.definitions.map { |d| generate(d) }.join("\n\n")
22
- when Nodes::Argument
23
- "#{node.name}: #{generate(node.value)}".dup
24
- when Nodes::Directive
25
- out = "@#{node.name}".dup
26
- out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
27
- out
28
- when Nodes::Enum
29
- "#{node.name}".dup
30
- when Nodes::NullValue
31
- "null".dup
32
- when Nodes::Field
33
- out = "#{indent}".dup
34
- out << "#{node.alias}: " if node.alias
35
- out << "#{node.name}"
36
- out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
37
- out << generate_directives(node.directives)
38
- out << generate_selections(node.selections, indent: indent)
39
- out
40
- when Nodes::FragmentDefinition
41
- out = "#{indent}fragment #{node.name}".dup
42
- if node.type
43
- out << " on #{generate(node.type)}"
44
- end
45
- out << generate_directives(node.directives)
46
- out << generate_selections(node.selections, indent: indent)
47
- out
48
- when Nodes::FragmentSpread
49
- out = "#{indent}...#{node.name}".dup
50
- out << generate_directives(node.directives)
51
- out
52
- when Nodes::InlineFragment
53
- out = "#{indent}...".dup
54
- if node.type
55
- out << " on #{generate(node.type)}"
56
- end
57
- out << generate_directives(node.directives)
58
- out << generate_selections(node.selections, indent: indent)
59
- out
60
- when Nodes::InputObject
61
- generate(node.to_h)
62
- when Nodes::ListType
63
- "[#{generate(node.of_type)}]".dup
64
- when Nodes::NonNullType
65
- "#{generate(node.of_type)}!".dup
66
- when Nodes::OperationDefinition
67
- out = "#{indent}#{node.operation_type}".dup
68
- out << " #{node.name}" if node.name
69
- out << "(#{node.variables.map { |v| generate(v) }.join(", ")})" if node.variables.any?
70
- out << generate_directives(node.directives)
71
- out << generate_selections(node.selections, indent: indent)
72
- out
73
- when Nodes::TypeName
74
- "#{node.name}".dup
75
- when Nodes::VariableDefinition
76
- out = "$#{node.name}: #{generate(node.type)}".dup
77
- out << " = #{generate(node.default_value)}" unless node.default_value.nil?
78
- out
79
- when Nodes::VariableIdentifier
80
- "$#{node.name}".dup
81
- when Nodes::SchemaDefinition
82
- if (node.query.nil? || node.query == 'Query') &&
83
- (node.mutation.nil? || node.mutation == 'Mutation') &&
84
- (node.subscription.nil? || node.subscription == 'Subscription')
85
- return
86
- end
87
-
88
- out = "schema {\n".dup
89
- out << " query: #{node.query}\n" if node.query
90
- out << " mutation: #{node.mutation}\n" if node.mutation
91
- out << " subscription: #{node.subscription}\n" if node.subscription
92
- out << "}"
93
- when Nodes::ScalarTypeDefinition
94
- out = generate_description(node)
95
- out << "scalar #{node.name}"
96
- out << generate_directives(node.directives)
97
- when Nodes::ObjectTypeDefinition
98
- out = generate_description(node)
99
- out << "type #{node.name}"
100
- out << generate_directives(node.directives)
101
- out << " implements " << node.interfaces.map(&:name).join(", ") unless node.interfaces.empty?
102
- out << generate_field_definitions(node.fields)
103
- when Nodes::InputValueDefinition
104
- out = "#{node.name}: #{generate(node.type)}".dup
105
- out << " = #{generate(node.default_value)}" unless node.default_value.nil?
106
- out << generate_directives(node.directives)
107
- when Nodes::FieldDefinition
108
- out = node.name.dup
109
- unless node.arguments.empty?
110
- out << "(" << node.arguments.map{ |arg| generate(arg) }.join(", ") << ")"
111
- end
112
- out << ": #{generate(node.type)}"
113
- out << generate_directives(node.directives)
114
- when Nodes::InterfaceTypeDefinition
115
- out = generate_description(node)
116
- out << "interface #{node.name}"
117
- out << generate_directives(node.directives)
118
- out << generate_field_definitions(node.fields)
119
- when Nodes::UnionTypeDefinition
120
- out = generate_description(node)
121
- out << "union #{node.name}"
122
- out << generate_directives(node.directives)
123
- out << " = " + node.types.map(&:name).join(" | ")
124
- when Nodes::EnumTypeDefinition
125
- out = generate_description(node)
126
- out << "enum #{node.name}#{generate_directives(node.directives)} {\n"
127
- node.values.each.with_index do |value, i|
128
- out << generate_description(value, indent: ' ', first_in_block: i == 0)
129
- out << generate(value)
130
- end
131
- out << "}"
132
- when Nodes::EnumValueDefinition
133
- out = " #{node.name}".dup
134
- out << generate_directives(node.directives)
135
- out << "\n"
136
- when Nodes::InputObjectTypeDefinition
137
- out = generate_description(node)
138
- out << "input #{node.name}"
139
- out << generate_directives(node.directives)
140
- out << " {\n"
141
- node.fields.each.with_index do |field, i|
142
- out << generate_description(field, indent: ' ', first_in_block: i == 0)
143
- out << " #{generate(field)}\n"
144
- end
145
- out << "}"
146
- when Nodes::DirectiveDefinition
147
- out = generate_description(node)
148
- out << "directive @#{node.name}"
149
- out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
150
- out << " on #{node.locations.join(' | ')}"
151
- when Nodes::AbstractNode
152
- node.to_query_string(indent: indent)
153
- when FalseClass, Float, Integer, NilClass, String, TrueClass
154
- GraphQL::Language.serialize(node)
155
- when Array
156
- "[#{node.map { |v| generate(v) }.join(", ")}]".dup
157
- when Hash
158
- "{#{node.map { |k, v| "#{k}: #{generate(v)}" }.join(", ")}}".dup
159
- else
160
- raise TypeError
161
- end
162
- end
163
-
164
- private
165
-
166
- def generate_directives(directives)
167
- if directives.any?
168
- directives.map { |d| " #{generate(d)}" }.join
169
- else
170
- ""
171
- end
172
- end
173
-
174
- def generate_selections(selections, indent: "")
175
- if selections.any?
176
- out = " {\n".dup
177
- selections.each do |selection|
178
- out << generate(selection, indent: indent + " ") << "\n"
179
- end
180
- out << "#{indent}}"
181
- else
182
- ""
183
- end
184
- end
185
-
186
- def generate_description(node, indent: '', first_in_block: true)
187
- return ''.dup unless node.description
188
-
189
- description = indent != '' && !first_in_block ? "\n".dup : "".dup
190
- description << GraphQL::Language::Comments.commentize(node.description, indent: indent)
191
- end
192
-
193
- def generate_field_definitions(fields)
194
- out = " {\n".dup
195
- fields.each.with_index do |field, i|
196
- out << generate_description(field, indent: ' ', first_in_block: i == 0)
197
- out << " #{generate(field)}\n"
198
- end
199
- out << "}"
19
+ def generate(node, indent: "", printer: GraphQL::Language::Printer.new)
20
+ printer.print(node, indent: indent)
200
21
  end
201
22
  end
202
23
  end