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,105 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ module Interface
5
+ include GraphQL::Schema::Member::GraphQLTypeNames
6
+ module DefinitionMethods
7
+ include GraphQL::Schema::Member::CachedGraphQLDefinition
8
+ include GraphQL::Relay::TypeExtensions
9
+ include GraphQL::Schema::Member::BaseDSLMethods
10
+ include GraphQL::Schema::Member::TypeSystemHelpers
11
+ include GraphQL::Schema::Member::HasFields
12
+
13
+ # Methods defined in this block will be:
14
+ # - Added as class methods to this interface
15
+ # - Added as class methods to all child interfaces
16
+ def definition_methods(&block)
17
+ self::DefinitionMethods.module_eval(&block)
18
+ end
19
+
20
+ # Here's the tricky part. Make sure behavior keeps making its way down the inheritance chain.
21
+ def included(child_class)
22
+ if !child_class.is_a?(Class)
23
+ # In this case, it's been included into another interface.
24
+ # This is how interface inheritance is implemented
25
+
26
+ # Use an instance variable to tell whether it's been included previously or not;
27
+ # You can't use constant detection because constants are brought into scope
28
+ # by `include`, which has already happened at this point.
29
+ if !child_class.instance_variable_defined?(:@_definition_methods)
30
+ defn_methods_module = Module.new
31
+ child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
32
+ child_class.const_set(:DefinitionMethods, defn_methods_module)
33
+ child_class.extend(child_class::DefinitionMethods)
34
+ end
35
+
36
+ # We need this before we can call `own_interfaces`
37
+ child_class.extend(Schema::Interface::DefinitionMethods)
38
+
39
+ child_class.own_interfaces << self
40
+ child_class.interfaces.each do |interface_defn|
41
+ child_class.extend(interface_defn::DefinitionMethods)
42
+ end
43
+ elsif child_class < GraphQL::Schema::Object
44
+ # This is being included into an object type, make sure it's using `implements(...)`
45
+ backtrace_line = caller(0, 10).find { |line| line.include?("schema/object.rb") && line.include?("in `implements'")}
46
+ if !backtrace_line
47
+ raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
48
+ end
49
+ end
50
+
51
+ super
52
+ end
53
+
54
+ def orphan_types(*types)
55
+ if types.any?
56
+ @orphan_types = types
57
+ else
58
+ all_orphan_types = @orphan_types || []
59
+ all_orphan_types += super if defined?(super)
60
+ all_orphan_types.uniq
61
+ end
62
+ end
63
+
64
+ def to_graphql
65
+ type_defn = GraphQL::InterfaceType.new
66
+ type_defn.name = graphql_name
67
+ type_defn.description = description
68
+ type_defn.orphan_types = orphan_types
69
+ fields.each do |field_name, field_inst|
70
+ field_defn = field_inst.graphql_definition
71
+ type_defn.fields[field_defn.name] = field_defn
72
+ end
73
+ type_defn.metadata[:type_class] = self
74
+ if respond_to?(:resolve_type)
75
+ type_defn.resolve_type = method(:resolve_type)
76
+ end
77
+ type_defn
78
+ end
79
+
80
+ def kind
81
+ GraphQL::TypeKinds::INTERFACE
82
+ end
83
+
84
+ protected
85
+
86
+ def own_interfaces
87
+ @own_interfaces ||= []
88
+ end
89
+
90
+ def interfaces
91
+ own_interfaces + (own_interfaces.map { |i| i.own_interfaces }).flatten
92
+ end
93
+ end
94
+
95
+ # Extend this _after_ `DefinitionMethods` is defined, so it will be used
96
+ extend GraphQL::Schema::Member::AcceptsDefinition
97
+
98
+ extend DefinitionMethods
99
+
100
+ def unwrap
101
+ self
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class IntrospectionSystem
5
+ attr_reader :schema_type, :type_type, :typename_field
6
+
7
+ def initialize(schema)
8
+ @schema = schema
9
+ @built_in_namespace = GraphQL::Introspection
10
+ @custom_namespace = schema.introspection_namespace || @built_in_namespace
11
+
12
+ # Use to-graphql to avoid sharing with any previous instantiations
13
+ @schema_type = load_constant(:SchemaType).to_graphql
14
+ @type_type = load_constant(:TypeType).to_graphql
15
+ @field_type = load_constant(:FieldType).to_graphql
16
+ @directive_type = load_constant(:DirectiveType).to_graphql
17
+ @enum_value_type = load_constant(:EnumValueType).to_graphql
18
+ @input_value_type = load_constant(:InputValueType).to_graphql
19
+ @type_kind_enum = load_constant(:TypeKindEnum).to_graphql
20
+ @directive_location_enum = load_constant(:DirectiveLocationEnum).to_graphql
21
+ @entry_point_fields = get_fields_from_class(class_sym: :EntryPoints)
22
+ @dynamic_fields = get_fields_from_class(class_sym: :DynamicFields)
23
+ end
24
+
25
+ def object_types
26
+ [
27
+ @schema_type,
28
+ @type_type,
29
+ @field_type,
30
+ @directive_type,
31
+ @enum_value_type,
32
+ @input_value_type,
33
+ @type_kind_enum,
34
+ @directive_location_enum,
35
+ ]
36
+ end
37
+
38
+ def entry_points
39
+ @entry_point_fields.values
40
+ end
41
+
42
+ def entry_point(name:)
43
+ @entry_point_fields[name]
44
+ end
45
+
46
+ def dynamic_fields
47
+ @dynamic_fields.values
48
+ end
49
+
50
+ def dynamic_field(name:)
51
+ @dynamic_fields[name]
52
+ end
53
+
54
+ private
55
+
56
+ def load_constant(class_name)
57
+ @custom_namespace.const_get(class_name)
58
+ rescue NameError
59
+ # Dup the built-in so that the cached fields aren't shared
60
+ @built_in_namespace.const_get(class_name)
61
+ end
62
+
63
+ def get_fields_from_class(class_sym:)
64
+ object_class = load_constant(class_sym)
65
+ object_type_defn = object_class.to_graphql
66
+ extracted_field_defns = {}
67
+ object_type_defn.all_fields.each do |field_defn|
68
+ inner_resolve = field_defn.resolve_proc
69
+ resolve_with_instantiate = PerFieldProxyResolve.new(object_class: object_class, inner_resolve: inner_resolve)
70
+ extracted_field_defns[field_defn.name] = field_defn.redefine(resolve: resolve_with_instantiate)
71
+ end
72
+ extracted_field_defns
73
+ end
74
+
75
+ class PerFieldProxyResolve
76
+ def initialize(object_class:, inner_resolve:)
77
+ @object_class = object_class
78
+ @inner_resolve = inner_resolve
79
+ end
80
+
81
+ def call(obj, args, ctx)
82
+ query_ctx = ctx.query.context
83
+ # Remove the QueryType wrapper
84
+ if obj.is_a?(GraphQL::Schema::Object)
85
+ obj = obj.object
86
+ end
87
+ wrapped_object = @object_class.new(obj, query_ctx)
88
+ @inner_resolve.call(wrapped_object, args, ctx)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ # A stand-in for a type which will be resolved in a given schema, by name.
5
+ # TODO: support argument types too, make this a public API somehow
6
+ # @api Private
7
+ class LateBoundType
8
+ attr_reader :name
9
+ def initialize(local_name)
10
+ @name = local_name
11
+ end
12
+
13
+ def unwrap
14
+ self
15
+ end
16
+
17
+ def to_non_null_type
18
+ GraphQL::NonNullType.new(of_type: self)
19
+ end
20
+
21
+ def to_list_type
22
+ GraphQL::ListType.new(of_type: self)
23
+ end
24
+
25
+ def inspect
26
+ "#<LateBoundType @name=#{name}>"
27
+ end
28
+
29
+ alias :to_s :inspect
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # Represents a list type in the schema.
6
+ # Wraps a {Schema::Member} as a list type.
7
+ # @see {Schema::Member::TypeSystemHelpers#to_list_type}
8
+ class List
9
+ include GraphQL::Schema::Member::CachedGraphQLDefinition
10
+ include GraphQL::Schema::Member::TypeSystemHelpers
11
+
12
+ # @return [Class, Module] The inner type of this list, the type of which one or more objects may be present.
13
+ attr_reader :of_type
14
+
15
+ def initialize(of_type)
16
+ @of_type = of_type
17
+ end
18
+
19
+ def to_graphql
20
+ @of_type.graphql_definition.to_list_type
21
+ end
22
+
23
+ def kind
24
+ GraphQL::TypeKinds::LIST
25
+ end
26
+
27
+ def unwrap
28
+ @of_type.unwrap
29
+ end
30
+ end
31
+ end
32
+ end
@@ -97,7 +97,7 @@ module GraphQL
97
97
  }]
98
98
  )
99
99
  when "FIELD"
100
- Field.define(
100
+ GraphQL::Field.define(
101
101
  name: type["name"],
102
102
  type: type_resolver.call(type["type"]),
103
103
  description: type["description"],
@@ -138,7 +138,7 @@ module GraphQL
138
138
  end
139
139
  end
140
140
 
141
- Argument.define(
141
+ GraphQL::Argument.define(
142
142
  name: type["name"],
143
143
  type: type_resolver.call(type["type"]),
144
144
  description: type["description"],
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ # Support for legacy `accepts_definitions` functions.
7
+ #
8
+ # Keep the legacy handler hooked up. Class-based types and fields
9
+ # will call those legacy handlers during their `.to_graphql`
10
+ # methods.
11
+ #
12
+ # This can help out while transitioning from one to the other.
13
+ # Eventually, `GraphQL::{X}Type` objects will be removed entirely,
14
+ # But this can help during the transition.
15
+ #
16
+ # @example Applying a function to base object class
17
+ # # Here's the legacy-style config, which we're calling back to:
18
+ # GraphQL::ObjectType.accepts_definition({
19
+ # permission_level: ->(defn, value) { defn.metadata[:permission_level] = value }
20
+ # })
21
+ #
22
+ # class BaseObject < GraphQL::Schema::Object
23
+ # # Setup a named pass-through to the legacy config functions
24
+ # accepts_definition :permission_level
25
+ # end
26
+ #
27
+ # class Account < BaseObject
28
+ # # This value will be passed to the legacy handler:
29
+ # permission_level 1
30
+ # end
31
+ #
32
+ # # The class gets a reader method which returns the args,
33
+ # # only marginally useful.
34
+ # Account.permission_level # => [1]
35
+ #
36
+ # # The legacy handler is called, as before:
37
+ # Account.graphql_definition.metadata[:permission_level] # => 1
38
+ module AcceptsDefinition
39
+ def self.included(child)
40
+ child.extend(AcceptsDefinitionDefinitionMethods)
41
+ child.prepend(ToGraphQLExtension)
42
+ child.prepend(InitializeExtension)
43
+ end
44
+
45
+ def self.extended(child)
46
+ if defined?(child::DefinitionMethods)
47
+ child::DefinitionMethods.include(AcceptsDefinitionDefinitionMethods)
48
+ child::DefinitionMethods.prepend(ToGraphQLExtension)
49
+ else
50
+ child.extend(AcceptsDefinitionDefinitionMethods)
51
+ # I tried to use `super`, but super isn't quite right
52
+ # since the method is defined in the same class itself,
53
+ # not the superclass
54
+ child.class_eval do
55
+ class << self
56
+ prepend(ToGraphQLExtension)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ module AcceptsDefinitionDefinitionMethods
63
+ def accepts_definition(name)
64
+ own_accepts_definition_methods << name
65
+
66
+ ivar_name = "@#{name}_args"
67
+ if self.is_a?(Class)
68
+ define_singleton_method(name) do |*args|
69
+ if args.any?
70
+ instance_variable_set(ivar_name, args)
71
+ end
72
+ instance_variable_get(ivar_name) || (superclass.respond_to?(name) ? superclass.public_send(name) : nil)
73
+ end
74
+
75
+ define_method(name) do |*args|
76
+ if args.any?
77
+ instance_variable_set(ivar_name, args)
78
+ end
79
+ instance_variable_get(ivar_name)
80
+ end
81
+ else
82
+ # Special handling for interfaces, define it here
83
+ # so it's appropriately passed down
84
+ self::DefinitionMethods.module_eval do
85
+ define_method(name) do |*args|
86
+ if args.any?
87
+ instance_variable_set(ivar_name, args)
88
+ end
89
+ instance_variable_get(ivar_name) || ((int = interfaces.first { |i| i.respond_to?()}) && int.public_send(name))
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ def accepts_definition_methods
96
+ inherited_methods = if self.is_a?(Class)
97
+ superclass.respond_to?(:accepts_definition_methods) ? superclass.accepts_definition_methods : []
98
+ elsif self.is_a?(Module)
99
+ m = []
100
+ ancestors.each do |a|
101
+ if a.respond_to?(:own_accepts_definition_methods)
102
+ m.concat(a.own_accepts_definition_methods)
103
+ end
104
+ end
105
+ m
106
+ else
107
+ self.class.accepts_definition_methods
108
+ end
109
+
110
+ own_accepts_definition_methods + inherited_methods
111
+ end
112
+
113
+ def own_accepts_definition_methods
114
+ @own_accepts_definition_methods ||= []
115
+ end
116
+ end
117
+
118
+ module ToGraphQLExtension
119
+ def to_graphql
120
+ defn = super
121
+ accepts_definition_methods.each do |method_name|
122
+ value = public_send(method_name)
123
+ if !value.nil?
124
+ defn = defn.redefine { public_send(method_name, *value) }
125
+ end
126
+ end
127
+ defn
128
+ end
129
+ end
130
+
131
+ module InitializeExtension
132
+ def initialize(*args, **kwargs, &block)
133
+ self.class.accepts_definition_methods.each do |method_name|
134
+ if kwargs.key?(method_name)
135
+ value = kwargs.delete(method_name)
136
+ if !value.is_a?(Array)
137
+ value = [value]
138
+ end
139
+ instance_variable_set("@#{method_name}_args", value)
140
+ end
141
+ end
142
+ super(*args, **kwargs, &block)
143
+ end
144
+
145
+ def accepts_definition_methods
146
+ self.class.accepts_definition_methods
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ # DSL methods shared by lots of things in the GraphQL Schema.
7
+ # @api private
8
+ # @see Classes that extend this, eg {GraphQL::Schema::Object}
9
+ module BaseDSLMethods
10
+ # Call this with a new name to override the default name for this schema member; OR
11
+ # call it without an argument to get the name of this schema member
12
+ #
13
+ # The default name is the Ruby constant name,
14
+ # without any namespaces and with any `-Type` suffix removed
15
+ # @param new_name [String]
16
+ # @return [String]
17
+ def graphql_name(new_name = nil)
18
+ case
19
+ when new_name
20
+ @graphql_name = new_name
21
+ when overridden = overridden_graphql_name
22
+ overridden
23
+ else # Fallback to Ruby constant name
24
+ raise NotImplementedError, 'Anonymous class should declare an `graphql_name`' if name.nil?
25
+
26
+ name.split("::").last.sub(/Type\Z/, "")
27
+ end
28
+ end
29
+
30
+ # Just a convenience method to point out that people should use graphql_name instead
31
+ def name(new_name = nil)
32
+ return super() if new_name.nil?
33
+
34
+ fail(
35
+ "The new name override method is `graphql_name`, not `name`. Usage: "\
36
+ "graphql_name \"#{new_name}\""
37
+ )
38
+ end
39
+
40
+ # Call this method to provide a new description; OR
41
+ # call it without an argument to get the description
42
+ # @param new_description [String]
43
+ # @return [String]
44
+ def description(new_description = nil)
45
+ if new_description
46
+ @description = new_description
47
+ else
48
+ @description || find_inherited_method(:description, nil)
49
+ end
50
+ end
51
+
52
+ # @return [Boolean] If true, this object is part of the introspection system
53
+ def introspection(new_introspection = nil)
54
+ if !new_introspection.nil?
55
+ @introspection = new_introspection
56
+ else
57
+ @introspection || find_inherited_method(:introspection, false)
58
+ end
59
+ end
60
+
61
+ # The mutation this type was derived from, if it was derived from a mutation
62
+ # @return [Class]
63
+ def mutation(mutation_class = nil)
64
+ if mutation_class
65
+ @mutation = mutation_class
66
+ end
67
+ @mutation
68
+ end
69
+
70
+ # @return [GraphQL::BaseType] Convert this type to a legacy-style object.
71
+ def to_graphql
72
+ raise NotImplementedError
73
+ end
74
+
75
+ def overridden_graphql_name
76
+ @graphql_name || find_inherited_method(:overridden_graphql_name, nil)
77
+ end
78
+
79
+ def unwrap
80
+ self
81
+ end
82
+
83
+ private
84
+
85
+ def find_inherited_method(method_name, default_value)
86
+ if self.is_a?(Class)
87
+ superclass.respond_to?(method_name) ? superclass.public_send(method_name) : default_value
88
+ else
89
+ ancestors[1..-1].each do |ancestor|
90
+ if ancestor.respond_to?(method_name)
91
+ return ancestor.public_send(method_name)
92
+ end
93
+ end
94
+ default_value
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class Member
5
+ # @api private
6
+ module BuildType
7
+ LIST_TYPE_ERROR = "Use an array of [T] or [T, null: true] for list types; other arrays are not supported"
8
+
9
+ module_function
10
+ # @param type_expr [String, Class, GraphQL::BaseType]
11
+ # @return [GraphQL::BaseType]
12
+ def parse_type(type_expr, null:)
13
+ list_type = false
14
+
15
+ return_type = case type_expr
16
+ when String
17
+ case type_expr
18
+ when "String"
19
+ GraphQL::STRING_TYPE
20
+ when "Int", "Integer"
21
+ GraphQL::INT_TYPE
22
+ when "Float"
23
+ GraphQL::FLOAT_TYPE
24
+ when "Boolean"
25
+ GraphQL::BOOLEAN_TYPE
26
+ when "ID"
27
+ GraphQL::ID_TYPE
28
+ when /\A\[.*\]\Z/
29
+ list_type = true
30
+ # List members are required by default
31
+ parse_type(type_expr[1..-2], null: false)
32
+ when /.*!\Z/
33
+ null = false
34
+ parse_type(type_expr[0..-2], null: true)
35
+ else
36
+ maybe_type = Object.const_get(type_expr)
37
+ case maybe_type
38
+ when GraphQL::BaseType
39
+ maybe_type
40
+ when Module
41
+ # This is a way to check that it's the right kind of module:
42
+ if maybe_type.respond_to?(:graphql_definition)
43
+ maybe_type
44
+ else
45
+ raise ArgumentError, "Unexpected class/module found for GraphQL type: #{type_expr} (must be type definition class/module)"
46
+ end
47
+ end
48
+ end
49
+ when GraphQL::BaseType, GraphQL::Schema::LateBoundType
50
+ type_expr
51
+ when Array
52
+ case type_expr.length
53
+ when 1
54
+ list_type = true
55
+ # List members are required by default
56
+ parse_type(type_expr.first, null: false)
57
+ when 2
58
+ inner_type, nullable_option = type_expr
59
+ if nullable_option.keys != [:null] || nullable_option.values != [true]
60
+ raise ArgumentError, LIST_TYPE_ERROR
61
+ end
62
+ list_type = true
63
+ parse_type(inner_type, null: true)
64
+ else
65
+ raise ArgumentError, LIST_TYPE_ERROR
66
+ end
67
+ when Module
68
+ # This is a way to check that it's the right kind of module:
69
+ if type_expr.respond_to?(:graphql_definition)
70
+ type_expr
71
+ else
72
+ # Eg `String` => GraphQL::STRING_TYPE
73
+ parse_type(type_expr.name, null: true)
74
+ end
75
+ when false
76
+ raise ArgumentError, "Received `false` instead of a type, maybe a `!` should be replaced with `null: true` (for fields) or `required: true` (for arguments)"
77
+ end
78
+
79
+ if return_type.nil?
80
+ raise "Unexpected type input: #{type_expr} (#{type_expr.class})"
81
+ end
82
+
83
+ # Apply list_type first, that way the
84
+ # .to_non_null_type applies to the list type, not the inner type
85
+ if list_type
86
+ return_type = return_type.to_list_type
87
+ end
88
+
89
+ if !null
90
+ return_type = return_type.to_non_null_type
91
+ end
92
+
93
+
94
+ return_type
95
+ end
96
+
97
+ def to_type_name(something)
98
+ case something
99
+ when GraphQL::BaseType, GraphQL::Schema::LateBoundType
100
+ something.unwrap.name
101
+ when Array
102
+ to_type_name(something.first)
103
+ when Module
104
+ if something.respond_to?(:graphql_name)
105
+ something.graphql_name
106
+ else
107
+ to_type_name(something.name)
108
+ end
109
+ when String
110
+ something.gsub(/\]\[\!/, "").split("::").last
111
+ when GraphQL::Schema::NonNull, GraphQL::Schema::List
112
+ to_type_name(something.unwrap)
113
+ else
114
+ raise "Unhandled to_type_name input: #{something} (#{something.class})"
115
+ end
116
+ end
117
+
118
+ def camelize(string)
119
+ return string unless string.include?("_")
120
+ camelized = string.split('_').map(&:capitalize).join
121
+ camelized[0] = camelized[0].downcase
122
+ if (match_data = string.match(/\A(_+)/))
123
+ camelized = "#{match_data[0]}#{camelized}"
124
+ end
125
+ camelized
126
+ end
127
+
128
+ def underscore(string)
129
+ string
130
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
131
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2') # someThing -> some_Thing
132
+ .downcase
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ # Adds a layer of caching over user-supplied `.to_graphql` methods.
7
+ # Users override `.to_graphql`, but all runtime code should use `.graphql_definition`.
8
+ # @api private
9
+ # @see concrete classes that extend this, eg {Schema::Object}
10
+ module CachedGraphQLDefinition
11
+ # A cached result of {.to_graphql}.
12
+ # It's cached here so that user-overridden {.to_graphql} implementations
13
+ # are also cached
14
+ def graphql_definition
15
+ @graphql_definition ||= to_graphql
16
+ end
17
+
18
+ # Wipe out the cached graphql_definition so that `.to_graphql` will be called again.
19
+ def initialize_copy(original)
20
+ super
21
+ @graphql_definition = nil
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end