rails-graphql 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (266) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +19 -0
  4. data/Rakefile +31 -0
  5. data/ext/depend +3 -0
  6. data/ext/extconf.rb +57 -0
  7. data/ext/graphqlparser/Ast.cpp +346 -0
  8. data/ext/graphqlparser/Ast.h +1214 -0
  9. data/ext/graphqlparser/AstNode.h +36 -0
  10. data/ext/graphqlparser/AstVisitor.h +137 -0
  11. data/ext/graphqlparser/GraphQLParser.cpp +76 -0
  12. data/ext/graphqlparser/GraphQLParser.h +55 -0
  13. data/ext/graphqlparser/JsonVisitor.cpp +161 -0
  14. data/ext/graphqlparser/JsonVisitor.cpp.inc +456 -0
  15. data/ext/graphqlparser/JsonVisitor.h +121 -0
  16. data/ext/graphqlparser/JsonVisitor.h.inc +110 -0
  17. data/ext/graphqlparser/VERSION +1 -0
  18. data/ext/graphqlparser/c/GraphQLAst.cpp +324 -0
  19. data/ext/graphqlparser/c/GraphQLAst.h +180 -0
  20. data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +44 -0
  21. data/ext/graphqlparser/c/GraphQLAstNode.cpp +25 -0
  22. data/ext/graphqlparser/c/GraphQLAstNode.h +33 -0
  23. data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +21 -0
  24. data/ext/graphqlparser/c/GraphQLAstToJSON.h +24 -0
  25. data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +55 -0
  26. data/ext/graphqlparser/c/GraphQLAstVisitor.h +53 -0
  27. data/ext/graphqlparser/c/GraphQLParser.cpp +35 -0
  28. data/ext/graphqlparser/c/GraphQLParser.h +54 -0
  29. data/ext/graphqlparser/dump_json_ast.cpp +48 -0
  30. data/ext/graphqlparser/lexer.lpp +324 -0
  31. data/ext/graphqlparser/parser.ypp +693 -0
  32. data/ext/graphqlparser/parsergen/lexer.cpp +2633 -0
  33. data/ext/graphqlparser/parsergen/lexer.h +528 -0
  34. data/ext/graphqlparser/parsergen/location.hh +189 -0
  35. data/ext/graphqlparser/parsergen/parser.tab.cpp +3300 -0
  36. data/ext/graphqlparser/parsergen/parser.tab.hpp +646 -0
  37. data/ext/graphqlparser/parsergen/position.hh +179 -0
  38. data/ext/graphqlparser/parsergen/stack.hh +156 -0
  39. data/ext/graphqlparser/syntaxdefs.h +19 -0
  40. data/ext/libgraphqlparser/AstNode.h +36 -0
  41. data/ext/libgraphqlparser/CMakeLists.txt +148 -0
  42. data/ext/libgraphqlparser/CONTRIBUTING.md +23 -0
  43. data/ext/libgraphqlparser/GraphQLParser.cpp +76 -0
  44. data/ext/libgraphqlparser/GraphQLParser.h +55 -0
  45. data/ext/libgraphqlparser/JsonVisitor.cpp +161 -0
  46. data/ext/libgraphqlparser/JsonVisitor.h +121 -0
  47. data/ext/libgraphqlparser/LICENSE +22 -0
  48. data/ext/libgraphqlparser/README.clang-tidy +7 -0
  49. data/ext/libgraphqlparser/README.md +84 -0
  50. data/ext/libgraphqlparser/ast/ast.ast +203 -0
  51. data/ext/libgraphqlparser/ast/ast.py +61 -0
  52. data/ext/libgraphqlparser/ast/c.py +100 -0
  53. data/ext/libgraphqlparser/ast/c.pyc +0 -0
  54. data/ext/libgraphqlparser/ast/c_impl.py +61 -0
  55. data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
  56. data/ext/libgraphqlparser/ast/c_visitor_impl.py +39 -0
  57. data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
  58. data/ext/libgraphqlparser/ast/casing.py +26 -0
  59. data/ext/libgraphqlparser/ast/casing.pyc +0 -0
  60. data/ext/libgraphqlparser/ast/cxx.py +197 -0
  61. data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
  62. data/ext/libgraphqlparser/ast/cxx_impl.py +61 -0
  63. data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
  64. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +42 -0
  65. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
  66. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +80 -0
  67. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
  68. data/ext/libgraphqlparser/ast/cxx_visitor.py +64 -0
  69. data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
  70. data/ext/libgraphqlparser/ast/js.py +65 -0
  71. data/ext/libgraphqlparser/ast/license.py +10 -0
  72. data/ext/libgraphqlparser/ast/license.pyc +0 -0
  73. data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +25 -0
  74. data/ext/libgraphqlparser/c/GraphQLAstNode.h +33 -0
  75. data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +21 -0
  76. data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +24 -0
  77. data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +55 -0
  78. data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +53 -0
  79. data/ext/libgraphqlparser/c/GraphQLParser.cpp +35 -0
  80. data/ext/libgraphqlparser/c/GraphQLParser.h +54 -0
  81. data/ext/libgraphqlparser/clang-tidy-all.sh +3 -0
  82. data/ext/libgraphqlparser/cmake/version.cmake +16 -0
  83. data/ext/libgraphqlparser/dump_json_ast.cpp +48 -0
  84. data/ext/libgraphqlparser/go/README.md +20 -0
  85. data/ext/libgraphqlparser/go/callbacks.go +18 -0
  86. data/ext/libgraphqlparser/go/gotest.go +64 -0
  87. data/ext/libgraphqlparser/lexer.lpp +324 -0
  88. data/ext/libgraphqlparser/libgraphqlparser.pc.in +11 -0
  89. data/ext/libgraphqlparser/parser.ypp +693 -0
  90. data/ext/libgraphqlparser/parsergen/lexer.cpp +2633 -0
  91. data/ext/libgraphqlparser/parsergen/lexer.h +528 -0
  92. data/ext/libgraphqlparser/parsergen/location.hh +189 -0
  93. data/ext/libgraphqlparser/parsergen/parser.tab.cpp +3300 -0
  94. data/ext/libgraphqlparser/parsergen/parser.tab.hpp +646 -0
  95. data/ext/libgraphqlparser/parsergen/position.hh +179 -0
  96. data/ext/libgraphqlparser/parsergen/stack.hh +156 -0
  97. data/ext/libgraphqlparser/python/CMakeLists.txt +14 -0
  98. data/ext/libgraphqlparser/python/README.md +5 -0
  99. data/ext/libgraphqlparser/python/example.py +31 -0
  100. data/ext/libgraphqlparser/syntaxdefs.h +19 -0
  101. data/ext/libgraphqlparser/test/BuildCAPI.c +5 -0
  102. data/ext/libgraphqlparser/test/CMakeLists.txt +25 -0
  103. data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +28 -0
  104. data/ext/libgraphqlparser/test/ParserTests.cpp +352 -0
  105. data/ext/libgraphqlparser/test/kitchen-sink.graphql +59 -0
  106. data/ext/libgraphqlparser/test/kitchen-sink.json +1 -0
  107. data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +78 -0
  108. data/ext/libgraphqlparser/test/schema-kitchen-sink.json +1 -0
  109. data/ext/libgraphqlparser/test/valgrind.supp +33 -0
  110. data/ext/version.cpp +21 -0
  111. data/lib/generators/graphql/controller_generator.rb +22 -0
  112. data/lib/generators/graphql/schema_generator.rb +22 -0
  113. data/lib/generators/graphql/templates/controller.erb +5 -0
  114. data/lib/generators/graphql/templates/schema.erb +6 -0
  115. data/lib/graphqlparser.so +0 -0
  116. data/lib/rails-graphql.rb +2 -0
  117. data/lib/rails/graphql.rake +1 -0
  118. data/lib/rails/graphql.rb +185 -0
  119. data/lib/rails/graphql/adapters/mysql_adapter.rb +0 -0
  120. data/lib/rails/graphql/adapters/pg_adapter.rb +50 -0
  121. data/lib/rails/graphql/adapters/sqlite_adapter.rb +39 -0
  122. data/lib/rails/graphql/argument.rb +220 -0
  123. data/lib/rails/graphql/callback.rb +124 -0
  124. data/lib/rails/graphql/collectors.rb +14 -0
  125. data/lib/rails/graphql/collectors/hash_collector.rb +83 -0
  126. data/lib/rails/graphql/collectors/idented_collector.rb +73 -0
  127. data/lib/rails/graphql/collectors/json_collector.rb +114 -0
  128. data/lib/rails/graphql/config.rb +61 -0
  129. data/lib/rails/graphql/directive.rb +203 -0
  130. data/lib/rails/graphql/directive/deprecated_directive.rb +59 -0
  131. data/lib/rails/graphql/directive/include_directive.rb +24 -0
  132. data/lib/rails/graphql/directive/skip_directive.rb +24 -0
  133. data/lib/rails/graphql/errors.rb +42 -0
  134. data/lib/rails/graphql/event.rb +141 -0
  135. data/lib/rails/graphql/field.rb +318 -0
  136. data/lib/rails/graphql/field/input_field.rb +92 -0
  137. data/lib/rails/graphql/field/mutation_field.rb +52 -0
  138. data/lib/rails/graphql/field/output_field.rb +96 -0
  139. data/lib/rails/graphql/field/proxied_field.rb +131 -0
  140. data/lib/rails/graphql/field/resolved_field.rb +96 -0
  141. data/lib/rails/graphql/field/scoped_config.rb +22 -0
  142. data/lib/rails/graphql/field/typed_field.rb +104 -0
  143. data/lib/rails/graphql/helpers.rb +40 -0
  144. data/lib/rails/graphql/helpers/attribute_delegator.rb +39 -0
  145. data/lib/rails/graphql/helpers/inherited_collection.rb +152 -0
  146. data/lib/rails/graphql/helpers/leaf_from_ar.rb +141 -0
  147. data/lib/rails/graphql/helpers/registerable.rb +103 -0
  148. data/lib/rails/graphql/helpers/with_arguments.rb +125 -0
  149. data/lib/rails/graphql/helpers/with_assignment.rb +113 -0
  150. data/lib/rails/graphql/helpers/with_callbacks.rb +55 -0
  151. data/lib/rails/graphql/helpers/with_directives.rb +126 -0
  152. data/lib/rails/graphql/helpers/with_events.rb +81 -0
  153. data/lib/rails/graphql/helpers/with_fields.rb +141 -0
  154. data/lib/rails/graphql/helpers/with_namespace.rb +40 -0
  155. data/lib/rails/graphql/helpers/with_owner.rb +35 -0
  156. data/lib/rails/graphql/helpers/with_schema_fields.rb +230 -0
  157. data/lib/rails/graphql/helpers/with_validator.rb +52 -0
  158. data/lib/rails/graphql/introspection.rb +53 -0
  159. data/lib/rails/graphql/native.rb +56 -0
  160. data/lib/rails/graphql/native/functions.rb +38 -0
  161. data/lib/rails/graphql/native/location.rb +41 -0
  162. data/lib/rails/graphql/native/pointers.rb +23 -0
  163. data/lib/rails/graphql/native/visitor.rb +349 -0
  164. data/lib/rails/graphql/railtie.rb +85 -0
  165. data/lib/rails/graphql/railties/base_generator.rb +35 -0
  166. data/lib/rails/graphql/railties/controller.rb +101 -0
  167. data/lib/rails/graphql/railties/controller_runtime.rb +40 -0
  168. data/lib/rails/graphql/railties/log_subscriber.rb +62 -0
  169. data/lib/rails/graphql/request.rb +343 -0
  170. data/lib/rails/graphql/request/arguments.rb +93 -0
  171. data/lib/rails/graphql/request/component.rb +100 -0
  172. data/lib/rails/graphql/request/component/field.rb +225 -0
  173. data/lib/rails/graphql/request/component/fragment.rb +118 -0
  174. data/lib/rails/graphql/request/component/operation.rb +178 -0
  175. data/lib/rails/graphql/request/component/operation/subscription.rb +16 -0
  176. data/lib/rails/graphql/request/component/spread.rb +119 -0
  177. data/lib/rails/graphql/request/component/typename.rb +82 -0
  178. data/lib/rails/graphql/request/context.rb +51 -0
  179. data/lib/rails/graphql/request/errors.rb +54 -0
  180. data/lib/rails/graphql/request/event.rb +112 -0
  181. data/lib/rails/graphql/request/helpers/directives.rb +64 -0
  182. data/lib/rails/graphql/request/helpers/selection_set.rb +87 -0
  183. data/lib/rails/graphql/request/helpers/value_writers.rb +115 -0
  184. data/lib/rails/graphql/request/steps/organizable.rb +146 -0
  185. data/lib/rails/graphql/request/steps/prepareable.rb +33 -0
  186. data/lib/rails/graphql/request/steps/resolveable.rb +32 -0
  187. data/lib/rails/graphql/request/strategy.rb +249 -0
  188. data/lib/rails/graphql/request/strategy/dynamic_instance.rb +41 -0
  189. data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +36 -0
  190. data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +28 -0
  191. data/lib/rails/graphql/schema.rb +272 -0
  192. data/lib/rails/graphql/shortcuts.rb +77 -0
  193. data/lib/rails/graphql/source.rb +371 -0
  194. data/lib/rails/graphql/source/active_record/builders.rb +154 -0
  195. data/lib/rails/graphql/source/active_record_source.rb +231 -0
  196. data/lib/rails/graphql/source/scoped_arguments.rb +87 -0
  197. data/lib/rails/graphql/to_gql.rb +368 -0
  198. data/lib/rails/graphql/type.rb +138 -0
  199. data/lib/rails/graphql/type/enum.rb +206 -0
  200. data/lib/rails/graphql/type/enum/directive_location_enum.rb +30 -0
  201. data/lib/rails/graphql/type/enum/type_kind_enum.rb +57 -0
  202. data/lib/rails/graphql/type/input.rb +134 -0
  203. data/lib/rails/graphql/type/interface.rb +82 -0
  204. data/lib/rails/graphql/type/object.rb +111 -0
  205. data/lib/rails/graphql/type/object/directive_object.rb +34 -0
  206. data/lib/rails/graphql/type/object/enum_value_object.rb +25 -0
  207. data/lib/rails/graphql/type/object/field_object.rb +54 -0
  208. data/lib/rails/graphql/type/object/input_value_object.rb +49 -0
  209. data/lib/rails/graphql/type/object/schema_object.rb +40 -0
  210. data/lib/rails/graphql/type/object/type_object.rb +136 -0
  211. data/lib/rails/graphql/type/scalar.rb +71 -0
  212. data/lib/rails/graphql/type/scalar/bigint_scalar.rb +34 -0
  213. data/lib/rails/graphql/type/scalar/binary_scalar.rb +30 -0
  214. data/lib/rails/graphql/type/scalar/boolean_scalar.rb +37 -0
  215. data/lib/rails/graphql/type/scalar/date_scalar.rb +34 -0
  216. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +32 -0
  217. data/lib/rails/graphql/type/scalar/decimal_scalar.rb +35 -0
  218. data/lib/rails/graphql/type/scalar/float_scalar.rb +32 -0
  219. data/lib/rails/graphql/type/scalar/id_scalar.rb +39 -0
  220. data/lib/rails/graphql/type/scalar/int_scalar.rb +36 -0
  221. data/lib/rails/graphql/type/scalar/string_scalar.rb +28 -0
  222. data/lib/rails/graphql/type/scalar/time_scalar.rb +40 -0
  223. data/lib/rails/graphql/type/union.rb +87 -0
  224. data/lib/rails/graphql/type_map.rb +347 -0
  225. data/lib/rails/graphql/version.rb +7 -0
  226. data/test/assets/introspection-db.json +0 -0
  227. data/test/assets/introspection-mem.txt +1 -0
  228. data/test/assets/introspection.gql +91 -0
  229. data/test/assets/luke.jpg +0 -0
  230. data/test/assets/mem.gql +428 -0
  231. data/test/assets/sqlite.gql +423 -0
  232. data/test/config.rb +80 -0
  233. data/test/graphql/request/context_test.rb +70 -0
  234. data/test/graphql/schema_test.rb +190 -0
  235. data/test/graphql/source_test.rb +237 -0
  236. data/test/graphql/type/enum_test.rb +203 -0
  237. data/test/graphql/type/input_test.rb +138 -0
  238. data/test/graphql/type/interface_test.rb +72 -0
  239. data/test/graphql/type/object_test.rb +104 -0
  240. data/test/graphql/type/scalar/bigint_scalar_test.rb +42 -0
  241. data/test/graphql/type/scalar/binary_scalar_test.rb +17 -0
  242. data/test/graphql/type/scalar/boolean_scalar_test.rb +40 -0
  243. data/test/graphql/type/scalar/date_scalar_test.rb +29 -0
  244. data/test/graphql/type/scalar/date_time_scalar_test.rb +29 -0
  245. data/test/graphql/type/scalar/decimal_scalar_test.rb +28 -0
  246. data/test/graphql/type/scalar/float_scalar_test.rb +22 -0
  247. data/test/graphql/type/scalar/id_scalar_test.rb +26 -0
  248. data/test/graphql/type/scalar/int_scalar_test.rb +26 -0
  249. data/test/graphql/type/scalar/string_scalar_test.rb +17 -0
  250. data/test/graphql/type/scalar/time_scalar_test.rb +36 -0
  251. data/test/graphql/type/scalar_test.rb +45 -0
  252. data/test/graphql/type/union_test.rb +82 -0
  253. data/test/graphql/type_map_test.rb +362 -0
  254. data/test/graphql/type_test.rb +68 -0
  255. data/test/graphql_test.rb +55 -0
  256. data/test/integration/config.rb +56 -0
  257. data/test/integration/memory/star_wars_introspection_test.rb +144 -0
  258. data/test/integration/memory/star_wars_query_test.rb +184 -0
  259. data/test/integration/memory/star_wars_validation_test.rb +99 -0
  260. data/test/integration/schemas/memory.rb +232 -0
  261. data/test/integration/schemas/sqlite.rb +82 -0
  262. data/test/integration/sqlite/star_wars_introspection_test.rb +15 -0
  263. data/test/integration/sqlite/star_wars_mutation_test.rb +82 -0
  264. data/test/integration/sqlite/star_wars_query_test.rb +71 -0
  265. data/test/test_ext.rb +48 -0
  266. metadata +509 -0
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ # = GraphQL Directive
6
+ #
7
+ # This is the base object for directives definition.
8
+ # See: http://spec.graphql.org/June2018/#DirectiveDefinition
9
+ #
10
+ # Whenever you want to use a directive, you can use the ClassName(...)
11
+ # shortcut (which is the same as ClassName.new(...)).
12
+ #
13
+ # Directives works as event listener and trigger, which means that some
14
+ # actions will trigger directives events, and the directive can listen to
15
+ # these events and perform an action
16
+ #
17
+ # ==== Examples
18
+ #
19
+ # argument :test, :boolean, directives: FlagDirective()
20
+ #
21
+ # # On defining an enum value
22
+ # add :old_value, directives: DeprecatedDirective(reason: 'not used anymore')
23
+ class Directive
24
+ extend ActiveSupport::Autoload
25
+ extend Helpers::InheritedCollection
26
+ extend Helpers::WithEvents
27
+ extend Helpers::WithCallbacks
28
+ extend Helpers::WithArguments
29
+ extend Helpers::Registerable
30
+
31
+ VALID_LOCATIONS = Rails::GraphQL::Type::Enum::DirectiveLocationEnum
32
+ .values.to_a.map { |value| value.downcase.to_sym }.freeze
33
+
34
+ EXECUTION_LOCATIONS = VALID_LOCATIONS[0..6].freeze
35
+ DEFINITION_LOCATIONS = VALID_LOCATIONS[7..17].freeze
36
+
37
+ class << self
38
+ def kind # :nodoc
39
+ :directive
40
+ end
41
+
42
+ def gql_name # :nodoc:
43
+ return @gql_name if defined?(@gql_name)
44
+ @gql_name = super.camelize(:lower)
45
+ end
46
+
47
+ # Get the list of locations of a the directive
48
+ def locations
49
+ @locations ||= Set.new
50
+ end
51
+
52
+ # A secure way to specify the locations of a the directive
53
+ def placed_on(*list)
54
+ validate_locations!(list)
55
+ @locations = (superclass.try(:locations)&.dup || Set.new) \
56
+ unless defined?(@locations)
57
+
58
+ @locations.merge(list)
59
+ end
60
+
61
+ # This method overrides the locations of a the directive
62
+ def placed_on!(*list)
63
+ validate_locations!(list)
64
+ @locations = list.to_set
65
+ end
66
+
67
+ def eager_load! # :nodoc:
68
+ super
69
+
70
+ TypeMap.loaded! :Directive
71
+ end
72
+
73
+ def inspect # :nodoc:
74
+ return '#<GraphQL::Directive>' if eql?(GraphQL::Directive)
75
+
76
+ args = arguments.each_value.map(&:inspect)
77
+ args = args.presence && "(#{args.join(', ')})"
78
+ "#<GraphQL::Directive @#{gql_name}#{args}>"
79
+ end
80
+
81
+ private
82
+
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
+ # Provide a nice way to use a directive without calling
95
+ # +Directive.new+, like the +DeprecatedDirective+ can be initialized
96
+ # using +GraphQL::DeprecatedDirective(*args)+
97
+ def inherited(subclass)
98
+ subclass.abstract = false
99
+ super if defined? super
100
+
101
+ return if subclass.anonymous?
102
+ method_name = subclass.name.demodulize
103
+ subclass.module_parent.define_singleton_method(method_name) do |*args, &block|
104
+ subclass.new(*args, &block)
105
+ end
106
+ end
107
+
108
+ # Allows checking value existence
109
+ def respond_to_missing?(method_name, *)
110
+ (const_defined?(method_name) rescue nil) || autoload?(method_name) || super
111
+ end
112
+
113
+ # Allow fast creation of values
114
+ def method_missing(method_name, *args, **xargs, &block)
115
+ const_get(method_name)&.new(*args, **xargs, &block) || super
116
+ rescue ::NameError
117
+ super
118
+ end
119
+ end
120
+
121
+ self.abstract = true
122
+
123
+ eager_autoload do
124
+ autoload :DeprecatedDirective
125
+ autoload :IncludeDirective
126
+ autoload :SkipDirective
127
+ end
128
+
129
+ delegate :locations, :gql_name, to: :class
130
+
131
+ array_sanitizer = ->(setting) do
132
+ Array.wrap(setting)
133
+ end
134
+
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
142
+
143
+ event_filter(:for, object_sanitizer) do |options, event|
144
+ options.any?(&event.source.method(:of_type?))
145
+ end
146
+
147
+ event_filter(:on, object_sanitizer) do |options, event|
148
+ event.respond_to?(:on?) && options.any?(&event.method(:on?))
149
+ end
150
+
151
+ event_filter(:during, array_sanitizer) do |options, event|
152
+ event.key?(:phase) && options.include?(event[:phase])
153
+ end
154
+
155
+ attr_reader :args
156
+
157
+ def initialize(args = nil, **xargs)
158
+ @args = args || OpenStruct.new(xargs.transform_keys { |key| key.to_s.underscore })
159
+ @args.freeze
160
+ end
161
+
162
+ # 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)
165
+ Owner already assigned for @#{gql_name} directive.
166
+ MSG
167
+
168
+ @owner = owner
169
+ end
170
+
171
+ # When fetching all the events, embed the actual instance as the context
172
+ # of the callback
173
+ def all_events
174
+ @all_events ||= self.class.all_events.transform_values do |events|
175
+ events.map { |item| Callback.set_context(item, self) }
176
+ end
177
+ end
178
+
179
+ # Checks if all the arguments provided to the directive instance are valid
180
+ def validate!(*)
181
+ invalid = all_arguments.reject { |name, arg| arg.valid?(@args[name]) }
182
+ return if invalid.empty?
183
+
184
+ invalid = invalid.map { |name, _| <<~MSG }
185
+ Invalid value "#{@args[name].inspect}" for #{name} argument.
186
+ MSG
187
+
188
+ raise ArgumentError, <<~MSG.squish
189
+ Invalid usage of @#{gql_name} directive: #{invalid.to_sentence}.
190
+ MSG
191
+ end
192
+
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
197
+
198
+ args = args.presence && "(#{args.join(', ')})"
199
+ "@#{gql_name}#{args}"
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ # = GraphQL Spec Deprecated Directive
6
+ #
7
+ # Mark fields or enum values as deprecated which will include an error
8
+ # message when they are requested or returned
9
+ class Directive::DeprecatedDirective < Directive
10
+ self.spec_object = true
11
+
12
+ placed_on :field_definition, :enum_value
13
+
14
+ desc <<~DESC
15
+ Indicate deprecated portions of a GraphQL service’s schema, such as deprecated
16
+ fields on a type or deprecated enum values.
17
+ DESC
18
+
19
+ argument :reason, :string, desc: <<~DESC
20
+ Explain why the underlying element was marked as deprecated. If possible,
21
+ indicate what element should be used instead. This description is formatted
22
+ using Markdown syntax (as specified by [CommonMark](http://commonmark.org/)).
23
+ DESC
24
+
25
+ on :organized do |event|
26
+ report_for_field(event)
27
+ end
28
+
29
+ on :finalize, for: Type::Enum do |event|
30
+ report_for_enum_value(event)
31
+ end
32
+
33
+ private
34
+
35
+ # Check if the requested field is marked as deprecated
36
+ def report_for_field(event)
37
+ return unless event.field.using?(self.class)
38
+ item = "#{event.source.gql_name} field"
39
+ event.request.report_error(build_message(item))
40
+ end
41
+
42
+ # Check if the resolved enum value is marked as deprecated
43
+ def report_for_enum_value(event)
44
+ return unless event.current_value.deprecated?
45
+
46
+ value = event.current_value.to_s
47
+ item = "#{value} value for the #{event.source.gql_name} field"
48
+ event.request.report_error(build_message(item))
49
+ end
50
+
51
+ # Build the error message to display on the result
52
+ def build_message(item)
53
+ result = "The #{item} is deprecated"
54
+ result += ", reason: #{args.reason}" if args.reason.present?
55
+ result + '.'
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ # = GraphQL Spec Include Directive
6
+ #
7
+ # Allow including fields only +if+ condition is true
8
+ class Directive::IncludeDirective < Directive
9
+ self.spec_object = true
10
+
11
+ placed_on :field, :fragment_spread, :inline_fragment
12
+
13
+ desc 'Allows for conditional inclusion during execution as described by the if argument.'
14
+
15
+ argument :if, :boolean, null: false, desc: <<~DESC
16
+ When false, the underlying element will be automatically marked as null.
17
+ DESC
18
+
19
+ on :attach do |source|
20
+ source.invalidate! unless args[:if]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ # = GraphQL Spec Skip Directive
6
+ #
7
+ # Allow skipping fields given an +if+ condition
8
+ class Directive::SkipDirective < Directive
9
+ self.spec_object = true
10
+
11
+ desc 'Allows for conditional exclusion during execution as described by the if argument.'
12
+
13
+ placed_on :field, :fragment_spread, :inline_fragment
14
+
15
+ argument :if, :boolean, null: false, desc: <<~DESC
16
+ When true, the underlying element will be automatically marked as null.
17
+ DESC
18
+
19
+ on :attach do |source|
20
+ source.invalidate! if args[:if]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ # Error class tha wrappes all the other error classes
6
+ StandardError = Class.new(::StandardError)
7
+
8
+ # Error class related to problems during the definition process
9
+ DefinitionError = Class.new(StandardError)
10
+
11
+ # Error class related to validation of a value
12
+ ValidationError = Class.new(StandardError)
13
+
14
+ # Errors that can happen related to the arguments given to a method
15
+ ArgumentError = Class.new(DefinitionError)
16
+
17
+ # Errors related to the name of the objects
18
+ NameError = Class.new(DefinitionError)
19
+
20
+ # Errors related to duplciated objects
21
+ DuplicatedError = Class.new(NameError)
22
+
23
+ # Error class related to problems during the execution process
24
+ ExecutionError = Class.new(StandardError)
25
+
26
+ # Error related to the parsing process
27
+ ParseError = Class.new(ExecutionError)
28
+
29
+ # Error class related to problems that happened during execution of fields
30
+ FieldError = Class.new(ExecutionError)
31
+
32
+ # Error class related to when a field was not found on the requested object
33
+ MissingFieldError = Class.new(FieldError)
34
+
35
+ # Error class related to when a field was found but is marked as disabled
36
+ DisabledFieldError = Class.new(FieldError)
37
+
38
+ # Error class related to when the captured output value is invalid due to
39
+ # type checking
40
+ InvalidValueError = Class.new(FieldError)
41
+ end
42
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ # = GraphQL Event
6
+ #
7
+ # This class is responsible for trigerring events. It also contains the
8
+ # +data+ that can be used on the event handlers.
9
+ class Event
10
+ attr_reader :source, :data, :name, :object, :last_result
11
+
12
+ alias event itself
13
+
14
+ # List of trigger types used on +trigger+ shortcut
15
+ TRIGGER_TYPES = {
16
+ all?: :trigger_all,
17
+ stack?: :trigger_all,
18
+ object?: :trigger_object,
19
+ single?: :trigger,
20
+ }.freeze
21
+
22
+ # Event trigger shortcut that can perform any mode of trigger
23
+ def self.trigger(event_name, object, source, **xargs, &block)
24
+ extra = xargs.slice!(*TRIGGER_TYPES.keys)
25
+ fallback = extra.delete(:fallback_trigger!) || :trigger
26
+ method_name = xargs.find { |k, v| break TRIGGER_TYPES[k] if v } || fallback
27
+
28
+ instance = new(event_name, source, **extra)
29
+ instance.instance_variable_set(:@object, object) if block.present?
30
+ instance.public_send(method_name, block || object)
31
+ end
32
+
33
+ def initialize(name, source, **data)
34
+ @collect = data.delete(:collect?)
35
+ @reverse = data.delete(:reverse?)
36
+
37
+ @name = name
38
+ @data = data
39
+ @source = source
40
+ @layers = []
41
+ end
42
+
43
+ # Return a given +name+ information from the event
44
+ def parameter(name)
45
+ respond_to?(name) ? public_send(name) : data[name]
46
+ end
47
+
48
+ alias [] parameter
49
+
50
+ # Check if the event has a given +name+ information
51
+ def parameter?(name)
52
+ respond_to?(name) || data.key?(name)
53
+ end
54
+
55
+ alias key? parameter?
56
+
57
+ # Temporarily attach the event into an instance ensuring to set the
58
+ # previous value back
59
+ def set_on(instance, &block)
60
+ send_args = block.arity.eql?(1) ? [instance] : []
61
+ old_event = instance.instance_variable_get(:@event) \
62
+ if instance.instance_variable_defined?(:@event)
63
+
64
+ return block.call(*send_args) if old_event === self
65
+
66
+ begin
67
+ instance.instance_variable_set(:@event, self)
68
+ block.call(*send_args)
69
+ ensure
70
+ instance.instance_variable_set(:@event, old_event)
71
+ end
72
+ end
73
+
74
+ # From the list of all given objects, run the +trigger_object+
75
+ def trigger_all(*objects)
76
+ catchable(:stack) do
77
+ iterator = @collect ? :map : :each
78
+ objects.flatten.send(iterator, &method(:trigger_object))
79
+ end
80
+ end
81
+
82
+ # Fetch all the events from the object, get only the ones that are from
83
+ # the same name as the instance of this class and call +trigger+. It runs
84
+ # in reverse order, so first in first out. Since events can sometimes be
85
+ # cached, using +events+ avoid calculating the +all_events+
86
+ def trigger_object(object, events = nil)
87
+ @items ||= nil
88
+ @object ||= nil
89
+ @last_result ||= nil
90
+
91
+ old_items, old_object, old_result, @object = @items, @object, @last_result, object
92
+
93
+ catchable(:object) do
94
+ events ||= object.all_events[name]
95
+ stop if events.blank?
96
+
97
+ @items = @reverse ? events.reverse_each : events.each
98
+ call_next while @items.peek
99
+ rescue StopIteration
100
+ # TODO: Make sure that the +@collect+ works
101
+ return @last_result
102
+ end
103
+ ensure
104
+ @items = old_items
105
+ @object = old_object
106
+ @last_result = old_result
107
+ end
108
+
109
+ # Call a given block and send the event as reference
110
+ def trigger(block)
111
+ catchable(:item) { @last_result = block.call(self) }
112
+ end
113
+
114
+ # Stop the execution of an event using a given +layer+. The default is to
115
+ # get the last activated layer and stop it
116
+ def stop(*result, layer: nil)
117
+ layer = @layers[layer] if layer.is_a?(Numeric)
118
+ throw(layer || @layers.first, *result)
119
+ end
120
+
121
+ # Call the next item on the queue and return its result
122
+ def call_next
123
+ trigger(@items.next)
124
+ rescue StopIteration
125
+ # Do not do anything when missing next/super
126
+ end
127
+
128
+ alias call_super call_next
129
+
130
+ private
131
+
132
+ # Add the layer, exec the block and remove the layer
133
+ def catchable(layer)
134
+ @layers.unshift(layer)
135
+ catch(layer) { yield }
136
+ ensure
137
+ @layers.pop
138
+ end
139
+ end
140
+ end
141
+ end