rails-graphql 0.2.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (315) hide show
  1. checksums.yaml +4 -4
  2. data/ext/console.rb +18 -0
  3. data/ext/extconf.h +3 -0
  4. data/ext/extconf.rb +1 -54
  5. data/ext/gql_parser.c +631 -0
  6. data/ext/gql_parser.h +21 -0
  7. data/ext/shared.c +477 -0
  8. data/ext/shared.h +177 -0
  9. data/lib/generators/graphql/channel_generator.rb +27 -0
  10. data/lib/generators/graphql/controller_generator.rb +9 -4
  11. data/lib/generators/graphql/install_generator.rb +49 -0
  12. data/lib/generators/graphql/schema_generator.rb +9 -4
  13. data/lib/generators/graphql/templates/channel.erb +7 -0
  14. data/lib/generators/graphql/templates/config.rb +97 -0
  15. data/lib/generators/graphql/templates/controller.erb +2 -0
  16. data/lib/generators/graphql/templates/schema.erb +5 -3
  17. data/lib/gql_parser.so +0 -0
  18. data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
  19. data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
  20. data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
  21. data/lib/rails/graphql/alternative/field_set.rb +48 -0
  22. data/lib/rails/graphql/alternative/mutation.rb +17 -0
  23. data/lib/rails/graphql/alternative/query.rb +98 -0
  24. data/lib/rails/graphql/alternative/subscription.rb +18 -0
  25. data/lib/rails/graphql/alternative.rb +20 -0
  26. data/lib/rails/graphql/argument.rb +25 -26
  27. data/lib/rails/graphql/callback.rb +30 -14
  28. data/lib/rails/graphql/collectors/hash_collector.rb +26 -7
  29. data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
  30. data/lib/rails/graphql/collectors/json_collector.rb +43 -17
  31. data/lib/rails/graphql/collectors.rb +4 -4
  32. data/lib/rails/graphql/config.rb +154 -23
  33. data/lib/rails/graphql/directive/cached_directive.rb +33 -0
  34. data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
  35. data/lib/rails/graphql/directive/include_directive.rb +4 -4
  36. data/lib/rails/graphql/directive/skip_directive.rb +4 -4
  37. data/lib/rails/graphql/directive/specified_by_directive.rb +24 -0
  38. data/lib/rails/graphql/directive.rb +134 -73
  39. data/lib/rails/graphql/errors.rb +33 -4
  40. data/lib/rails/graphql/event.rb +21 -9
  41. data/lib/rails/graphql/field/authorized_field.rb +17 -6
  42. data/lib/rails/graphql/field/input_field.rb +8 -12
  43. data/lib/rails/graphql/field/mutation_field.rb +43 -9
  44. data/lib/rails/graphql/field/output_field.rb +112 -12
  45. data/lib/rails/graphql/field/proxied_field.rb +35 -26
  46. data/lib/rails/graphql/field/resolved_field.rb +27 -25
  47. data/lib/rails/graphql/field/scoped_config.rb +10 -4
  48. data/lib/rails/graphql/field/subscription_field.rb +123 -0
  49. data/lib/rails/graphql/field/typed_field.rb +69 -24
  50. data/lib/rails/graphql/field.rb +89 -74
  51. data/lib/rails/graphql/global_id.rb +89 -0
  52. data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
  53. data/lib/rails/graphql/helpers/inherited_collection/array.rb +51 -0
  54. data/lib/rails/graphql/helpers/inherited_collection/base.rb +45 -0
  55. data/lib/rails/graphql/helpers/inherited_collection/hash.rb +88 -0
  56. data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
  57. data/lib/rails/graphql/helpers/instantiable.rb +15 -0
  58. data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
  59. data/lib/rails/graphql/helpers/registerable.rb +44 -62
  60. data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
  61. data/lib/rails/graphql/helpers/with_arguments.rb +33 -28
  62. data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
  63. data/lib/rails/graphql/helpers/with_callbacks.rb +28 -11
  64. data/lib/rails/graphql/helpers/with_description.rb +73 -0
  65. data/lib/rails/graphql/helpers/with_directives.rb +58 -30
  66. data/lib/rails/graphql/helpers/with_events.rb +22 -23
  67. data/lib/rails/graphql/helpers/with_fields.rb +86 -26
  68. data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
  69. data/lib/rails/graphql/helpers/with_name.rb +44 -0
  70. data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
  71. data/lib/rails/graphql/helpers/with_owner.rb +8 -7
  72. data/lib/rails/graphql/helpers/with_schema_fields.rb +162 -56
  73. data/lib/rails/graphql/helpers/with_validator.rb +9 -9
  74. data/lib/rails/graphql/helpers.rb +10 -3
  75. data/lib/rails/graphql/introspection.rb +43 -36
  76. data/lib/rails/graphql/railtie.rb +89 -33
  77. data/lib/rails/graphql/railties/app/base_channel.rb +10 -0
  78. data/lib/rails/graphql/railties/app/base_controller.rb +12 -0
  79. data/lib/rails/graphql/railties/app/views/_cable.js.erb +56 -0
  80. data/lib/rails/graphql/railties/app/views/_fetch.js.erb +20 -0
  81. data/lib/rails/graphql/railties/app/views/graphiql.html.erb +101 -0
  82. data/lib/rails/graphql/railties/base_generator.rb +5 -17
  83. data/lib/rails/graphql/railties/channel.rb +157 -0
  84. data/lib/rails/graphql/railties/controller.rb +91 -25
  85. data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
  86. data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
  87. data/lib/rails/graphql/request/arguments.rb +26 -50
  88. data/lib/rails/graphql/request/backtrace.rb +212 -0
  89. data/lib/rails/graphql/request/component/field.rb +98 -70
  90. data/lib/rails/graphql/request/component/fragment.rb +80 -26
  91. data/lib/rails/graphql/request/component/operation/subscription.rb +162 -4
  92. data/lib/rails/graphql/request/component/operation.rb +73 -34
  93. data/lib/rails/graphql/request/component/spread.rb +79 -27
  94. data/lib/rails/graphql/request/component/typename.rb +28 -13
  95. data/lib/rails/graphql/request/component.rb +77 -36
  96. data/lib/rails/graphql/request/context.rb +19 -9
  97. data/lib/rails/graphql/request/errors.rb +16 -6
  98. data/lib/rails/graphql/request/event.rb +23 -8
  99. data/lib/rails/graphql/request/helpers/directives.rb +69 -27
  100. data/lib/rails/graphql/request/helpers/selection_set.rb +57 -25
  101. data/lib/rails/graphql/request/helpers/value_writers.rb +24 -19
  102. data/lib/rails/graphql/request/prepared_data.rb +100 -0
  103. data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
  104. data/lib/rails/graphql/request/steps/organizable.rb +111 -49
  105. data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +21 -8
  106. data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +16 -7
  107. data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
  108. data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
  109. data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
  110. data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
  111. data/lib/rails/graphql/request/strategy.rb +147 -77
  112. data/lib/rails/graphql/request/subscription.rb +82 -0
  113. data/lib/rails/graphql/request.rb +353 -104
  114. data/lib/rails/graphql/schema.rb +251 -106
  115. data/lib/rails/graphql/shortcuts.rb +33 -8
  116. data/lib/rails/graphql/source/active_record/builders.rb +64 -51
  117. data/lib/rails/graphql/source/active_record_source.rb +158 -82
  118. data/lib/rails/graphql/source/base.rb +83 -0
  119. data/lib/rails/graphql/source/builder.rb +115 -0
  120. data/lib/rails/graphql/source/scoped_arguments.rb +39 -21
  121. data/lib/rails/graphql/source.rb +90 -228
  122. data/lib/rails/graphql/subscription/provider/action_cable.rb +113 -0
  123. data/lib/rails/graphql/subscription/provider/base.rb +192 -0
  124. data/lib/rails/graphql/subscription/provider.rb +18 -0
  125. data/lib/rails/graphql/subscription/store/base.rb +141 -0
  126. data/lib/rails/graphql/subscription/store/memory.rb +136 -0
  127. data/lib/rails/graphql/subscription/store.rb +19 -0
  128. data/lib/rails/graphql/subscription.rb +17 -0
  129. data/lib/rails/graphql/to_gql.rb +29 -32
  130. data/lib/rails/graphql/type/creator.rb +196 -0
  131. data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
  132. data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
  133. data/lib/rails/graphql/type/enum.rb +44 -50
  134. data/lib/rails/graphql/type/input.rb +92 -25
  135. data/lib/rails/graphql/type/interface.rb +29 -28
  136. data/lib/rails/graphql/type/object/directive_object.rb +10 -9
  137. data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
  138. data/lib/rails/graphql/type/object/field_object.rb +24 -6
  139. data/lib/rails/graphql/type/object/input_value_object.rb +6 -7
  140. data/lib/rails/graphql/type/object/schema_object.rb +5 -8
  141. data/lib/rails/graphql/type/object/type_object.rb +62 -25
  142. data/lib/rails/graphql/type/object.rb +34 -26
  143. data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
  144. data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
  145. data/lib/rails/graphql/type/scalar/binary_scalar.rb +5 -3
  146. data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
  147. data/lib/rails/graphql/type/scalar/date_scalar.rb +5 -3
  148. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +5 -3
  149. data/lib/rails/graphql/type/scalar/decimal_scalar.rb +5 -3
  150. data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
  151. data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
  152. data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
  153. data/lib/rails/graphql/type/scalar/json_scalar.rb +41 -0
  154. data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
  155. data/lib/rails/graphql/type/scalar/time_scalar.rb +8 -6
  156. data/lib/rails/graphql/type/scalar.rb +26 -23
  157. data/lib/rails/graphql/type/union.rb +21 -18
  158. data/lib/rails/graphql/type.rb +43 -26
  159. data/lib/rails/graphql/type_map.rb +268 -165
  160. data/lib/rails/graphql/uri.rb +167 -0
  161. data/lib/rails/graphql/version.rb +19 -3
  162. data/lib/rails/graphql.rake +3 -0
  163. data/lib/rails/graphql.rb +91 -56
  164. data/lib/rails-graphql.rb +1 -1
  165. data/test/assets/en.yml +29 -0
  166. data/test/assets/introspection-mem.txt +1 -1
  167. data/test/assets/introspection.gql +2 -0
  168. data/test/assets/mem.gql +86 -99
  169. data/test/assets/mysql.gql +406 -0
  170. data/test/assets/sqlite.gql +96 -73
  171. data/test/assets/translate.gql +346 -0
  172. data/test/config.rb +19 -8
  173. data/test/graphql/schema_test.rb +14 -50
  174. data/test/graphql/source_test.rb +8 -85
  175. data/test/graphql/type/enum_test.rb +207 -203
  176. data/test/graphql/type/input_test.rb +14 -9
  177. data/test/graphql/type/interface_test.rb +12 -9
  178. data/test/graphql/type/object_test.rb +8 -2
  179. data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
  180. data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
  181. data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
  182. data/test/graphql/type_map_test.rb +63 -81
  183. data/test/graphql/type_test.rb +0 -19
  184. data/test/graphql_test.rb +1 -1
  185. data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
  186. data/test/integration/config.rb +36 -3
  187. data/test/integration/customization_test.rb +39 -0
  188. data/test/integration/global_id_test.rb +99 -0
  189. data/test/integration/memory/star_wars_introspection_test.rb +24 -16
  190. data/test/integration/memory/star_wars_query_test.rb +54 -3
  191. data/test/integration/memory/star_wars_validation_test.rb +3 -3
  192. data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
  193. data/test/integration/persisted_query_test.rb +87 -0
  194. data/test/integration/resolver_precedence_test.rb +154 -0
  195. data/test/integration/schemas/memory.rb +24 -10
  196. data/test/integration/schemas/mysql.rb +62 -0
  197. data/test/integration/schemas/sqlite.rb +21 -12
  198. data/test/integration/sqlite/star_wars_global_id_test.rb +89 -0
  199. data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
  200. data/test/integration/sqlite/star_wars_query_test.rb +14 -1
  201. data/test/integration/translate_test.rb +73 -0
  202. data/test/test_ext.rb +16 -13
  203. metadata +125 -161
  204. data/ext/depend +0 -3
  205. data/ext/graphqlparser/Ast.cpp +0 -346
  206. data/ext/graphqlparser/Ast.h +0 -1214
  207. data/ext/graphqlparser/AstNode.h +0 -36
  208. data/ext/graphqlparser/AstVisitor.h +0 -137
  209. data/ext/graphqlparser/GraphQLParser.cpp +0 -76
  210. data/ext/graphqlparser/GraphQLParser.h +0 -55
  211. data/ext/graphqlparser/JsonVisitor.cpp +0 -161
  212. data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
  213. data/ext/graphqlparser/JsonVisitor.h +0 -121
  214. data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
  215. data/ext/graphqlparser/VERSION +0 -1
  216. data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
  217. data/ext/graphqlparser/c/GraphQLAst.h +0 -180
  218. data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
  219. data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
  220. data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
  221. data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  222. data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
  223. data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  224. data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
  225. data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
  226. data/ext/graphqlparser/c/GraphQLParser.h +0 -54
  227. data/ext/graphqlparser/dump_json_ast.cpp +0 -48
  228. data/ext/graphqlparser/lexer.lpp +0 -324
  229. data/ext/graphqlparser/parser.ypp +0 -693
  230. data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
  231. data/ext/graphqlparser/parsergen/lexer.h +0 -528
  232. data/ext/graphqlparser/parsergen/location.hh +0 -189
  233. data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
  234. data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
  235. data/ext/graphqlparser/parsergen/position.hh +0 -179
  236. data/ext/graphqlparser/parsergen/stack.hh +0 -156
  237. data/ext/graphqlparser/syntaxdefs.h +0 -19
  238. data/ext/libgraphqlparser/AstNode.h +0 -36
  239. data/ext/libgraphqlparser/CMakeLists.txt +0 -148
  240. data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
  241. data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
  242. data/ext/libgraphqlparser/GraphQLParser.h +0 -55
  243. data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
  244. data/ext/libgraphqlparser/JsonVisitor.h +0 -121
  245. data/ext/libgraphqlparser/LICENSE +0 -22
  246. data/ext/libgraphqlparser/README.clang-tidy +0 -7
  247. data/ext/libgraphqlparser/README.md +0 -84
  248. data/ext/libgraphqlparser/ast/ast.ast +0 -203
  249. data/ext/libgraphqlparser/ast/ast.py +0 -61
  250. data/ext/libgraphqlparser/ast/c.py +0 -100
  251. data/ext/libgraphqlparser/ast/c.pyc +0 -0
  252. data/ext/libgraphqlparser/ast/c_impl.py +0 -61
  253. data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
  254. data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
  255. data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
  256. data/ext/libgraphqlparser/ast/casing.py +0 -26
  257. data/ext/libgraphqlparser/ast/casing.pyc +0 -0
  258. data/ext/libgraphqlparser/ast/cxx.py +0 -197
  259. data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
  260. data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
  261. data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
  262. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
  263. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
  264. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
  265. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
  266. data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
  267. data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
  268. data/ext/libgraphqlparser/ast/js.py +0 -65
  269. data/ext/libgraphqlparser/ast/license.py +0 -10
  270. data/ext/libgraphqlparser/ast/license.pyc +0 -0
  271. data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
  272. data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
  273. data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  274. data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
  275. data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  276. data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
  277. data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
  278. data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
  279. data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
  280. data/ext/libgraphqlparser/cmake/version.cmake +0 -16
  281. data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
  282. data/ext/libgraphqlparser/go/README.md +0 -20
  283. data/ext/libgraphqlparser/go/callbacks.go +0 -18
  284. data/ext/libgraphqlparser/go/gotest.go +0 -64
  285. data/ext/libgraphqlparser/lexer.lpp +0 -324
  286. data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
  287. data/ext/libgraphqlparser/parser.ypp +0 -693
  288. data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
  289. data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
  290. data/ext/libgraphqlparser/parsergen/location.hh +0 -189
  291. data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
  292. data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
  293. data/ext/libgraphqlparser/parsergen/position.hh +0 -179
  294. data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
  295. data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
  296. data/ext/libgraphqlparser/python/README.md +0 -5
  297. data/ext/libgraphqlparser/python/example.py +0 -31
  298. data/ext/libgraphqlparser/syntaxdefs.h +0 -19
  299. data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
  300. data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
  301. data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
  302. data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
  303. data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
  304. data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
  305. data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
  306. data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
  307. data/ext/libgraphqlparser/test/valgrind.supp +0 -33
  308. data/ext/version.cpp +0 -21
  309. data/lib/graphqlparser.so +0 -0
  310. data/lib/rails/graphql/native/functions.rb +0 -38
  311. data/lib/rails/graphql/native/location.rb +0 -41
  312. data/lib/rails/graphql/native/pointers.rb +0 -23
  313. data/lib/rails/graphql/native/visitor.rb +0 -349
  314. data/lib/rails/graphql/native.rb +0 -56
  315. data/test/integration/schemas/authorization.rb +0 -12
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ class Source
6
+ module Builder
7
+
8
+ # Check if the object was already built
9
+ def built?(part = nil)
10
+ defined?(@built) && @built.present? &&
11
+ (part.nil? || @built.include?(part.to_sym))
12
+ end
13
+
14
+ # Build all from all descendant sources
15
+ def build_all_sources
16
+ descendants.each(&:build_all)
17
+ end
18
+
19
+ # Trigger a safe build of everything
20
+ def build_all
21
+ build_all! unless abstract?
22
+ end
23
+
24
+ # Allows building anything that is in hooks
25
+ def respond_to_missing?(method_name, *)
26
+ return super unless method_name.to_s.start_with?('build_') &&
27
+ hook_names.include?(method_name.to_s[6..-1].to_sym)
28
+ end
29
+
30
+ # Allow fast creation of values
31
+ def method_missing(method_name, *args, **xargs, &block)
32
+ return super unless method_name.to_s.start_with?('build_')
33
+
34
+ type = method_name.to_s[6..-1]
35
+ type = type.singularize unless hook_names.include?(type.to_sym)
36
+ type = type.to_sym
37
+ return if built?(type)
38
+
39
+ import_skips_for(type, xargs)
40
+ build!(type, *args, **xargs, &block)
41
+ end
42
+
43
+ protected
44
+
45
+ # Store the list of built steps
46
+ def built
47
+ @built ||= Set.new
48
+ end
49
+
50
+ private
51
+
52
+ # Import all options-based settings for skipping field
53
+ def import_skips_for(type, options)
54
+ return if type == :all
55
+
56
+ if !(values = options.delete(:except)).nil?
57
+ segmented_skip_fields[type] += GraphQL.enumerate(values).map do |value|
58
+ value.to_s.underscore
59
+ end
60
+ end
61
+
62
+ if !(values = options.delete(:only)).nil?
63
+ segmented_only_fields[type] += GraphQL.enumerate(values).map do |value|
64
+ value.to_s.underscore
65
+ end
66
+ end
67
+ end
68
+
69
+ # Build all the hooks if it's not built
70
+ def build_all!
71
+ catch(:done) do
72
+ hook_names.to_enum.drop(1).each do |hook|
73
+ send("build_#{hook}")
74
+ end
75
+ end
76
+ end
77
+
78
+ # Check if the build process can happen
79
+ def ensure_build!(type)
80
+ raise DefinitionError, (+<<~MSG).squish if hook_names.exclude?(type)
81
+ #{self.name} doesn't know how build #{type}, hook not proper defined.
82
+ MSG
83
+
84
+ raise DefinitionError, (+<<~MSG).squish if abstract
85
+ Abstract source #{name} cannot be built.
86
+ MSG
87
+
88
+ raise DefinitionError, (+<<~MSG).squish if built?(type)
89
+ The #{type} part is already built.
90
+ MSG
91
+ end
92
+
93
+ # Build all the objects associated with this source
94
+ def build!(type)
95
+ ensure_build!(type)
96
+ built << type
97
+
98
+ schema_type = Helpers::WithSchemaFields::TYPE_FIELD_CLASS.key?(type)
99
+ catch(:skip) { run_hooks(:start) } unless built?(:start)
100
+ catch(:skip) { run_hooks(type, hook_scope_for(type, schema_type)) }
101
+
102
+ attach_fields!(type, fields_for(type)) if schema_type && fields_for?(type)
103
+ end
104
+
105
+ # Get the correct +self_object+ for the hook instance
106
+ def hook_scope_for(type, schema_type)
107
+ type = type.to_sym
108
+ klass = schema_type ? 'WithSchemaFields::ScopedConfig' : 'AttributeDelegator'
109
+ Source::ScopedConfig.new(self, Helpers.const_get(klass).new(self, type), type)
110
+ end
111
+
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,13 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
5
  # This is a helper class that allows sources to have scoped-based arguments,
6
6
  # meaning that when an argument is present, it triggers the underlying block
7
7
  # on the fields where the argument was attached to
8
- #
9
- # TODO: Easy the usage of scoped arguments with AR, to map model scopes as
10
- # arguments using the abilities here provided
11
8
  module Source::ScopedArguments
12
9
  def self.included(other)
13
10
  other.extend(ClassMethods)
@@ -15,41 +12,58 @@ module Rails # :nodoc:
15
12
 
16
13
  # Extended argument class to be the instance of the scoped
17
14
  class Argument < GraphQL::Argument
18
- attr_reader :block, :fields
19
-
20
- def initialize(*args, on: nil, **xargs, &block)
15
+ def initialize(*args, block:, on: nil, **xargs)
21
16
  super(*args, **xargs)
22
17
 
23
- @block = block
24
- @fields = Array.wrap(on).presence
18
+ @block = (block == true) ? name : block
19
+ @fields = on
20
+ end
21
+
22
+ # Apply the argument block to the given object, using or not the value
23
+ def apply_to(object, value)
24
+ callable = @block.is_a?(Symbol) ? object.method(@block) : @block
25
+ raise ::ArgumentError, (+<<~MSG) unless callable.respond_to?(:call)
26
+ Unable to call "#{@block.inspect}" on #{object.class}.
27
+ MSG
28
+
29
+ args = (callable.arity == 1 || callable.arity == -1) ? [value] : nil
30
+
31
+ return callable.call(*args) if callable.is_a?(Method)
32
+ object.instance_exec(*args, &callable)
25
33
  end
26
34
 
27
35
  # Check if the argument should be attached to the given +field+
28
36
  def attach_to?(field)
29
- return true if fields.nil?
37
+ return true if @fields.nil?
30
38
 
31
- fields.any? do |item|
39
+ GraphQL.enumerate(@fields).any? do |item|
32
40
  (item.is_a?(Symbol) && field.name.eql?(item)) || field.gql_name.eql?(item)
33
41
  end
34
42
  end
35
43
  end
36
44
 
37
- module ClassMethods # :nodoc:
45
+ module ClassMethods
38
46
  # Return the list of scoped params defined
39
47
  def scoped_arguments
40
48
  defined?(@scoped_arguments) ? @scoped_arguments : {}
41
49
  end
42
50
 
51
+ # Hook into the attach fields process to attach the scoped arguments
52
+ def attach_fields!(type, fields)
53
+ attach_scoped_arguments_to(fields.values)
54
+ super
55
+ end
56
+
43
57
  protected
44
58
 
45
59
  # Add a new scoped param to the list
46
60
  def scoped_argument(param, type = :string, proc_method = nil, **settings, &block)
47
- block = proc_method if proc_method.present? && block.nil?
48
- argument = Argument.new(param, type, **settings, owner: self, &block)
61
+ block ||= proc_method if proc_method.present?
62
+ argument = Argument.new(param, type, **settings, owner: self, block: block)
49
63
  (@scoped_arguments ||= {})[argument.name] = argument
50
64
  end
51
65
 
52
- alias scoped_arg scoped_arguments
66
+ alias scoped_arg scoped_argument
53
67
 
54
68
  # Helper method to attach the scoped arguments to a given +field+
55
69
  def attach_scoped_arguments_to(*fields, safe: true)
@@ -69,14 +83,18 @@ module Rails # :nodoc:
69
83
  # Find all the executable arguments attached to the running field and
70
84
  # call them with the given object
71
85
  def inject_scopes(object, assigned_to = nil)
72
- return object if event.field.nil? || (args_source = event.send(:args_source)).nil?
86
+ return object if event.field.nil? || (field_args = event.field.all_arguments).blank?
73
87
 
88
+ args_source = event.send(:args_source)
74
89
  event.data[assigned_to] ||= object unless assigned_to.nil?
75
- event.field.all_arguments.each_value.inject(object) do |result, argument|
76
- next result unless argument.respond_to?(:block) && args_source.key?(argument.name)
77
- send_args = argument.block.arity.eql?(1) ? [args_source[argument.name]] : []
90
+ field_args.each_value.inject(object) do |result, argument|
91
+ arg_value = args_source.key?(argument.name) \
92
+ ? args_source[argument.name] \
93
+ : argument.default
94
+
95
+ next result if arg_value.nil? || !argument.is_a?(Argument)
78
96
 
79
- value = result.instance_exec(*send_args, &argument.block)
97
+ value = argument.apply_to(result, arg_value)
80
98
  value = value.nil? ? result : value
81
99
 
82
100
  assigned_to.nil? ? value : event.data[assigned_to] = value
@@ -1,29 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
5
  # = GraphQL Source
6
6
  #
7
7
  # Source is an abstract object that can contains fields, objects, and
8
- # informations that them are delivered to the relative schemas throughout
9
- # proxies, ensuring that it still kepps the main ownership of the objects
8
+ # information that them are delivered to the relative schemas throughout
9
+ # proxies, ensuring that it still keeps the main ownership of the objects
10
10
  class Source
11
11
  extend ActiveSupport::Autoload
12
12
 
13
13
  extend Helpers::InheritedCollection
14
- extend Helpers::WithSchemaFields
15
- extend Helpers::WithAssignment
16
14
  extend Helpers::WithNamespace
15
+ extend Helpers::WithEvents
16
+ extend Helpers::WithCallbacks
17
17
 
18
- DEFAULT_NAMESPACES = %i[base].freeze
18
+ include Helpers::Instantiable
19
19
 
20
- eager_autoload do
21
- autoload :ScopedArguments
20
+ autoload :Base
21
+ autoload :Builder
22
22
 
23
- autoload :ActiveRecordSource
24
- end
23
+ autoload :ScopedArguments
24
+ autoload :ActiveRecordSource
25
+
26
+ extend Source::Builder
27
+
28
+ # Helper class to be used as the +self+ in configuration blocks
29
+ ScopedConfig = Struct.new(:receiver, :self_object, :type) do
30
+ def safe_field(name, *args, **xargs, &block)
31
+ return if receiver.send(:skip_field?, name, on: type)
32
+ self_object.safe_field(name, *args, **xargs, &block)
33
+ end
25
34
 
26
- ScopedConfig = Struct.new(:receiver, :self_object) do # :nodoc: all
27
35
  def respond_to_missing?(method_name, include_private = false)
28
36
  self_object.respond_to?(method_name, include_private) ||
29
37
  receiver.respond_to?(method_name, include_private)
@@ -39,53 +47,34 @@ module Rails # :nodoc:
39
47
  # If a source is marked as abstract, it means that it generates a new
40
48
  # source describer and any non-abstract class inherited from it will be
41
49
  # described by this new abstraction
42
- class_attribute :abstract, instance_writer: false, default: false
50
+ class_attribute :abstract, instance_accessor: false, default: false
43
51
 
44
52
  # List of hook names used while describing a new source. This basically
45
53
  # set the order of the execution of the hooks while validating the hooks
46
- # callbacks using the +on+ method. Make sure to kepp the +finish+ hook
47
- # always at the end of the list
48
- class_attribute :hook_names, instance_writer: false,
49
- default: %i[start object input query mutation finish].to_set
54
+ # callbacks using the +on+ method
55
+ class_attribute :hook_names, instance_accessor: false,
56
+ default: %i[start object input query mutation subscription].to_set.freeze
50
57
 
51
58
  # The list of hooks defined in order to describe a source
52
59
  inherited_collection :hooks, instance_reader: false, type: :hash_array
53
60
 
54
- # The name of the class (or the class itself) to be used as superclass for
55
- # the generate GraphQL object type of this source
56
- class_attribute :object_class, instance_writer: false,
57
- default: '::Rails::GraphQL::Type::Object'
58
-
59
- # The name of the class (or the class itself) to be used as superclass for
60
- # the generate GraphQL input type of this source
61
- class_attribute :input_class, instance_writer: false,
62
- default: '::Rails::GraphQL::Type::Input'
63
-
64
- # Mark if the objects created from this source will build fields for
65
- # associations associated to the object
66
- class_attribute :with_associations, instance_writer: false, default: true
67
-
68
61
  # A list of fields to skip when performing shared methods
69
- inherited_collection :skip_fields, instance_reader: false
62
+ inherited_collection :skip_fields, instance_reader: false, type: :set
70
63
 
71
64
  # A list of fields to skip but segmented by holder source
72
65
  inherited_collection :segmented_skip_fields, instance_reader: false, type: :hash_set
73
66
 
74
- # The purpose of instantiating a source is to have access to its public
75
- # methods. It then runs from the strategy perspective, pointing out any
76
- # other methods to the manually set event
77
- delegate_missing_to :event
78
- attr_reader :event
67
+ # A list of fields that should only be included. Available only when using
68
+ # individual builders
69
+ inherited_collection :segmented_only_fields, instance_reader: false, type: :hash_set
79
70
 
80
71
  self.abstract = true
81
72
 
82
73
  class << self
83
- attr_reader :schemas
74
+ delegate :field, :proxy_field, :overwrite_field, :field?, :field_names,
75
+ :gql_name, to: :object
84
76
 
85
- delegate :field, :proxy_field, :overwrite_field, :[], :field?,
86
- :field_names, :gql_name, to: :object
87
-
88
- def kind # :nodoc:
77
+ def kind
89
78
  :source
90
79
  end
91
80
 
@@ -96,27 +85,19 @@ module Rails # :nodoc:
96
85
 
97
86
  # Get the main name of the source
98
87
  def base_name
99
- name.demodulize[0..-7] unless abstract?
100
- end
101
-
102
- # Wait the end of the class in order to create the objects
103
- def inherited(subclass)
104
- subclass.abstract = false
105
- super if defined? super
106
-
107
- pending[subclass] ||= caller(1).find do |item|
108
- !item.end_with?("`inherited'")
109
- end
88
+ name.demodulize[0..-7]
110
89
  end
111
90
 
91
+ # :singleton-method:
112
92
  # Find a source for a given object. If none is found, then raise an
113
93
  # exception
114
94
  def find_for!(object)
115
- find_for(object) || raise(::ArgumentError, <<~MSG.squish)
95
+ find_for(object) || raise(::ArgumentError, (+<<~MSG).squish)
116
96
  Unable to find a source for "#{object.name}".
117
97
  MSG
118
98
  end
119
99
 
100
+ # :singleton-method:
120
101
  # Using the list of +base_sources+, find the first one that can handle
121
102
  # the given +object+
122
103
  def find_for(object)
@@ -124,60 +105,33 @@ module Rails # :nodoc:
124
105
  base_sources.reverse_each.find { |source| object <= source.assigned_class }
125
106
  end
126
107
 
127
- # Return the GraphQL object type associated with the source. It will
128
- # create one if it's not defined yet. The created class will be added
129
- # to the +::GraphQL+ namespace with the addition of any namespace of the
130
- # currect class
131
- def object
132
- @object ||= create_type(superclass: object_class)
133
- end
134
-
135
- # Return the GraphQL input type associated with the source. It will
136
- # create one if it's not defined yet. The created class will be added
137
- # to the +::GraphQL+ namespace with the addition of any namespace of the
138
- # currect class
139
- def input
140
- @input ||= create_type(superclass: input_class)
141
- end
142
-
143
- # Check if the object was already built
144
- def built?
145
- defined?(@built) && !!@built
146
- end
108
+ # Add a new description hook. You can use +throw :skip+ and skip
109
+ # parent hooks. If the class is already built, then execute the hook.
110
+ # Use the +unshift: true+ to add the hook at the beginning of the
111
+ # list, which will then be the last to run
112
+ def step(hook_name, unshift: false, &block)
113
+ raise ArgumentError, (+<<~MSG).squish unless hook_names.include?(hook_name.to_sym)
114
+ The #{hook_name.inspect} is not a valid hook method.
115
+ MSG
147
116
 
148
- # Checks if a given method can act as resolver
149
- def gql_resolver?(method_name)
150
- (instance_methods - GraphQL::Source.instance_methods).include?(method_name)
117
+ if built?(hook_name)
118
+ hook_scope_for(hook_name).instance_exec(&block)
119
+ else
120
+ hooks[hook_name.to_sym].public_send(unshift ? :unshift : :push, block)
121
+ end
151
122
  end
152
123
 
153
124
  # Attach all defined schema fields into the schemas using the namespaces
154
125
  # configured for the source
155
- def attach_fields!
156
- refresh_schemas!
157
- schemas.each_value do |schema|
158
- Helpers::WithSchemaFields::SCHEMA_FIELD_TYPES.keys.each do |type|
159
- list = public_send("#{type}_fields")
160
- next if list.empty?
161
-
162
- list.each_value do |field|
163
- next if schema.has_field?(type, field)
164
- schema.add_proxy_field(type, field)
165
- end
166
- end
167
- end
126
+ def attach_fields!(type = :all, from = self)
127
+ schemas.each { |schema| schema.import_into(type, from) }
168
128
  end
169
129
 
170
130
  # Find all the schemas associated with the configured namespaces
171
- def refresh_schemas!
172
- @schemas = (namespaces.presence || DEFAULT_NAMESPACES).map do |ns|
173
- (schema = Schema.find(ns)).present? ? [ns, schema] : nil
174
- end.compact.to_h
175
- end
176
-
177
- def eager_load! # :nodoc:
178
- super
179
-
180
- build_pending!
131
+ def schemas
132
+ GraphQL.enumerate(namespaces.presence || :base).lazy.filter_map do |ns|
133
+ Schema.find(ns)
134
+ end
181
135
  end
182
136
 
183
137
  protected
@@ -191,78 +145,23 @@ module Rails # :nodoc:
191
145
  end
192
146
 
193
147
  # A little bypass to the actual type map after register method which
194
- # just add the namesapace by default
148
+ # just add the namespace by default
195
149
  # See {TypeMap#after_register}[rdoc-ref:Rails::GraphQL::TypeMap#after_register]
196
150
  def type_map_after_register(*args, **xargs, &block)
197
151
  xargs[:namespaces] ||= namespaces
198
152
  GraphQL.type_map.after_register(*args, **xargs, &block)
199
153
  end
200
154
 
201
- # A helper method to create an enum type
202
- def create_enum(enum_name, values, **xargs, &block)
203
- enumerator = values.each_pair if values.respond_to?(:each_pair)
204
- enumerator ||= values.each.with_index
205
-
206
- xargs = xargs.reverse_merge(once: true)
207
- create_type(:enum, as: enum_name.classify, **xargs) do
208
- indexed! if enumerator.first.last.is_a?(Numeric)
209
- enumerator.sort_by(&:last).map(&:first).each(&method(:add))
210
- instance_exec(&block) if block.present?
211
- end
212
- end
213
-
214
- # Helper method to create a class based on the given type and allows
215
- # several other settings to be executed on it
216
- def create_type(type = nil, **xargs, &block)
217
- name = "#{gql_module.name}::#{xargs.delete(:as) || base_name}"
218
- superclass = xargs.delete(:superclass)
219
- with_owner = xargs.delete(:with_owner)
220
-
221
- if superclass.nil?
222
- superclass = type.to_s.classify
223
- elsif superclass.is_a?(String)
224
- superclass = superclass.constantize
225
- end
226
-
227
- source = self
228
- Schema.send(:create_type, name, superclass, **xargs) do
229
- include Helpers::WithOwner if with_owner
230
- set_namespaces(*source.namespaces)
231
-
232
- self.owner = source if respond_to?(:owner=)
233
- self.assigned_to = source.safe_assigned_class \
234
- if source.assigned? && is_a?(Helpers::WithAssignment)
235
-
236
- instance_exec(&block) if block.present?
237
- end
238
- end
239
-
240
155
  # Add fields to be skipped on the given +source+ as the segment
241
- def skip_on(source, *fields)
156
+ def skip_from(source, *fields)
242
157
  segmented_skip_fields[source] += fields.flatten.compact.map(&:to_sym).to_set
243
158
  end
244
159
 
245
- # Add a new description hook. You can use +throw :skip+ and skip
246
- # parent hooks. If the class is already built, then execute the hook.
247
- # Use the +unshift: true+ to add the hook at the beginning of the
248
- # list, which will then be the last to run
249
- def on(hook_name, unshift: false, &block)
250
- raise ArgumentError, <<~MSG.squish unless hook_names.include?(hook_name.to_sym)
251
- The #{hook_name.inspect} is not a valid hook method.
252
- MSG
253
-
254
- if built?
255
- send("run_#{hook_name}_hooks", block)
256
- else
257
- hooks[hook_name.to_sym].public_send(unshift ? :unshift : :push, block)
258
- end
259
- end
260
-
261
160
  # Creates a hook that throws a done action, preventing any parent hooks
262
161
  def skip(*names)
263
162
  names.each do |hook_name|
264
163
  hook_name = hook_name.to_s.singularize.to_sym
265
- on(hook_name) { throw :skip }
164
+ step(hook_name) { throw :skip }
266
165
  end
267
166
  end
268
167
 
@@ -270,106 +169,69 @@ module Rails # :nodoc:
270
169
  # +on hook_name do; end+
271
170
  def override(hook_name, &block)
272
171
  skip(hook_name)
273
- on(hook_name, &block)
172
+ step(hook_name, &block)
274
173
  end
275
174
 
276
175
  # It's an alternative to +self.hook_names -= %i[*names]+ which
277
176
  # disables a specific hook
278
177
  def disable(*names)
279
- self.hook_names -= names.flatten.map do |hook_name|
178
+ list = names.flatten.map do |hook_name|
280
179
  hook_name.to_s.singularize.to_sym
281
180
  end
181
+
182
+ self.hook_names = (hook_names - list).freeze
282
183
  end
283
184
 
284
185
  # It's an alternative to +self.hook_names += %i[*names]+ which
285
186
  # enables additional hooks
286
187
  def enable(*names)
287
- self.hook_names += names.flatten.map do |hook_name|
188
+ list = names.flatten.map do |hook_name|
288
189
  hook_name.to_s.singularize.to_sym
289
190
  end
290
- end
291
191
 
292
- # Return the module where the GraphQL types should be created at
293
- def gql_module
294
- name.starts_with?('GraphQL::') ? module_parent : ::GraphQL
192
+ self.hook_names = (hook_names + list).freeze
295
193
  end
296
194
 
297
- # Get the list of fields to be skipped from the given +holder+ as the
298
- # segment source
299
- def skips_for(holder)
300
- segment = holder.kind
301
- segment = :input if segment.eql?(:input_object)
302
- segmented = all_segmented_skip_fields[segment]
303
- segmented.present? ? all_skip_fields + segmented : all_skip_fields
304
- end
305
-
306
- private
195
+ # Add one or more fields to the list of fields that needs to be
196
+ # ignored in all places. It converts strings to underscore
197
+ def skip_fields!(*list)
198
+ list = list.flatten.map do |value|
199
+ value.is_a?(Symbol) ? value.to_s : value.to_s.underscore
200
+ end
307
201
 
308
- # The list of pending sources to be built asscoaited to where they
309
- # were defined
310
- def pending
311
- @@pending ||= {}
202
+ self.skip_fields.merge(list)
312
203
  end
313
204
 
314
- # Check if there are pending sources to be built
315
- def pending?
316
- pending.any?
317
- end
205
+ # Check if a given field +name+ should be skipped on the give type
206
+ def skip_field?(name, on:)
207
+ on = :input if on == :input_object
208
+ name = name.to_s.underscore
318
209
 
319
- # Build the pending sources
320
- def build_pending!
321
- while (klass, = pending.shift)
322
- klass.send(:build!) unless klass.abstract?
323
- end
210
+ all_skip_fields&.include?(name) ||
211
+ all_segmented_skip_fields.try(:[], on)&.include?(name) ||
212
+ all_segmented_only_fields.try(:[], on)&.exclude?(name)
324
213
  end
325
214
 
326
- # Find all classes that inherits from source that are abstract,
327
- # meaning that they are a base sources
328
- def base_sources
329
- @@base_sources ||= begin
330
- eager_load!
331
- descendants.select(&:abstract?).to_set
215
+ # Run a list of hooks using the +source+ as the instance of the block
216
+ def run_hooks(hook_name, source = self)
217
+ all_hooks.try(:[], hook_name.to_sym)&.reverse_each do |block|
218
+ source.instance_exec(&block)
332
219
  end
333
220
  end
334
221
 
335
- # Build all the objects associated with this source
336
- def build!
337
- return if built?
338
-
339
- raise DefinitionError, <<~MSG.squish if abstract
340
- Abstract source #{name} cannot be built.
341
- MSG
342
-
343
- @built = true
344
-
345
- catch(:done) do
346
- hook_names.each do |hook_name|
347
- break if hook_name === :finish
348
- catch(:skip) { send("run_#{hook_name}_hooks") }
349
- end
350
- end
222
+ private
351
223
 
352
- catch(:skip) { send(:run_finish_hooks) } if respond_to?(:run_finish_hooks, true)
224
+ # Make sure to reset the value of +abstract+
225
+ def inherited(subclass)
226
+ subclass.abstract = false
227
+ super if defined? super
353
228
  end
354
229
 
355
- {
356
- start: 'self',
357
- finish: 'self',
358
- object: 'Helpers::AttributeDelegator.new(self, :object)',
359
- input: 'Helpers::AttributeDelegator.new(self, :input)',
360
- query: format('schema_scoped_config(self, %s)', ':query'),
361
- mutation: format('schema_scoped_config(self, %s)', ':mutation'),
362
- subscription: format('schema_scoped_config(self, %s)', ':subscription'),
363
- }.each do |key, object|
364
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
365
- def run_#{key}_hooks(list = nil)
366
- source_config = Source::ScopedConfig.new(self, #{object})
367
- Array.wrap(list.presence || all_hooks[:#{key}]).reverse_each do |block|
368
- source_config.instance_exec(&block)
369
- end
370
- end
371
- RUBY
230
+ # Constantize all the base sources that were defined in the settings
231
+ def base_sources
232
+ @@base_sources ||= GraphQL.config.sources.map(&:constantize).to_set
372
233
  end
234
+
373
235
  end
374
236
  end
375
237
  end