rails-graphql 0.2.1 → 1.0.0.rc1

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 (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
@@ -1,7 +1,7 @@
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 module that basically works with fields that have an
6
6
  # assigned type value
7
7
  module Field::TypedField
@@ -13,14 +13,9 @@ module Rails # :nodoc:
13
13
 
14
14
  delegate :input_type?, :output_type?, :leaf_type?, :kind, to: :type_klass
15
15
 
16
- def initialize(name, type, *args, **xargs, &block)
17
- if type.is_a?(Module) && type < GraphQL::Type
18
- @type_klass = type
19
- @type = type.to_sym
20
- else
21
- @type = type.to_s.underscore.to_sym
22
- end
23
-
16
+ def initialize(name, type = nil, *args, **xargs, &block)
17
+ type = (name == :id ? :id : :string) if type.nil?
18
+ assign_type(type)
24
19
  super(name, *args, **xargs, &block)
25
20
  end
26
21
 
@@ -32,11 +27,11 @@ module Rails # :nodoc:
32
27
 
33
28
  # Check if types are compatible
34
29
  def =~(other)
35
- other.is_a?(Field::TypedField) && other.type_klass =~ type_klass && super
30
+ super && other.is_a?(Field::TypedField) && other.type_klass =~ type_klass
36
31
  end
37
32
 
38
33
  # Sometimes the owner does not designate this, but it is safe to assume it
39
- # will be associated to the object valyd types
34
+ # will be associated to the object valid types
40
35
  def valid_field_types
41
36
  owner.try(:valid_field_types) || Type::Object.valid_field_types
42
37
  end
@@ -55,29 +50,67 @@ module Rails # :nodoc:
55
50
  )
56
51
  end
57
52
 
53
+ alias type_class type_klass
54
+
58
55
  # Add the listeners from the associated type
59
56
  def all_listeners
60
- type_klass.all_listeners + super
57
+ inherited = super
58
+ return inherited unless type_klass.listeners?
59
+ inherited.present? ? inherited + type_klass.all_listeners : type_klass.all_listeners
60
+ end
61
+
62
+ # Make sure to check the associated type
63
+ def listeners?
64
+ super || type_klass.listeners?
61
65
  end
62
66
 
63
67
  # Add the events from the associated type
64
68
  def all_events
65
- Helpers.merge_hash_array(type_klass.all_events, super)
69
+ inherited = super
70
+ return inherited unless type_klass.events?
71
+ return type_klass.all_events if inherited.blank?
72
+ Helpers.merge_hash_array(inherited, type_klass.all_events)
73
+ end
74
+
75
+ # Make sure to check the associated type
76
+ def events?
77
+ super || type_klass.events?
78
+ end
79
+
80
+ # Transforms the given value to its representation in a JSON string
81
+ def to_json(value)
82
+ return 'null' if value.nil?
83
+ return type_klass.to_json(value) unless array?
84
+ value.map { |part| type_klass.to_json(part) }
85
+ end
86
+
87
+ # Turn the given value into a JSON string representation
88
+ def as_json(value)
89
+ return if value.nil?
90
+ return type_klass.as_json(value) unless array?
91
+ value.map { |part| type_klass.as_json(part) }
92
+ end
93
+
94
+ # Turn a user input of this given type into an ruby object
95
+ def deserialize(value)
96
+ return if value.nil?
97
+ return type_klass.deserialize(value) unless array?
98
+ value.map { |val| type_klass.deserialize(val) unless val.nil? }
66
99
  end
67
100
 
68
101
  # Checks if the type of the field is valid
69
102
  def validate!(*)
70
103
  super if defined? super
71
104
 
72
- raise ArgumentError, <<~MSG.squish unless type_klass.is_a?(Module)
73
- Unable to find the "#{type.inspect}" input type on GraphQL context.
105
+ raise ArgumentError, (+<<~MSG).squish unless type_klass.is_a?(Module)
106
+ Unable to find the "#{type.inspect}" data type on GraphQL context.
74
107
  MSG
75
108
 
76
109
  valid_type = valid_field_types.empty? || valid_field_types.any? do |base_type|
77
110
  type_klass < base_type
78
111
  end
79
112
 
80
- raise ArgumentError, <<~MSG.squish unless valid_type
113
+ raise ArgumentError, (+<<~MSG).squish unless valid_type
81
114
  The "#{type_klass.base_type}" is not accepted in this context.
82
115
  MSG
83
116
  end
@@ -86,16 +119,28 @@ module Rails # :nodoc:
86
119
 
87
120
  # Little helper that shows the type of the field
88
121
  def inspect_type
89
- result = ': '
90
- result += '[' if array?
91
- result += type_klass.gql_name
92
- result += '!' if array? && !nullable?
93
- result += ']' if array?
94
- result += '!' unless null?
122
+ result = +': '
123
+ result << '[' if array?
124
+ result << type_klass.gql_name
125
+ result << '!' if array? && !nullable?
126
+ result << ']' if array?
127
+ result << '!' unless null?
95
128
  result
96
129
  end
97
130
 
98
- def proxied # :nodoc:
131
+ # A little hidden helper to support forcing reassignment of type, which
132
+ # should only be done with caution
133
+ def assign_type(type)
134
+ if type.is_a?(Module) && type < GraphQL::Type
135
+ @type_klass = type
136
+ @type = type.to_sym
137
+ else
138
+ @type_klass = nil
139
+ @type = type
140
+ end
141
+ end
142
+
143
+ def proxied
99
144
  super if defined? super
100
145
  extend Field::TypedField::Proxied
101
146
  end
@@ -1,7 +1,7 @@
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 Field
6
6
  #
7
7
  # A field has multiple purposes, which is defined by the specific subclass
@@ -20,11 +20,9 @@ module Rails # :nodoc:
20
20
  # (defaults to true).
21
21
  # * <tt>:full</tt> - Shortcut for +null: false, nullable: false, array: true+
22
22
  # (defaults to false).
23
- # * <tt>:method_name</tt> - The name of the method used to fetch the field data
24
- # (defaults to nil).
25
23
  # * <tt>:enabled</tt> - Mark the field as enabled
26
24
  # (defaults to true).
27
- # * <tt>:disabled</tt> - Works as the oposite of the enabled option
25
+ # * <tt>:disabled</tt> - Works as the opposite of the enabled option
28
26
  # (defaults to false).
29
27
  # * <tt>:directives</tt> - The list of directives associated with the value
30
28
  # (defaults to nil).
@@ -35,6 +33,7 @@ module Rails # :nodoc:
35
33
  class Field
36
34
  extend ActiveSupport::Autoload
37
35
  include Helpers::WithDirectives
36
+ include Helpers::WithDescription
38
37
 
39
38
  autoload :ScopedConfig
40
39
 
@@ -46,19 +45,25 @@ module Rails # :nodoc:
46
45
  autoload :InputField
47
46
  autoload :OutputField
48
47
  autoload :MutationField
48
+ autoload :SubscriptionField
49
49
 
50
50
  attr_reader :name, :gql_name, :owner
51
51
 
52
- delegate :input_type?, :output_type?, :leaf_type?, :proxy?, :mutation?, to: :class
52
+ alias gid_base_class owner
53
+ alias proxied_owner owner
54
+ alias to_sym name
55
+
53
56
  delegate :namespaces, to: :owner
57
+ delegate :input_type?, :output_type?, :leaf_type?, :proxy?,
58
+ :mutation?, :subscription?, to: :class
54
59
 
55
60
  class << self
56
61
  # A small shared helper method that allows field information to be
57
62
  # proxied
58
63
  def proxyable_methods(*list, klass:, allow_nil: false)
59
64
  list = list.flatten.compact.map do |method_name|
60
- ivar = '@' + method_name.delete_suffix('?')
61
- accessor = 'field' + (allow_nil ? '&.' : '.') + method_name
65
+ ivar = +'@' + method_name.delete_suffix('?')
66
+ accessor = +'field' + (allow_nil ? '&.' : '.') + method_name
62
67
  "def #{method_name}; defined?(#{ivar}) ? #{ivar} : #{accessor}; end"
63
68
  end
64
69
 
@@ -89,13 +94,21 @@ module Rails # :nodoc:
89
94
  def mutation?
90
95
  false
91
96
  end
97
+
98
+ # Checks if the field is associated with a subscription
99
+ def subscription?
100
+ false
101
+ end
92
102
  end
93
103
 
94
104
  def initialize(name, owner:, **xargs, &block)
95
105
  @owner = owner
96
106
  normalize_name(name)
97
107
 
98
- @directives = GraphQL.directives_to_set(xargs[:directives], source: self)
108
+ # TODO: Replace by a proper method to build and set @directives
109
+ directives = GraphQL.directives_to_set(xargs[:directives], source: self)
110
+ @directives = directives unless directives.nil?
111
+
99
112
  @method_name = xargs[:method_name].to_s.underscore.to_sym \
100
113
  unless xargs[:method_name].nil?
101
114
 
@@ -104,13 +117,13 @@ module Rails # :nodoc:
104
117
  @array = full ? true : xargs.fetch(:array, false)
105
118
  @nullable = full ? false : xargs.fetch(:nullable, true)
106
119
 
107
- @desc = xargs[:desc]&.strip_heredoc&.chomp
120
+ self.description = xargs[:desc] || xargs[:description]
108
121
  @enabled = xargs.fetch(:enabled, !xargs.fetch(:disabled, false))
109
122
 
110
123
  configure(&block) if block.present?
111
124
  end
112
125
 
113
- def initialize_copy(*) # :nodoc:
126
+ def initialize_copy(*)
114
127
  super
115
128
 
116
129
  @owner = nil
@@ -123,44 +136,69 @@ module Rails # :nodoc:
123
136
  disable! if xargs.fetch(:disabled, false)
124
137
  enable! if xargs.fetch(:enabled, false)
125
138
 
126
- @desc = xargs[:desc].strip_heredoc.chomp if xargs.key?(:desc)
139
+ self.description = xargs[:desc] if xargs.key?(:desc)
140
+ self.description = xargs[:description] if xargs.key?(:description)
127
141
  configure(&block) if block.present?
128
142
  end
129
143
 
130
144
  # Allow extra configurations to be performed using a block
131
145
  def configure(&block)
132
146
  Field::ScopedConfig.new(self, block.binding.receiver).instance_exec(&block)
147
+ self
148
+ end
149
+
150
+ # Return the owner as the single item of the list
151
+ def all_owners
152
+ [owner]
133
153
  end
134
154
 
135
155
  # Returns the name of the method used to retrieve the information
136
156
  def method_name
137
- defined?(@method_name) ? @method_name : @name
157
+ if defined?(@method_name)
158
+ @method_name
159
+ elsif from_alternative?
160
+ :resolve
161
+ else
162
+ @name
163
+ end
138
164
  end
139
165
 
140
- # Check if the other field is equivalent
141
- def =~(other)
142
- other.is_a?(GraphQL::Field) &&
143
- other.array? == array? &&
144
- (other.null? == null? || other.null? && !null?) &&
145
- (other.nullable? == nullable? || other.nullable? && !nullable?)
166
+ # Mark the field as globally enabled
167
+ def enable!
168
+ @enabled = true
146
169
  end
147
170
 
148
- # Return the owner as the single item of the list
149
- def all_owners
150
- [owner]
171
+ # Mark the field as globally disabled
172
+ def disable!
173
+ @enabled = false
151
174
  end
152
175
 
153
- # Checks if the argument can be null
176
+ # Update the null value
177
+ def required!
178
+ @null = false
179
+ end
180
+
181
+ # Update the nullable value
182
+ def required_items!
183
+ @nullable = false
184
+ end
185
+
186
+ # Checks if the field can be null
154
187
  def null?
155
188
  !!@null
156
189
  end
157
190
 
158
- # Checks if the argument can be an array
191
+ # Checks if the field cannot br null
192
+ def required?
193
+ !null?
194
+ end
195
+
196
+ # Checks if the field can be an array
159
197
  def array?
160
198
  !!@array
161
199
  end
162
200
 
163
- # Checks if the argument can have null elements in the array
201
+ # Checks if the field can have null elements in the array
164
202
  def nullable?
165
203
  !!@nullable
166
204
  end
@@ -175,24 +213,9 @@ module Rails # :nodoc:
175
213
  !enabled?
176
214
  end
177
215
 
178
- # Mark the field as globally enabled
179
- def enable!
180
- @enabled = true
181
- end
182
-
183
- # Mark the field as globally disabled
184
- def disable!
185
- @enabled = false
186
- end
187
-
188
- # Return the description of the argument
189
- def description
190
- @desc
191
- end
192
-
193
- # Checks if a description was provided
194
- def description?
195
- defined?(@desc) && !!@desc
216
+ # Override to add the kind
217
+ def description(namespace = nil, *)
218
+ super(namespace, :field)
196
219
  end
197
220
 
198
221
  # Check if the field is an internal one
@@ -211,24 +234,18 @@ module Rails # :nodoc:
211
234
  end
212
235
 
213
236
  # Transforms the given value to its representation in a JSON string
214
- def to_json(value)
215
- return 'null' if value.nil?
216
- return type_klass.to_json(value) unless array?
217
- value.map { |part| type_klass.to_json(part) }
237
+ def to_json(*)
238
+ raise NotImplementedError, +"#{self.class.name} does not implement to_json"
218
239
  end
219
240
 
220
241
  # Turn the given value into a JSON string representation
221
- def as_json(value)
222
- return if value.nil?
223
- return type_klass.as_json(value) unless array?
224
- value.map { |part| type_klass.as_json(part) }
242
+ def as_json(*)
243
+ raise NotImplementedError, +"#{self.class.name} does not implement as_json"
225
244
  end
226
245
 
227
246
  # Turn a user input of this given type into an ruby object
228
- def deserialize(value)
229
- return if value.nil?
230
- return type_klass.deserialize(value) unless array?
231
- value.map { |val| type_klass.deserialize(val) unless val.nil? }
247
+ def deserialize(*)
248
+ raise NotImplementedError, +"#{self.class.name} does not implement deserialize"
232
249
  end
233
250
 
234
251
  # Check if the given value is valid using +valid_input?+ or
@@ -241,22 +258,12 @@ module Rails # :nodoc:
241
258
  def validate!(*)
242
259
  super if defined? super
243
260
 
244
- raise NameError, <<~MSG.squish if gql_name.start_with?('__') && !internal?
261
+ raise NameError, (+<<~MSG).squish if gql_name.start_with?('__') && !internal?
245
262
  The name "#{gql_name}" is invalid. Only internal fields from the
246
263
  spec can have a name starting with "__".
247
264
  MSG
248
265
  end
249
266
 
250
- # Update the null value
251
- def required!
252
- @null = false
253
- end
254
-
255
- # Update the nullable value
256
- def required_items!
257
- @nullable = false
258
- end
259
-
260
267
  # Create a proxy of the current field
261
268
  def to_proxy(*args, **xargs, &block)
262
269
  proxy = self.class.allocate
@@ -266,16 +273,24 @@ module Rails # :nodoc:
266
273
  proxy
267
274
  end
268
275
 
269
- def inspect # :nodoc:
270
- <<~INSPECT.squish + '>'
271
- #<#{self.class.name}
272
- #{inspect_owner}
276
+ # Check if the other field is equivalent
277
+ def =~(other)
278
+ other.is_a?(GraphQL::Field) &&
279
+ other.array? == array? &&
280
+ (other.null? == null? || other.null? && !null?) &&
281
+ (other.nullable? == nullable? || other.nullable? && !nullable?)
282
+ end
283
+
284
+ def inspect
285
+ (+<<~INFO).squish << '>'
286
+ #<GraphQL::#{self.class.name.split('::').last}
287
+ #{inspect_owner&.split(+'GraphQL::')&.last&.sub(+'::NestedTypes', '')}
273
288
  #{inspect_source}
274
289
  #{inspect_enabled}
275
290
  #{gql_name}#{inspect_arguments}#{inspect_type}
276
291
  #{inspect_default_value}
277
292
  #{inspect_directives}
278
- INSPECT
293
+ INFO
279
294
  end
280
295
 
281
296
  protected
@@ -304,9 +319,9 @@ module Rails # :nodoc:
304
319
  end
305
320
  end
306
321
 
307
- # Helper method to inspect the directives
308
- def inspect_directives
309
- all_directives.map(&:inspect)
322
+ # Check if the field was defined as an alternative class
323
+ def from_alternative?
324
+ proxied_owner.is_a?(Module) && proxied_owner <= Alternative::Query
310
325
  end
311
326
 
312
327
  # Show the name of the owner of the object for inspection
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'globalid'
4
+
5
+ module Rails
6
+ module GraphQL
7
+ # = GraphQL Global ID
8
+ #
9
+ # GraphQL implementation of the Global ID that adds extended support to how
10
+ # things are located and stored. Mostly used for caching and custom access
11
+ # to the tree and request process.
12
+ #
13
+ # TODO: Implement signed operations
14
+ class GlobalID < ::GlobalID
15
+ SERIALIZER_KEY = "_gql_globalid"
16
+
17
+ # This adds support to ActiveJob serialization, which can be used to pass
18
+ # GraphQL objects to jobs and also deserialize things for subscriptions
19
+ class Serializer
20
+ include Singleton
21
+
22
+ class << self
23
+ delegate :serialize?, :serialize, :deserialize, to: :instance
24
+ end
25
+
26
+ # Determines if an argument should be serialized by this serializer.
27
+ def serialize?(argument)
28
+ argument.is_a?(Helpers::WithGlobalID) || argument.class.is_a?(Helpers::WithGlobalID)
29
+ end
30
+
31
+ # Serializes an argument to a JSON primitive type.
32
+ def serialize(argument)
33
+ { GlobalID::SERIALIZER_KEY => argument.to_global_id.to_s }
34
+ end
35
+
36
+ # Deserializes an argument from a JSON primitive type.
37
+ def deserialize(argument)
38
+ GlobalID.find argument[GlobalID::SERIALIZER_KEY]
39
+ end
40
+
41
+ private
42
+ # The class of the object that will be serialized.
43
+ def klass
44
+ GlobalID
45
+ end
46
+ end
47
+
48
+ class << self
49
+ undef_method :app, :app=
50
+
51
+ # Create a new GraphQL Global identifier
52
+ def create(object, options = nil)
53
+ scope = options&.delete(:scope) || scope_of(object)
54
+ new(URI::GQL.create(object, scope, options), options)
55
+ end
56
+
57
+ # Find the scope on which the object is applied to
58
+ def scope_of(object)
59
+ object.try(:schema_type) if object.gid_base_class.is_a?(Helpers::WithSchemaFields)
60
+ end
61
+ end
62
+
63
+ undef_method :app, :model_name, :model_id
64
+ delegate :namespace, :class_name, :scope, :name, :instantiate?, to: :uri
65
+
66
+ def initialize(gid, options = {})
67
+ @uri = gid.is_a?(URI::GQL) ? gid : URI::GQL.parse(gid)
68
+ end
69
+
70
+ def find(options = {})
71
+ base_class.try(:find_by_gid, self)
72
+ end
73
+
74
+ def base_class
75
+ if %w[Schema Directive Type].include?(class_name)
76
+ GraphQL.const_get(class_name, false)
77
+ else
78
+ GraphQL.type_map.fetch(class_name, namespace: namespace)
79
+ end
80
+ end
81
+
82
+ def ==(other)
83
+ other.is_a?(GlobalID) && @uri == other.uri
84
+ end
85
+
86
+ alias eql? ==
87
+ end
88
+ end
89
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
5
- module Helpers # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
+ module Helpers
6
6
  # This is an extra magic on top of the delegator class from the standard
7
7
  # lib that allows fetching a specific property of the delegated object
8
8
  class AttributeDelegator < ActiveSupport::ProxyObject
@@ -14,11 +14,11 @@ module Rails # :nodoc:
14
14
 
15
15
  private
16
16
 
17
- def respond_to_missing?(method_name, include_private = false) # :nodoc:
17
+ def respond_to_missing?(method_name, include_private = false)
18
18
  __getobj__.respond_to?(method_name, include_private) || super
19
19
  end
20
20
 
21
- def method_missing(method_name, *args, **xargs, &block) # :nodoc:
21
+ def method_missing(method_name, *args, **xargs, &block)
22
22
  return super unless __getobj__.respond_to?(method_name)
23
23
  __getobj__.public_send(method_name, *args, **xargs, &block)
24
24
  end
@@ -0,0 +1,51 @@
1
+ module Rails
2
+ module GraphQL
3
+ module Helpers
4
+ # A inherited collection of arrays that can be unique when it is a set
5
+ class InheritedCollection::Array < InheritedCollection::Base
6
+ alias size count
7
+ alias to_ary eager
8
+
9
+ # Provide similar functionality of any? but returns the object instead
10
+ def find(value = nil, &block)
11
+ block ||= !value.is_a?(Module) ? value.method(:==) : ->(val) { val.class <= value }
12
+ reverse_each { |item| return item if block.call(item) }
13
+ nil
14
+ end
15
+
16
+ # Check if a given +value+ is included in any of the definitions
17
+ def include?(value)
18
+ each_definition.any? { |definition| definition.include?(value) }
19
+ end
20
+
21
+ # If any elements appears, the each block will run and return true
22
+ def empty?
23
+ lazy.each { return true }
24
+ false
25
+ end
26
+
27
+ # The normal each is the reverse each of the definitions
28
+ def each(&block)
29
+ lazy.reverse_each(&block)
30
+ end
31
+
32
+ # The reverse each is the normal each of the definitions
33
+ def reverse_each(&block)
34
+ block.nil? ? lazy : lazy.each(&block)
35
+ end
36
+
37
+ # Overrides the lazy operator
38
+ def lazy
39
+ (@type == :set) ? super.uniq : super
40
+ end
41
+
42
+ # Allow concatenating objects
43
+ def +(other)
44
+ result = to_a
45
+ result = result.to_set if @type == :set
46
+ result + other
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,45 @@
1
+ module Rails
2
+ module GraphQL
3
+ module Helpers
4
+ # The base class for inherited collections. It helps softly dealing with
5
+ # values defined in multiple class instance variables and look up the tree
6
+ # to make it possible to iterate over combined result
7
+ class InheritedCollection::Base
8
+ include Enumerable
9
+
10
+ delegate :eager, to: :each
11
+
12
+ # Just a little helper to initialize the iterator form a given +source+
13
+ def self.handle(source, ivar, type)
14
+ klass = (type == :array || type == :set) ? :Array : :Hash
15
+ InheritedCollection.const_get(klass).new(source, ivar, type)
16
+ end
17
+
18
+ def initialize(source, ivar, type)
19
+ @source = source
20
+ @ivar = ivar
21
+ @type = type
22
+ end
23
+
24
+ # Overrides the lazy enumerator because each instance variable defined
25
+ # and found by the +each_definition+ will be iterated over lazily
26
+ def lazy
27
+ Enumerator::Lazy.new(each_definition) { |y, d| d.each(&y) }
28
+ end
29
+
30
+ protected
31
+
32
+ def each_definition
33
+ Enumerator.new do |yielder|
34
+ current = @source
35
+ until current === Object
36
+ yielder << current.instance_variable_get(@ivar) \
37
+ if current.instance_variable_defined?(@ivar)
38
+ current = current.superclass
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end