rails-graphql 0.2.1 → 1.0.0.beta

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 (297) 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 +646 -0
  6. data/ext/shared.c +482 -0
  7. data/ext/shared.h +177 -0
  8. data/lib/gql_parser.so +0 -0
  9. data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
  10. data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
  11. data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
  12. data/lib/rails/graphql/alternative/field_set.rb +36 -0
  13. data/lib/rails/graphql/alternative/mutation.rb +17 -0
  14. data/lib/rails/graphql/alternative/query.rb +93 -0
  15. data/lib/rails/graphql/alternative/subscription.rb +17 -0
  16. data/lib/rails/graphql/alternative.rb +20 -0
  17. data/lib/rails/graphql/argument.rb +21 -24
  18. data/lib/rails/graphql/callback.rb +24 -9
  19. data/lib/rails/graphql/collectors/hash_collector.rb +14 -6
  20. data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
  21. data/lib/rails/graphql/collectors/json_collector.rb +22 -17
  22. data/lib/rails/graphql/collectors.rb +4 -4
  23. data/lib/rails/graphql/config.rb +130 -15
  24. data/lib/rails/graphql/directive/cached_directive.rb +33 -0
  25. data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
  26. data/lib/rails/graphql/directive/include_directive.rb +5 -4
  27. data/lib/rails/graphql/directive/skip_directive.rb +5 -4
  28. data/lib/rails/graphql/directive.rb +118 -63
  29. data/lib/rails/graphql/errors.rb +33 -4
  30. data/lib/rails/graphql/event.rb +16 -5
  31. data/lib/rails/graphql/field/authorized_field.rb +19 -3
  32. data/lib/rails/graphql/field/input_field.rb +11 -10
  33. data/lib/rails/graphql/field/mutation_field.rb +42 -7
  34. data/lib/rails/graphql/field/output_field.rb +102 -13
  35. data/lib/rails/graphql/field/proxied_field.rb +31 -22
  36. data/lib/rails/graphql/field/resolved_field.rb +26 -24
  37. data/lib/rails/graphql/field/scoped_config.rb +10 -4
  38. data/lib/rails/graphql/field/subscription_field.rb +140 -0
  39. data/lib/rails/graphql/field/typed_field.rb +43 -22
  40. data/lib/rails/graphql/field.rb +70 -56
  41. data/lib/rails/graphql/global_id.rb +85 -0
  42. data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
  43. data/lib/rails/graphql/helpers/inherited_collection/array.rb +50 -0
  44. data/lib/rails/graphql/helpers/inherited_collection/base.rb +43 -0
  45. data/lib/rails/graphql/helpers/inherited_collection/hash.rb +87 -0
  46. data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
  47. data/lib/rails/graphql/helpers/instantiable.rb +15 -0
  48. data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
  49. data/lib/rails/graphql/helpers/registerable.rb +44 -62
  50. data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
  51. data/lib/rails/graphql/helpers/with_arguments.rb +31 -27
  52. data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
  53. data/lib/rails/graphql/helpers/with_callbacks.rb +25 -8
  54. data/lib/rails/graphql/helpers/with_description.rb +71 -0
  55. data/lib/rails/graphql/helpers/with_directives.rb +54 -30
  56. data/lib/rails/graphql/helpers/with_events.rb +21 -23
  57. data/lib/rails/graphql/helpers/with_fields.rb +76 -22
  58. data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
  59. data/lib/rails/graphql/helpers/with_name.rb +43 -0
  60. data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
  61. data/lib/rails/graphql/helpers/with_owner.rb +8 -7
  62. data/lib/rails/graphql/helpers/with_schema_fields.rb +137 -55
  63. data/lib/rails/graphql/helpers/with_validator.rb +9 -9
  64. data/lib/rails/graphql/helpers.rb +10 -3
  65. data/lib/rails/graphql/introspection.rb +43 -36
  66. data/lib/rails/graphql/railtie.rb +88 -33
  67. data/lib/rails/graphql/railties/base_generator.rb +3 -9
  68. data/lib/rails/graphql/railties/channel.rb +157 -0
  69. data/lib/rails/graphql/railties/controller.rb +62 -17
  70. data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
  71. data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
  72. data/lib/rails/graphql/request/arguments.rb +24 -49
  73. data/lib/rails/graphql/request/backtrace.rb +191 -0
  74. data/lib/rails/graphql/request/component/field.rb +86 -65
  75. data/lib/rails/graphql/request/component/fragment.rb +72 -24
  76. data/lib/rails/graphql/request/component/operation/subscription.rb +164 -4
  77. data/lib/rails/graphql/request/component/operation.rb +63 -31
  78. data/lib/rails/graphql/request/component/spread.rb +68 -25
  79. data/lib/rails/graphql/request/component/typename.rb +27 -12
  80. data/lib/rails/graphql/request/component.rb +75 -36
  81. data/lib/rails/graphql/request/context.rb +18 -8
  82. data/lib/rails/graphql/request/errors.rb +16 -6
  83. data/lib/rails/graphql/request/event.rb +19 -8
  84. data/lib/rails/graphql/request/helpers/directives.rb +68 -27
  85. data/lib/rails/graphql/request/helpers/selection_set.rb +51 -25
  86. data/lib/rails/graphql/request/helpers/value_writers.rb +18 -16
  87. data/lib/rails/graphql/request/prepared_data.rb +98 -0
  88. data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
  89. data/lib/rails/graphql/request/steps/organizable.rb +110 -48
  90. data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +20 -7
  91. data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +15 -6
  92. data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
  93. data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
  94. data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
  95. data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
  96. data/lib/rails/graphql/request/strategy.rb +131 -75
  97. data/lib/rails/graphql/request/subscription.rb +80 -0
  98. data/lib/rails/graphql/request.rb +305 -86
  99. data/lib/rails/graphql/schema.rb +240 -48
  100. data/lib/rails/graphql/shortcuts.rb +22 -3
  101. data/lib/rails/graphql/source/active_record/builders.rb +49 -35
  102. data/lib/rails/graphql/source/active_record_source.rb +70 -54
  103. data/lib/rails/graphql/source/base.rb +111 -0
  104. data/lib/rails/graphql/source/builder.rb +128 -0
  105. data/lib/rails/graphql/source/scoped_arguments.rb +31 -19
  106. data/lib/rails/graphql/source.rb +89 -213
  107. data/lib/rails/graphql/subscription/provider/action_cable.rb +112 -0
  108. data/lib/rails/graphql/subscription/provider/base.rb +191 -0
  109. data/lib/rails/graphql/subscription/provider.rb +18 -0
  110. data/lib/rails/graphql/subscription/store/base.rb +145 -0
  111. data/lib/rails/graphql/subscription/store/memory.rb +127 -0
  112. data/lib/rails/graphql/subscription/store.rb +19 -0
  113. data/lib/rails/graphql/subscription.rb +17 -0
  114. data/lib/rails/graphql/to_gql.rb +29 -32
  115. data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
  116. data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
  117. data/lib/rails/graphql/type/enum.rb +34 -48
  118. data/lib/rails/graphql/type/input.rb +74 -23
  119. data/lib/rails/graphql/type/interface.rb +16 -26
  120. data/lib/rails/graphql/type/object/directive_object.rb +4 -4
  121. data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
  122. data/lib/rails/graphql/type/object/field_object.rb +24 -6
  123. data/lib/rails/graphql/type/object/input_value_object.rb +3 -3
  124. data/lib/rails/graphql/type/object/schema_object.rb +5 -8
  125. data/lib/rails/graphql/type/object/type_object.rb +29 -19
  126. data/lib/rails/graphql/type/object.rb +26 -23
  127. data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
  128. data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
  129. data/lib/rails/graphql/type/scalar/binary_scalar.rb +3 -3
  130. data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
  131. data/lib/rails/graphql/type/scalar/date_scalar.rb +3 -3
  132. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +3 -3
  133. data/lib/rails/graphql/type/scalar/decimal_scalar.rb +3 -3
  134. data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
  135. data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
  136. data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
  137. data/lib/rails/graphql/type/scalar/json_scalar.rb +39 -0
  138. data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
  139. data/lib/rails/graphql/type/scalar/time_scalar.rb +5 -5
  140. data/lib/rails/graphql/type/scalar.rb +25 -22
  141. data/lib/rails/graphql/type/union.rb +14 -16
  142. data/lib/rails/graphql/type.rb +34 -25
  143. data/lib/rails/graphql/type_map.rb +256 -164
  144. data/lib/rails/graphql/uri.rb +166 -0
  145. data/lib/rails/graphql/version.rb +15 -3
  146. data/lib/rails/graphql.rake +3 -0
  147. data/lib/rails/graphql.rb +85 -52
  148. data/lib/rails-graphql.rb +1 -1
  149. data/test/assets/en.yml +29 -0
  150. data/test/assets/introspection-mem.txt +1 -1
  151. data/test/assets/mem.gql +18 -45
  152. data/test/assets/mysql.gql +392 -0
  153. data/test/assets/sqlite.gql +21 -12
  154. data/test/assets/translate.gql +335 -0
  155. data/test/config.rb +18 -8
  156. data/test/graphql/schema_test.rb +12 -19
  157. data/test/graphql/source_test.rb +8 -75
  158. data/test/graphql/type/enum_test.rb +207 -203
  159. data/test/graphql/type/input_test.rb +14 -9
  160. data/test/graphql/type/interface_test.rb +4 -4
  161. data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
  162. data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
  163. data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
  164. data/test/graphql/type_map_test.rb +51 -66
  165. data/test/graphql/type_test.rb +0 -19
  166. data/test/graphql_test.rb +1 -1
  167. data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
  168. data/test/integration/config.rb +36 -3
  169. data/test/integration/customization_test.rb +39 -0
  170. data/test/integration/global_id_test.rb +99 -0
  171. data/test/integration/memory/star_wars_introspection_test.rb +24 -16
  172. data/test/integration/memory/star_wars_query_test.rb +54 -3
  173. data/test/integration/memory/star_wars_validation_test.rb +1 -1
  174. data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
  175. data/test/integration/persisted_query_test.rb +87 -0
  176. data/test/integration/resolver_precedence_test.rb +154 -0
  177. data/test/integration/schemas/memory.rb +22 -7
  178. data/test/integration/schemas/mysql.rb +62 -0
  179. data/test/integration/schemas/sqlite.rb +21 -12
  180. data/test/integration/sqlite/star_wars_global_id_test.rb +83 -0
  181. data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
  182. data/test/integration/sqlite/star_wars_query_test.rb +14 -1
  183. data/test/integration/translate_test.rb +61 -0
  184. data/test/test_ext.rb +16 -13
  185. metadata +108 -157
  186. data/ext/depend +0 -3
  187. data/ext/graphqlparser/Ast.cpp +0 -346
  188. data/ext/graphqlparser/Ast.h +0 -1214
  189. data/ext/graphqlparser/AstNode.h +0 -36
  190. data/ext/graphqlparser/AstVisitor.h +0 -137
  191. data/ext/graphqlparser/GraphQLParser.cpp +0 -76
  192. data/ext/graphqlparser/GraphQLParser.h +0 -55
  193. data/ext/graphqlparser/JsonVisitor.cpp +0 -161
  194. data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
  195. data/ext/graphqlparser/JsonVisitor.h +0 -121
  196. data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
  197. data/ext/graphqlparser/VERSION +0 -1
  198. data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
  199. data/ext/graphqlparser/c/GraphQLAst.h +0 -180
  200. data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
  201. data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
  202. data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
  203. data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  204. data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
  205. data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  206. data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
  207. data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
  208. data/ext/graphqlparser/c/GraphQLParser.h +0 -54
  209. data/ext/graphqlparser/dump_json_ast.cpp +0 -48
  210. data/ext/graphqlparser/lexer.lpp +0 -324
  211. data/ext/graphqlparser/parser.ypp +0 -693
  212. data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
  213. data/ext/graphqlparser/parsergen/lexer.h +0 -528
  214. data/ext/graphqlparser/parsergen/location.hh +0 -189
  215. data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
  216. data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
  217. data/ext/graphqlparser/parsergen/position.hh +0 -179
  218. data/ext/graphqlparser/parsergen/stack.hh +0 -156
  219. data/ext/graphqlparser/syntaxdefs.h +0 -19
  220. data/ext/libgraphqlparser/AstNode.h +0 -36
  221. data/ext/libgraphqlparser/CMakeLists.txt +0 -148
  222. data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
  223. data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
  224. data/ext/libgraphqlparser/GraphQLParser.h +0 -55
  225. data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
  226. data/ext/libgraphqlparser/JsonVisitor.h +0 -121
  227. data/ext/libgraphqlparser/LICENSE +0 -22
  228. data/ext/libgraphqlparser/README.clang-tidy +0 -7
  229. data/ext/libgraphqlparser/README.md +0 -84
  230. data/ext/libgraphqlparser/ast/ast.ast +0 -203
  231. data/ext/libgraphqlparser/ast/ast.py +0 -61
  232. data/ext/libgraphqlparser/ast/c.py +0 -100
  233. data/ext/libgraphqlparser/ast/c.pyc +0 -0
  234. data/ext/libgraphqlparser/ast/c_impl.py +0 -61
  235. data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
  236. data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
  237. data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
  238. data/ext/libgraphqlparser/ast/casing.py +0 -26
  239. data/ext/libgraphqlparser/ast/casing.pyc +0 -0
  240. data/ext/libgraphqlparser/ast/cxx.py +0 -197
  241. data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
  242. data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
  243. data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
  244. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
  245. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
  246. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
  247. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
  248. data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
  249. data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
  250. data/ext/libgraphqlparser/ast/js.py +0 -65
  251. data/ext/libgraphqlparser/ast/license.py +0 -10
  252. data/ext/libgraphqlparser/ast/license.pyc +0 -0
  253. data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
  254. data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
  255. data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  256. data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
  257. data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  258. data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
  259. data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
  260. data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
  261. data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
  262. data/ext/libgraphqlparser/cmake/version.cmake +0 -16
  263. data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
  264. data/ext/libgraphqlparser/go/README.md +0 -20
  265. data/ext/libgraphqlparser/go/callbacks.go +0 -18
  266. data/ext/libgraphqlparser/go/gotest.go +0 -64
  267. data/ext/libgraphqlparser/lexer.lpp +0 -324
  268. data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
  269. data/ext/libgraphqlparser/parser.ypp +0 -693
  270. data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
  271. data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
  272. data/ext/libgraphqlparser/parsergen/location.hh +0 -189
  273. data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
  274. data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
  275. data/ext/libgraphqlparser/parsergen/position.hh +0 -179
  276. data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
  277. data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
  278. data/ext/libgraphqlparser/python/README.md +0 -5
  279. data/ext/libgraphqlparser/python/example.py +0 -31
  280. data/ext/libgraphqlparser/syntaxdefs.h +0 -19
  281. data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
  282. data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
  283. data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
  284. data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
  285. data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
  286. data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
  287. data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
  288. data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
  289. data/ext/libgraphqlparser/test/valgrind.supp +0 -33
  290. data/ext/version.cpp +0 -21
  291. data/lib/graphqlparser.so +0 -0
  292. data/lib/rails/graphql/native/functions.rb +0 -38
  293. data/lib/rails/graphql/native/location.rb +0 -41
  294. data/lib/rails/graphql/native/pointers.rb +0 -23
  295. data/lib/rails/graphql/native/visitor.rb +0 -349
  296. data/lib/rails/graphql/native.rb +0 -56
  297. 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
  # = GraphQL Directive
6
6
  #
7
7
  # This is the base object for directives definition.
@@ -22,24 +22,31 @@ module Rails # :nodoc:
22
22
  # add :old_value, directives: DeprecatedDirective(reason: 'not used anymore')
23
23
  class Directive
24
24
  extend ActiveSupport::Autoload
25
- extend Helpers::InheritedCollection
26
25
  extend Helpers::WithEvents
27
26
  extend Helpers::WithCallbacks
28
27
  extend Helpers::WithArguments
28
+ extend Helpers::WithGlobalID
29
29
  extend Helpers::Registerable
30
30
 
31
- VALID_LOCATIONS = Rails::GraphQL::Type::Enum::DirectiveLocationEnum
32
- .values.to_a.map { |value| value.downcase.to_sym }.freeze
31
+ EXECUTION_LOCATIONS = %i[
32
+ query mutation subscription field fragment_definition fragment_spread inline_fragment
33
+ ].to_set.freeze
33
34
 
34
- EXECUTION_LOCATIONS = VALID_LOCATIONS[0..6].freeze
35
- DEFINITION_LOCATIONS = VALID_LOCATIONS[7..17].freeze
35
+ DEFINITION_LOCATIONS = %i[
36
+ schema scalar object field_definition argument_definition interface union
37
+ enum enum_value input_object input_field_definition
38
+ ].to_set.freeze
39
+
40
+ VALID_LOCATIONS = (EXECUTION_LOCATIONS + DEFINITION_LOCATIONS).freeze
36
41
 
37
42
  class << self
38
- def kind # :nodoc
43
+ def kind
39
44
  :directive
40
45
  end
41
46
 
42
- def gql_name # :nodoc:
47
+ # Return the name of the object as a GraphQL name, ensure to use the
48
+ # first letter as lower case when being auto generated
49
+ def gql_name
43
50
  return @gql_name if defined?(@gql_name)
44
51
  @gql_name = super.camelize(:lower)
45
52
  end
@@ -64,33 +71,40 @@ module Rails # :nodoc:
64
71
  @locations = list.to_set
65
72
  end
66
73
 
67
- def eager_load! # :nodoc:
68
- super
74
+ # Ensure to return the directive class
75
+ def gid_base_class
76
+ GraphQL::Directive
77
+ end
78
+
79
+ # A helper method that allows directives to be initialized while
80
+ # correctly parsing the arguments
81
+ def build(**xargs)
82
+ xargs = xargs.stringify_keys
83
+ result = all_arguments&.each&.each_with_object({}) do |(name, argument), hash|
84
+ hash[name] = argument.deserialize(xargs[argument.gql_name] || xargs[name.to_s])
85
+ end
86
+
87
+ new(**result)
88
+ end
69
89
 
70
- TypeMap.loaded! :Directive
90
+ # Return the directive, instantiate if it has params
91
+ def find_by_gid(gid)
92
+ options = { namespaces: gid.namespace, base_class: :Directive }
93
+ klass = GraphQL.type_map.fetch!(gid.name, **options)
94
+ gid.instantiate? ? klass.build(**gid.params) : klass
71
95
  end
72
96
 
73
- def inspect # :nodoc:
74
- return '#<GraphQL::Directive>' if eql?(GraphQL::Directive)
97
+ def inspect
98
+ return super if eql?(GraphQL::Directive)
75
99
 
76
- args = arguments.each_value.map(&:inspect)
100
+ args = all_arguments&.each_value&.map(&:inspect)
101
+ args = args.force if args.respond_to?(:force)
77
102
  args = args.presence && "(#{args.join(', ')})"
78
- "#<GraphQL::Directive @#{gql_name}#{args}>"
103
+ +"#<GraphQL::Directive @#{gql_name}#{args}>"
79
104
  end
80
105
 
81
106
  private
82
107
 
83
- # Check if the given list the locations are valid
84
- def validate_locations!(list)
85
- list.flatten!
86
- list.map! { |item| item.to_s.underscore.to_sym }
87
-
88
- invalid = list - VALID_LOCATIONS
89
- raise ArgumentError, <<~MSG.squish unless invalid.empty?
90
- Invalid locations for @#{gql_name}: #{invalid.to_sentence}.
91
- MSG
92
- end
93
-
94
108
  # Provide a nice way to use a directive without calling
95
109
  # +Directive.new+, like the +DeprecatedDirective+ can be initialized
96
110
  # using +GraphQL::DeprecatedDirective(*args)+
@@ -105,6 +119,29 @@ module Rails # :nodoc:
105
119
  end
106
120
  end
107
121
 
122
+ # A helper method that allows the +on+ and +for+ event filters to be
123
+ # used with things from both the TypeMap and the GraphQL shortcut
124
+ # classes
125
+ def sanitize_objects(setting)
126
+ GraphQL.enumerate(setting).map do |item|
127
+ next item unless item.is_a?(String) || item.is_a?(Symbol)
128
+ GraphQL.type_map.fetch(item, namespaces: namespaces) ||
129
+ ::GraphQL.const_get(item)
130
+ end
131
+ end
132
+
133
+ # Check if the given list the locations are valid
134
+ def validate_locations!(list)
135
+ invalid = list.flatten.lazy.reject do |item|
136
+ item = item.to_s.underscore.to_sym unless item.is_a?(Symbol)
137
+ VALID_LOCATIONS.include?(item)
138
+ end
139
+
140
+ raise ArgumentError, (+<<~MSG).squish if invalid.any?
141
+ Invalid locations for @#{gql_name}: #{invalid.force.to_sentence}.
142
+ MSG
143
+ end
144
+
108
145
  # Allows checking value existence
109
146
  def respond_to_missing?(method_name, *)
110
147
  (const_defined?(method_name) rescue nil) || autoload?(method_name) || super
@@ -120,36 +157,24 @@ module Rails # :nodoc:
120
157
 
121
158
  self.abstract = true
122
159
 
123
- eager_autoload do
124
- autoload :DeprecatedDirective
125
- autoload :IncludeDirective
126
- autoload :SkipDirective
127
- end
160
+ autoload :DeprecatedDirective
161
+ autoload :IncludeDirective
162
+ autoload :SkipDirective
128
163
 
129
- delegate :locations, :gql_name, to: :class
130
-
131
- array_sanitizer = ->(setting) do
132
- Array.wrap(setting)
133
- end
164
+ autoload :CachedDirective
134
165
 
135
- object_sanitizer = ->(setting) do
136
- Array.wrap(setting).map! do |item|
137
- next item unless item.is_a?(String) || item.is_a?(Symbol)
138
- GraphQL.type_map.fetch(item, namespaces: namespaces) ||
139
- ::GraphQL.const_get(item)
140
- end
141
- end
166
+ delegate :locations, :gql_name, :gid_base_class, to: :class
142
167
 
143
- event_filter(:for, object_sanitizer) do |options, event|
144
- options.any?(&event.source.method(:of_type?))
168
+ event_filter(:for) do |options, event|
169
+ sanitize_objects(options).any?(&event.source.method(:of_type?))
145
170
  end
146
171
 
147
- event_filter(:on, object_sanitizer) do |options, event|
148
- event.respond_to?(:on?) && options.any?(&event.method(:on?))
172
+ event_filter(:on) do |options, event|
173
+ event.respond_to?(:on?) && sanitize_objects(options).any?(&event.method(:on?))
149
174
  end
150
175
 
151
- event_filter(:during, array_sanitizer) do |options, event|
152
- event.key?(:phase) && options.include?(event[:phase])
176
+ event_filter(:during) do |options, event|
177
+ event.key?(:phase) && GraphQL.enumerate(options).include?(event[:phase])
153
178
  end
154
179
 
155
180
  attr_reader :args
@@ -160,17 +185,35 @@ module Rails # :nodoc:
160
185
  end
161
186
 
162
187
  # Once the directive is correctly prepared, we need to assign the owner
163
- def assing_owner!(owner)
164
- raise ArgumentError, <<~MSG.squish if defined?(@owner)
188
+ def assign_owner!(owner)
189
+ raise ArgumentError, (+<<~MSG).squish if defined?(@owner)
165
190
  Owner already assigned for @#{gql_name} directive.
166
191
  MSG
167
192
 
168
193
  @owner = owner
169
194
  end
170
195
 
196
+ # Correctly turn all the arguments into their +as_json+ version and return
197
+ # a hash of them
198
+ def args_as_json
199
+ all_arguments&.each&.with_object({}) do |(name, argument), hash|
200
+ hash[argument.gql_name] = argument.as_json(@args[name])
201
+ end
202
+ end
203
+
204
+ # Correctly turn all the arguments into their +to_json+ version and return
205
+ # a hash of them
206
+ def args_to_json
207
+ all_arguments&.each&.with_object({}) do |(name, argument), hash|
208
+ hash[argument.gql_name] = argument.to_json(@args[name])
209
+ end
210
+ end
211
+
171
212
  # When fetching all the events, embed the actual instance as the context
172
213
  # of the callback
173
214
  def all_events
215
+ return unless self.class.events?
216
+
174
217
  @all_events ||= self.class.all_events.transform_values do |events|
175
218
  events.map { |item| Callback.set_context(item, self) }
176
219
  end
@@ -178,26 +221,38 @@ module Rails # :nodoc:
178
221
 
179
222
  # Checks if all the arguments provided to the directive instance are valid
180
223
  def validate!(*)
181
- invalid = all_arguments.reject { |name, arg| arg.valid?(@args[name]) }
182
- return if invalid.empty?
224
+ raise ArgumentError, (+<<~MSG).squish unless defined?(@owner)
225
+ The @#{gql_name} directive is unbounded.
226
+ MSG
183
227
 
184
- invalid = invalid.map { |name, _| <<~MSG }
185
- Invalid value "#{@args[name].inspect}" for #{name} argument.
228
+ invalid = all_arguments&.reject { |name, arg| arg.valid?(@args[name]) }
229
+ return if invalid.blank?
230
+
231
+ invalid = invalid.each_key.map { |name| (+<<~MSG).squish }
232
+ invalid value "#{@args[name].inspect}" for #{name} argument
186
233
  MSG
187
234
 
188
- raise ArgumentError, <<~MSG.squish
235
+ raise ArgumentError, (+<<~MSG).squish
189
236
  Invalid usage of @#{gql_name} directive: #{invalid.to_sentence}.
190
237
  MSG
191
238
  end
192
239
 
193
- def inspect # :nodoc:
194
- args = all_arguments.map do |name, arg|
195
- "#{arg.gql_name}: #{@args[name].inspect}" unless @args[name].nil?
196
- end.compact
240
+ def inspect
241
+ args = all_arguments&.map do |name, arg|
242
+ +"#{arg.gql_name}: #{@args[name].inspect}" unless @args[name].nil?
243
+ end&.compact
197
244
 
198
- args = args.presence && "(#{args.join(', ')})"
199
- "@#{gql_name}#{args}"
245
+ args = args.presence && +"(#{args.join(', ')})"
246
+ unbound = ' # unbound' unless defined?(@owner)
247
+ +"@#{gql_name}#{args}#{unbound}"
200
248
  end
249
+
250
+ %i[to_global_id to_gid to_gid_param].each do |method_name|
251
+ define_method(method_name) do
252
+ self.class.public_send(method_name, args_as_json&.compact || '')
253
+ end
254
+ end
255
+
201
256
  end
202
257
  end
203
258
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
5
- # Error class tha wrappes all the other error classes
3
+ module Rails
4
+ module GraphQL
5
+ # Error class tha wraps all the other error classes
6
6
  StandardError = Class.new(::StandardError)
7
7
 
8
8
  # Error class related to problems during the definition process
@@ -14,10 +14,13 @@ module Rails # :nodoc:
14
14
  # Errors that can happen related to the arguments given to a method
15
15
  ArgumentError = Class.new(DefinitionError)
16
16
 
17
+ # Errors that can happen when locking for definition objects, like fields
18
+ NotFoundError = Class.new(DefinitionError)
19
+
17
20
  # Errors related to the name of the objects
18
21
  NameError = Class.new(DefinitionError)
19
22
 
20
- # Errors related to duplciated objects
23
+ # Errors related to duplicated objects
21
24
  DuplicatedError = Class.new(NameError)
22
25
 
23
26
  # Error class related to problems during the execution process
@@ -26,6 +29,9 @@ module Rails # :nodoc:
26
29
  # Error related to the parsing process
27
30
  ParseError = Class.new(ExecutionError)
28
31
 
32
+ # Error class related to parsing the arguments
33
+ ArgumentsError = Class.new(ParseError)
34
+
29
35
  # Error class related to problems that happened during execution of fields
30
36
  FieldError = Class.new(ExecutionError)
31
37
 
@@ -42,5 +48,28 @@ module Rails # :nodoc:
42
48
  # Error class related to when a field is unauthorized and can not be used,
43
49
  # similar to disabled fields
44
50
  UnauthorizedFieldError = Class.new(FieldError)
51
+
52
+ # Error class related to problems that happened while subscribing to a field
53
+ SubscriptionError = Class.new(FieldError)
54
+
55
+ # Error class related to execution responses that don't require processing
56
+ StaticResponse = Class.new(Interrupt)
57
+
58
+ # Error class related to cached responses, which doesn't need processing
59
+ CachedResponse = Class.new(StaticResponse)
60
+
61
+ # Error class related to a persisted query that has't been persisted yet
62
+ PersistedQueryNotFound = Class.new(StaticResponse)
63
+
64
+ # A simple module and way to extend errors with extra information
65
+ ExtendedError = Module.new do
66
+ delegate_missing_to :@extension
67
+
68
+ def self.extend(error, extension)
69
+ error.instance_variable_set(:@extension, extension)
70
+ error.extend(self)
71
+ error
72
+ end
73
+ end
45
74
  end
46
75
  end
@@ -1,10 +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
  # = GraphQL Event
6
6
  #
7
- # This class is responsible for trigerring events. It also contains the
7
+ # This class is responsible for triggering events. It also contains the
8
8
  # +data+ that can be used on the event handlers.
9
9
  class Event
10
10
  attr_reader :source, :data, :name, :object, :last_result
@@ -40,6 +40,16 @@ module Rails # :nodoc:
40
40
  @layers = []
41
41
  end
42
42
 
43
+ # Check if the provided +other+ is equal to the source of the event. If
44
+ # other is a directive, then check if the source is using that directive
45
+ def same_source?(other)
46
+ if other.is_a?(Directive) || (other.is_a?(Module) && other < Directive)
47
+ source.using?(other)
48
+ else
49
+ source == other
50
+ end
51
+ end
52
+
43
53
  # Return a given +name+ information from the event
44
54
  def parameter(name)
45
55
  respond_to?(name) ? public_send(name) : data[name]
@@ -75,6 +85,7 @@ module Rails # :nodoc:
75
85
  def trigger_all(*objects)
76
86
  catchable(:stack) do
77
87
  iterator = @collect ? :map : :each
88
+ objects = objects.first if objects.size == 1 && objects.first.is_a?(Enumerable)
78
89
  objects.flatten.send(iterator, &method(:trigger_object))
79
90
  end
80
91
  end
@@ -91,7 +102,7 @@ module Rails # :nodoc:
91
102
  old_items, old_object, old_result, @object = @items, @object, @last_result, object
92
103
 
93
104
  catchable(:object) do
94
- events ||= object.all_events[name]
105
+ events ||= object.all_events.try(:[], name)
95
106
  stop if events.blank?
96
107
 
97
108
  @items = @reverse ? events.reverse_each : events.each
@@ -138,7 +149,7 @@ module Rails # :nodoc:
138
149
  @layers.unshift(layer)
139
150
  catch(layer) { yield }
140
151
  ensure
141
- @layers.pop
152
+ @layers.shift
142
153
  end
143
154
 
144
155
  # Check for data based readers
@@ -1,11 +1,21 @@
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 provides ways for fields to be authorized, giving a logical level for
6
6
  # enabling or disabling access to a field. It has a similar structure to
7
7
  # events, but has a different hierarchy of resolution
8
8
  module Field::AuthorizedField
9
+ module Proxied # :nodoc: all
10
+ def authorizer
11
+ super || field.authorizer
12
+ end
13
+
14
+ def authorizable?
15
+ super || field.authorizable?
16
+ end
17
+ end
18
+
9
19
  # Just add the callbacks setup to the field
10
20
  def self.included(other)
11
21
  other.event_types(:authorize, append: true)
@@ -27,7 +37,13 @@ module Rails # :nodoc:
27
37
  def authorizable?
28
38
  defined?(@authorizer)
29
39
  end
40
+
41
+ protected
42
+
43
+ def proxied
44
+ super if defined? super
45
+ extend Field::AuthorizedField::Proxied
46
+ end
30
47
  end
31
48
  end
32
49
  end
33
- #
@@ -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 Input Field
6
6
  #
7
7
  # An input field works the same way as an argument and they are pretty much
@@ -13,8 +13,6 @@ module Rails # :nodoc:
13
13
  # ==== Options
14
14
  #
15
15
  # * <tt>:default</tt> - Sets a default value for the argument (defaults to nil).
16
- # * <tt>:directives</tt> - The list of directives associated with the value
17
- # (defaults to nil).
18
16
  class Field::InputField < Field
19
17
  include Field::TypedField
20
18
 
@@ -25,11 +23,14 @@ module Rails # :nodoc:
25
23
 
26
24
  def initialize(*args, default: nil, **xargs, &block)
27
25
  super(*args, **xargs, &block)
26
+
28
27
  @default = default
28
+ @default = deserialize(@default) if @default.is_a?(::GQLParser::Token)
29
29
  end
30
30
 
31
- def configure # :nodoc:
32
- raise ArgumentError, 'Input fields can\'t be further configured using blocks'
31
+ # Prevent input fields from being further configured using a block
32
+ def configure
33
+ raise ArgumentError, +'Input fields can\'t be further configured using blocks'
33
34
  end
34
35
 
35
36
  # Allow change the default value for the input
@@ -72,11 +73,11 @@ module Rails # :nodoc:
72
73
  def validate!(*)
73
74
  super if defined? super
74
75
 
75
- raise ArgumentError, <<~MSG.squish unless type_klass.input_type?
76
+ raise ArgumentError, (+<<~MSG).squish unless type_klass.input_type?
76
77
  The "#{type_klass.gql_name}" is not a valid input type.
77
78
  MSG
78
79
 
79
- raise ArgumentError, <<~MSG.squish unless default.nil? || valid_input?(default)
80
+ raise ArgumentError, (+<<~MSG).squish unless default.nil? || valid_input?(default)
80
81
  The given default value "#{default.inspect}" is not valid for this field.
81
82
  MSG
82
83
  end
@@ -85,7 +86,7 @@ module Rails # :nodoc:
85
86
 
86
87
  # Check if the given +value+ is a valid array as input
87
88
  def valid_input_array?(value, deep)
88
- return false unless value.is_a?(Array)
89
+ return false unless value.is_a?(::Array)
89
90
 
90
91
  value.all? do |val|
91
92
  (val.nil? && nullable?) || (leaf_type? || !deep) ||
@@ -95,7 +96,7 @@ module Rails # :nodoc:
95
96
 
96
97
  # Display the default value when it is present for inspection
97
98
  def inspect_default_value
98
- " = #{to_hash.inspect}" if default?
99
+ +" = #{as_json.inspect}" if default_value?
99
100
  end
100
101
  end
101
102
  end
@@ -1,11 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
5
- # = GraphQL Output Field
3
+ module Rails
4
+ module GraphQL
5
+ # = GraphQL Mutation Field
6
6
  #
7
7
  # This is an extension of a normal output field, which just add extra
8
8
  # validation and ensurance that the +perform+ step can be executed
9
+ #
10
+ # ==== Options
11
+ #
12
+ # * <tt>:call</tt> - The alternative method to call to actually perform the mutation.
13
+ # (defaults to nil).
9
14
  class Field::MutationField < Field::OutputField
10
15
  redefine_singleton_method(:mutation?) { true }
11
16
 
@@ -15,6 +20,34 @@ module Rails # :nodoc:
15
20
  end
16
21
  end
17
22
 
23
+ # Intercept the initializer to maybe set the +perform_method_name+
24
+ def initialize(*args, call: nil, **xargs, &block)
25
+ @perform_method_name = call.to_sym unless call.nil?
26
+ super(*args, **xargs, &block)
27
+ end
28
+
29
+ # Accept changes to the perform method name through the +apply_changes+
30
+ def apply_changes(**xargs, &block)
31
+ @perform_method_name = xargs.delete(:call) if xargs.key?(:call)
32
+ super
33
+ end
34
+
35
+ # Allows overrides for the default bang method
36
+ def perform_method_name
37
+ if defined?(@perform_method_name)
38
+ @perform_method_name
39
+ elsif from_alternative?
40
+ :perform
41
+ else
42
+ :"#{method_name}!"
43
+ end
44
+ end
45
+
46
+ # Change the schema type of the field
47
+ def schema_type
48
+ :mutation
49
+ end
50
+
18
51
  # Add a block or a callable method that is executed before the resolver
19
52
  # but after all the before resolve. It returns +self+ for chain purposes
20
53
  def perform(*args, **xargs, &block)
@@ -25,8 +58,8 @@ module Rails # :nodoc:
25
58
  # Get the performer that can be already defined or used through the
26
59
  # +method_name+ if that is callable
27
60
  def performer
28
- @performer ||= callable?(:"#{method_name}!") \
29
- ? Callback.new(self, :perform, :"#{method_name}!") \
61
+ @performer ||= callable?(perform_method_name) \
62
+ ? Callback.new(self, :perform, perform_method_name) \
30
63
  : false
31
64
  end
32
65
 
@@ -34,7 +67,9 @@ module Rails # :nodoc:
34
67
  def validate!(*)
35
68
  super if defined? super
36
69
 
37
- raise ValidationError, <<~MSG.squish unless performer.present?
70
+ binding.pry unless performer.present?
71
+
72
+ raise ValidationError, (+<<~MSG).squish unless performer.present?
38
73
  The "#{gql_name}" mutation field must have a perform action through a given
39
74
  block or a method named #{method_name} on #{owner.class.name}.
40
75
  MSG
@@ -42,7 +77,7 @@ module Rails # :nodoc:
42
77
 
43
78
  protected
44
79
 
45
- def proxied # :nodoc:
80
+ def proxied
46
81
  super if defined? super
47
82
  extend Field::MutationField::Proxied
48
83
  end