rails-graphql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ class Type # :nodoc:
6
+ # = GraphQL UnionType
7
+ #
8
+ # Unions represent an object that could be one of a list of GraphQL
9
+ # Object types.
10
+ # See http://spec.graphql.org/June2018/#UnionTypeDefinition
11
+ class Union < Type
12
+ setup! output: true
13
+
14
+ # The list of accepted classes for members
15
+ VALID_MEMBER_TYPES = [Type::Object].freeze
16
+
17
+ # Define the methods for accessing the members attribute
18
+ inherited_collection :members
19
+
20
+ # The purpose of instantiating an interface is to have access to its
21
+ # public methods. It then runs from the strategy perspective, pointing
22
+ # out any other methods to the manually set event
23
+ delegate_missing_to :event
24
+ attr_reader :event
25
+
26
+ class << self
27
+ # Return the base type of the objects on this union
28
+ def of_kind
29
+ members.first.base_type
30
+ end
31
+
32
+ # Check if the other type is equivalent by checking if the type is
33
+ # member of any of this union members
34
+ def =~(other)
35
+ super || all_members.any? { |item| other =~ item }
36
+ end
37
+
38
+ # Use this method to add members to the union
39
+ def append(*others)
40
+ return if others.blank?
41
+
42
+ others.flatten!
43
+ others.map! do |item|
44
+ next item unless item.is_a?(Symbol)
45
+ GraphQL.type_map.fetch(item, namespaces: namespaces)
46
+ end
47
+
48
+ checker = others.lazy.map { |item| item.try(:base_type) }.uniq.force
49
+ raise ArgumentError, <<~MSG.squish unless checker.size === 1
50
+ All the union members must be of the same base class.
51
+ MSG
52
+
53
+ check_types = members? ? [members.first.base_type] : VALID_MEMBER_TYPES
54
+ raise ArgumentError, <<~MSG.squish unless (check_types & checker).size === 1
55
+ A union cannot contain members of different base classes.
56
+ MSG
57
+
58
+ members.concat(others)
59
+ end
60
+
61
+ # Check if the union definition is valid
62
+ def validate!(*)
63
+ super if defined? super
64
+
65
+ members = all_members
66
+ raise ArgumentError, <<~MSG.squish unless members.size >= 1
67
+ A union must contain at least one member.
68
+ MSG
69
+
70
+ size = members.lazy.map(&:base_type).uniq.force.size
71
+ raise ArgumentError, <<~MSG.squish unless size.eql?(1)
72
+ All the members of the union must contain the same base class.
73
+ MSG
74
+ end
75
+
76
+ def inspect # :nodoc:
77
+ <<~INFO.squish + '>'
78
+ #<GraphQL::Union #{gql_name}
79
+ (#{all_members.size})
80
+ {#{all_members.map(&:gql_name).join(' | ')}}
81
+ INFO
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,347 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'concurrent/map'
4
+ require 'active_support/core_ext/class/subclasses'
5
+
6
+ module Rails # :nodoc:
7
+ module GraphQL # :nodoc:
8
+ # = GraphQL Type Map
9
+ #
10
+ # Inspired by ActiveRecord::Type::TypeMap, this class stores all the things
11
+ # defined, their unique name, their basic settings, and correctly index
12
+ # them so they are easy to find whenever necessary.
13
+ #
14
+ # Items are stored as procs because aliases should fetch whatever the base
15
+ # object is, even if they change in the another point.
16
+ #
17
+ # The cache stores in the following structure:
18
+ # Namespace -> BaseClass -> ItemKey -> Item
19
+ class TypeMap
20
+ FILTER_REGISTER_TRACE = /((inherited|initialize)'$|schema\.rb:\d+)/.freeze
21
+
22
+ # Store all the base classes and if they were eager loaded by the type map
23
+ # Be aware of the order because hard reset is based in this order
24
+ mattr_accessor :base_classes, instance_writer: false, default: {
25
+ Type: false,
26
+ Directive: false,
27
+ Schema: false,
28
+ }
29
+
30
+ def self.loaded!(base_class)
31
+ base_classes[base_class] = true
32
+ end
33
+
34
+ # Reset the state of the type mapper
35
+ def reset!
36
+ @objects = 0 # Number of types and directives defined
37
+
38
+ @pending = []
39
+ @callbacks = Hash.new { |h, k| h[k] = [] }
40
+ @skip_register = nil
41
+
42
+ @index = Concurrent::Map.new do |h1, key1| # Namespaces
43
+ base_class = Concurrent::Map.new do |h2, key2| # Base classes
44
+ ensure_base_class!(key2)
45
+ h2.fetch_or_store(key2, Concurrent::Map.new) # Items
46
+ end
47
+
48
+ h1.fetch_or_store(key1, base_class)
49
+ end
50
+
51
+ @checkpoint.map(&:register!) if defined?(@checkpoint)
52
+ end
53
+
54
+ alias initialize reset!
55
+
56
+ # This will do a full reset of the type map, re-registering all the
57
+ # descendant classes for all the base classes
58
+ def hard_reset!
59
+ remove_instance_variable(:@checkpoint) if defined?(@checkpoint)
60
+
61
+ reset!
62
+ base_classes.each_key do |base_class|
63
+ GraphQL.const_get(base_class).descendants.each(&:register!)
64
+ end
65
+ end
66
+
67
+ # Save or restore a checkpoint that can the type map can be reseted to
68
+ # TODO: With hard reset, we might not need checkpoint anymore
69
+ def use_checkpoint!
70
+ return reset! if defined?(@checkpoint)
71
+
72
+ register_pending!
73
+ @checkpoint = objects
74
+ end
75
+
76
+ # Get the list of all registred objects
77
+ def objects(base_classes: nil, namespaces: nil)
78
+ (Array.wrap(namespaces).presence || @index.keys).map do |namespace|
79
+ (Array.wrap(base_classes).presence || @index[namespace].keys).map do |base_class|
80
+ @index[namespace][base_class].values.map(&:call) \
81
+ if @index[namespace].key?(base_class)
82
+ end if @index.key?(namespace)
83
+ end.flatten.compact.uniq.select do |obj|
84
+ obj.respond_to?(:register!)
85
+ end
86
+ end
87
+
88
+ # Same as +fetch+ but it will raise an exception or retry depending if the
89
+ # base type was already loaded or not
90
+ def fetch!(*args, base_class: :Type, **xargs)
91
+ xargs[:base_class] = base_class
92
+
93
+ result = fetch(*args, **xargs)
94
+ return result unless result.nil?
95
+
96
+ raise ArgumentError, <<~MSG.squish if base_classes[base_class]
97
+ Unable to find #{args.first.inspect} #{base_class} object.
98
+ MSG
99
+
100
+ GraphQL.const_get(base_class).eager_load!
101
+ fetch!(*args, **xargs)
102
+ end
103
+
104
+ # Find the given key or name inside the base class either on the given
105
+ # namespace or in the base +:base+ namespace
106
+ def fetch(key_or_name, prevent_register: nil, **xargs)
107
+ if prevent_register != true
108
+ skip_register << Array.wrap(prevent_register)
109
+ register_pending!
110
+ end
111
+
112
+ namespaces = xargs[:namespaces]
113
+ namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
114
+ namespaces += [:base] unless xargs.fetch(:exclusive, false)
115
+
116
+ possibilities = Array.wrap(key_or_name)
117
+ possibilities += Array.wrap(xargs[:fallback]) if xargs.key?(:fallback)
118
+
119
+ namespaces.uniq.find do |namespace|
120
+ possibilities.find do |item|
121
+ result = dig(namespace, xargs.fetch(:base_class, :Type), item)
122
+ return result.call unless result.nil?
123
+ end
124
+ end
125
+ ensure
126
+ skip_register.pop
127
+ end
128
+
129
+ # Checks if a given key or name is already defined under the same base
130
+ # class and namespace. If +exclusive+ is set to +false+, then it won't
131
+ # check the +:base+ namespace when not found on the given namespace.
132
+ def exist?(name_or_key, base_class: :Type, namespaces: :base, exclusive: false)
133
+ namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
134
+ namespaces += [:base] unless exclusive
135
+ namespaces.uniq.any? { |namespace| dig(namespace, base_class, name_or_key).present? }
136
+ end
137
+
138
+ # Find if a given object is already defined. If +exclusive+ is set to
139
+ # +false+, then it won't check the +:base+ namespace
140
+ def object_exist?(object, **xargs)
141
+ xargs[:base_class] = find_base_class(object)
142
+ xargs[:namespaces] ||= object.namespaces
143
+ exist?(object, **xargs)
144
+ end
145
+
146
+ # Mark the given object to be registered later, when a fetch is triggered
147
+ # TODO: Improve this with a Backtracer Cleaner
148
+ def postpone_registration(object)
149
+ source = caller(3).find { |item| item !~ FILTER_REGISTER_TRACE }
150
+ @pending << [object, source]
151
+ end
152
+
153
+ # Register a given object, which must be a class where the namespaces and
154
+ # the base class can be inferred
155
+ def register(object)
156
+ namespaces = object.namespaces.dup
157
+ namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
158
+
159
+ base_namespace = namespaces.shift || :base
160
+ base_class = find_base_class(object)
161
+ ensure_base_class!(base_class)
162
+
163
+ # Cache the name, the key, and the alias proc
164
+ object_name = object.gql_name
165
+ object_key = object.to_sym
166
+ alias_proc = -> do
167
+ fetch(object_key,
168
+ base_class: base_class,
169
+ namespaces: base_namespace,
170
+ exclusive: true,
171
+ )
172
+ end
173
+
174
+ # Register the main type object
175
+ add(base_namespace, base_class, object_key, -> { object })
176
+
177
+ # Register all the aliases plus the object name
178
+ aliases = object.try(:aliases) || []
179
+ [object_name, *aliases].each do |alias_name|
180
+ add(base_namespace, base_class, alias_name, alias_proc)
181
+ end
182
+
183
+ # For each remaining namespace, register a key and a name alias
184
+ namespaces.product([object_key, object_name, *aliases]) do |(namespace, key_or_name)|
185
+ add(namespace, base_class, key_or_name, alias_proc)
186
+ end
187
+
188
+ # Return the object for chain purposes
189
+ @objects += 1
190
+ object
191
+ end
192
+
193
+ # Register an item alias. Either provide a block that trigger the fetch
194
+ # method to return that item, or a key from the same namespace and base
195
+ # class
196
+ def register_alias(name_or_key, key = nil, **xargs, &block)
197
+ raise ArgumentError, <<~MSG.squish unless key.nil? ^ block.nil?
198
+ Provide either a key or a block in order to register an alias.
199
+ MSG
200
+
201
+ base_class = xargs.delete(:base_class) || :Type
202
+ ensure_base_class!(base_class)
203
+
204
+ namespaces = xargs.delete(:namespaces) || []
205
+ namespaces = namespaces.to_a if namespaces.is_a?(Set)
206
+ namespaces << xargs.delete(:namespace)
207
+
208
+ namespaces = namespaces.compact.presence || [:base]
209
+
210
+ block ||= -> do
211
+ fetch(key, base_class: base_class, namespaces: namespaces, exclusive: true)
212
+ end
213
+
214
+ namespaces.each { |ns| add(ns, base_class, name_or_key, block) }
215
+ end
216
+
217
+ # Iterate over the types of the given +base_class+ that are defined on the
218
+ # given +namespaces+.
219
+ def each_from(namespaces, base_class: :Type, exclusive: false, &block)
220
+ register_pending!
221
+
222
+ namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
223
+ namespaces += [:base] unless namespaces.include?(:base) || exclusive
224
+
225
+ iterated = []
226
+ enumerator = Enumerator::Lazy.new(namespaces.uniq) do |yielder, *values|
227
+ next unless @index.key?(values.last)
228
+
229
+ # Only iterate over string based types
230
+ @index[values.last][base_class]&.each do |_key, value|
231
+ next if iterated.include?(value = value.call) || value.blank?
232
+ iterated << value
233
+ yielder << value
234
+ end
235
+ end
236
+
237
+ block.present? ? enumerator.each(&block) : enumerator
238
+ end
239
+
240
+ # Add a callback that will trigger when a type is registered under the
241
+ # given set of settings of this method
242
+ def after_register(name_or_key, base_class: :Type, namespaces: :base, &block)
243
+ item = fetch(name_or_key,
244
+ prevent_register: true,
245
+ base_class: base_class,
246
+ namespaces: namespaces,
247
+ )
248
+
249
+ return block.call(item) unless item.nil?
250
+
251
+ namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
252
+ position = callbacks[name_or_key].size
253
+
254
+ callbacks[name_or_key] << ->(n, b, result) do
255
+ return unless b === base_class && namespaces.include?(n)
256
+ block.call(result)
257
+ position
258
+ end
259
+ end
260
+
261
+ def inspect # :nodoc:
262
+ <<~INFO.squish + '>'
263
+ #<Rails::GraphQL::TypeMap [index]
264
+ @namespaces=#{@index.size}
265
+ @base_classes=#{base_classes.size}
266
+ @objects=#{@objects}
267
+ @pending=#{@pending.size}
268
+ INFO
269
+ end
270
+
271
+ private
272
+
273
+ attr_reader :callbacks
274
+
275
+ # Add a item to the index and then trigger the callbacks if any
276
+ def add(namespace, base_class, key, raw_result)
277
+ @index[namespace][base_class][key] = raw_result
278
+ return unless callbacks.key?(key)
279
+
280
+ result = nil
281
+ removeables = callbacks[key].map do |callback|
282
+ callback.call(namespace, base_class, result ||= raw_result.call)
283
+ end
284
+
285
+ removeables.compact.reverse_each(&callbacks[key].method(:delete_at))
286
+ callbacks.delete(key) if callbacks[key].empty?
287
+ end
288
+
289
+ # A list of classes to prevent the registration, since they might be
290
+ # the source of a fetch
291
+ def skip_register
292
+ @skip_register ||= []
293
+ end
294
+
295
+ # Clear the pending list of classes to be registered
296
+ def register_pending!
297
+ return if @pending.blank?
298
+
299
+ skip = skip_register.flatten
300
+ keep = []
301
+ validate = []
302
+
303
+ while (klass, source = @pending.shift)
304
+ next if klass.registered?
305
+
306
+ if skip.include?(klass)
307
+ keep << [klass, source]
308
+ else
309
+ validate << klass.register!
310
+ end
311
+ end
312
+
313
+ validate.compact.each(&:call)
314
+ rescue DefinitionError => e
315
+ raise e.class, e.message + "\n Defined at: #{source}"
316
+ ensure
317
+ @pending += keep unless keep.nil?
318
+ end
319
+
320
+ # Since concurrent map doesn't implement this method, use this to
321
+ # navigate through the index
322
+ def dig(*parts)
323
+ parts.inject(@index) do |h, key|
324
+ break unless h.key?(key)
325
+ h.fetch(key)
326
+ end
327
+ end
328
+
329
+ # Find the base class of an object, which is basically the class that
330
+ # doesn't inherit any other class (superclass is equal Object)
331
+ def find_base_class(object)
332
+ return object.base_type_class if object.respond_to?(:base_type_class)
333
+
334
+ base_class = object
335
+ base_class = base_class.superclass until base_class.superclass === Object
336
+ base_class.name.demodulize.to_sym
337
+ end
338
+
339
+ # Make sure that the given key is a valid base class key
340
+ def ensure_base_class!(key)
341
+ raise ArgumentError, <<~MSG.squish unless base_classes.keys.include?(key)
342
+ Unsupported base class "#{key.inspect}".
343
+ MSG
344
+ end
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails # :nodoc:
4
+ module GraphQL # :nodoc:
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
File without changes
@@ -0,0 +1 @@
1
+ {"data":{"__schema":{"queryType":{"name":"_Query"},"mutationType":{"name":"_Mutation"},"subscriptionType":{"name":"_Subscription"},"types":[{"kind":"ENUM","name":"Episode","description":"One of the films in the Star Wars Trilogy","fields":[],"inputFields":[],"interfaces":[],"enumValues":[{"name":"NEW_HOPE","description":"Released in 1977.","isDeprecated":false,"deprecationReason":null},{"name":"EMPIRE","description":"Released in 1980.","isDeprecated":false,"deprecationReason":null},{"name":"JEDI","description":"Released in 1983.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":[]},{"kind":"INTERFACE","name":"Character","description":"A character in the Star Wars Trilogy","fields":[{"name":"id","description":"The id of the character","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The name of the character","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"friends","description":"The friends of the character, or an empty list if they have none","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"INTERFACE","name":"Character","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"appearsIn","description":"Which movies they appear in","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"Episode","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"secretBackstory","description":"All secrets about their past","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[{"kind":"OBJECT","name":"Human","ofType":null},{"kind":"OBJECT","name":"Droid","ofType":null}]},{"kind":"OBJECT","name":"Human","description":"A humanoid creature in the Star Wars universe","fields":[{"name":"id","description":"The id of the character","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The name of the character","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"friends","description":"The friends of the character, or an empty list if they have none","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"INTERFACE","name":"Character","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"appearsIn","description":"Which movies they appear in","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"Episode","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"secretBackstory","description":"All secrets about their past","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"homePlanet","description":"The home planet of the human, or null if unknown","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[{"kind":"INTERFACE","name":"Character","ofType":null}],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"Droid","description":"A mechanical creature in the Star Wars universe","fields":[{"name":"id","description":"The id of the character","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The name of the character","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"friends","description":"The friends of the character, or an empty list if they have none","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"INTERFACE","name":"Character","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"appearsIn","description":"Which movies they appear in","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"Episode","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"secretBackstory","description":"All secrets about their past","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryFunction","description":"The primary function of the droid","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[{"kind":"INTERFACE","name":"Character","ofType":null}],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"_Query","description":null,"fields":[{"name":"__schema","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Schema","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"__type","description":null,"args":[{"name":"name","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hero","description":"Find the hero of the whole saga","args":[{"name":"episode","description":"Return for a specific episode","type":{"kind":"ENUM","name":"Episode","ofType":null},"defaultValue":null}],"type":{"kind":"INTERFACE","name":"Character","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"human","description":"Find a human character","args":[{"name":"id","description":"ID of the human","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Human","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"droid","description":"Find a droid character","args":[{"name":"id","description":"ID of the droid","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Droid","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"_Mutation","description":null,"fields":[{"name":"changeHuman","description":"Change the episodes of a human and return a set of characters","args":[{"name":"id","description":"The ID of the human to be changed","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"episodes","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"Episode","ofType":null}}},"defaultValue":null}],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INTERFACE","name":"Character","ofType":null}}}},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"ENUM","name":"__TypeKind","description":"The fundamental unit of any GraphQL Schema is the type.\nThis enum enlist all the valid base types.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[{"name":"SCALAR","description":"Scalar types represent primitive leaf values in a GraphQL type system.\n","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Objects represent a list of named fields, each of which yield a value of a\nspecific type.\n","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Interfaces represent a list of named fields and their types.\n","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Unions represent an object that could be one of a list of GraphQL Object types.\n","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Enum types, like scalar types, also represent leaf values in a GraphQL\ntype system. However Enum types describe the set of possible values.\n","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Objects represent a list of named fields, each of which yield a value of\na specific type.\n","isDeprecated":false,"deprecationReason":null},{"name":"LIST","description":"A GraphQL list is a special collection type which declares the type of\neach item in the List (referred to as the item type of the list).\n","isDeprecated":false,"deprecationReason":null},{"name":"NON_NULL","description":"This type wraps an underlying type, and this type acts identically to that wrapped\ntype, with the exception that null is not a valid response for the wrapping type.\n","isDeprecated":false,"deprecationReason":null}],"possibleTypes":[]},{"kind":"OBJECT","name":"__Directive","description":"Directives provide a way to describe alternate runtime execution\nand type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL’s execution\nbehavior in ways field arguments will not suffice, such as conditionally\nincluding or skipping a field. Directives provide this by describing\nadditional information to the executor.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"locations","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__DirectiveLocation","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"__EnumValue","description":"One of the values of an Enum object. It is unique within the Enum set\nof values. It's a string representation, not a numeric representation,\nof a value kept as all caps (ie. ONE_VALUE).","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"__Field","description":"Fields are the elements that compose both Objects and Interfaces. Each\nfield in these other objects may contain arguments and always yields\na value of a specific type.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"__InputValue","description":"Alongside with scalars and enums, input value objects allow the user\nto provide values to arguments on fields and directives. Different\nfrom those, input values accepts a list of keyed values, instead of\na single value.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"defaultValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"__Schema","description":"A GraphQL service’s collective type system capabilities are referred\nto as that service’s \"schema\". A schema is defined in terms of the\ntypes and directives it supports as well as the root operation types\nfor each kind of operation: query, mutation, and subscription; this\ndetermines the place in the type system where those operations begin.","fields":[{"name":"types","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"queryType","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"mutationType","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"subscriptionType","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"directives","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Directive","ofType":null}}}},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"OBJECT","name":"__Type","description":"The fundamental unit of any GraphQL Schema is the type. There are six\nkinds of named type definitions in GraphQL, and two wrapping types.\n\nThe most basic type is a +Scalar+. A scalar represents a primitive value,\nlike a string or an integer.\n\n+Scalars+ and +Enums+ form the leaves in response trees; the intermediate\nlevels are +Object+ types, which define a set of fields.\n\nAn +Interface+ defines a list of fields; +Object+ types that implement\nthat interface are guaranteed to implement those fields.\n\nA +Union+ defines a list of possible types; similar to interfaces,\nwhenever the type system claims a union will be returned, one of the\npossible types will be returned.\n\nFinally, oftentimes it is useful to provide complex structs as inputs\nto GraphQL field arguments or variables; the +Input Object+ type allows\nthe schema to define exactly what data is expected.","fields":[{"name":"kind","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__TypeKind","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fields","description":"OBJECT and INTERFACE only","args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Field","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"interfaces","description":"OBJECT only","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"possibleTypes","description":"INTERFACE and UNION only","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"enumValues","description":"ENUM only","args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__EnumValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"inputFields","description":"INPUT_OBJECT only","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"ofType","description":"NON_NULL and LIST only","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"String","description":"The String scalar type represents textual data, represented as UTF‐8 character\nsequences.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Boolean","description":"The Boolean scalar type represents true or false.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"ID","description":"The ID scalar type represents a unique identifier and it is serialized in the same\nway as a String but it accepts both numeric and string based values as input.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Bigint","description":"The Bigint scalar type represents a signed numeric non‐fractional value.\nIt can go beyond the Int 32‐bit limit, but it's exchanged as a string.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Binary","description":"The Binary scalar type represents a Base64 string.\nNormally used to share files and uploads.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Date","description":"The Date scalar type represents a ISO 8601 string value.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"DateTime","description":"The DateTime scalar type represents a ISO 8601 string value.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Decimal","description":"The Decimal scalar type represents signed fractional values with extra precision.\nThe values are exchange as string.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Time","description":"The Time scalar type that represents a distance in time using hours,\nminutes, seconds, and miliseconds.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"ENUM","name":"__DirectiveLocation","description":"The valid locations that a directive may be placed.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[{"name":"QUERY","description":"Mark as a executable directive usable on query objects.","isDeprecated":false,"deprecationReason":null},{"name":"MUTATION","description":"Mark as a executable directive usable on mutation objects.","isDeprecated":false,"deprecationReason":null},{"name":"SUBSCRIPTION","description":"Mark as a executable directive usable on subscription objects.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD","description":"Mark as a executable directive usable on field objects.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_DEFINITION","description":"Mark as a executable directive usable on fragment definition objects.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_SPREAD","description":"Mark as a executable directive usable on fragment spread objects.","isDeprecated":false,"deprecationReason":null},{"name":"INLINE_FRAGMENT","description":"Mark as a executable directive usable on inline fragment objects.","isDeprecated":false,"deprecationReason":null},{"name":"SCHEMA","description":"Mark as a type system directive usable on schema definitions.","isDeprecated":false,"deprecationReason":null},{"name":"SCALAR","description":"Mark as a type system directive usable on scalar definitions.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Mark as a type system directive usable on object definitions.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD_DEFINITION","description":"Mark as a type system directive usable on field definitions.","isDeprecated":false,"deprecationReason":null},{"name":"ARGUMENT_DEFINITION","description":"Mark as a type system directive usable on argument definitions.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Mark as a type system directive usable on interface definitions.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Mark as a type system directive usable on union definitions.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Mark as a type system directive usable on enum definitions.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM_VALUE","description":"Mark as a type system directive usable on enum value definitions.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Mark as a type system directive usable on input object definitions.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_FIELD_DEFINITION","description":"Mark as a type system directive usable on input field definitions.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":[]},{"kind":"SCALAR","name":"Int","description":"The Int scalar type represents a signed 32‐bit numeric non‐fractional value.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]},{"kind":"SCALAR","name":"Float","description":"The Float scalar type represents signed double‐precision fractional values.","fields":[],"inputFields":[],"interfaces":[],"enumValues":[],"possibleTypes":[]}],"directives":[{"name":"deprecated","description":"Indicate deprecated portions of a GraphQL service’s schema, such as deprecated\nfields on a type or deprecated enum values.","locations":["FIELD_DEFINITION","ENUM_VALUE"],"args":[{"name":"reason","description":"Explain why the underlying element was marked as deprecated. If possible,\nindicate what element should be used instead. This description is formatted\nusing Markdown syntax (as specified by [CommonMark](http://commonmark.org/)).","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}]},{"name":"include","description":"Allows for conditional inclusion during execution as described by the if argument.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"When false, the underlying element will be automatically marked as null.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"skip","description":"Allows for conditional exclusion during execution as described by the if argument.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"When true, the underlying element will be automatically marked as null.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]}]}}}
@@ -0,0 +1,91 @@
1
+ query IntrospectionQuery {
2
+ __schema {
3
+ queryType { name }
4
+ mutationType { name }
5
+ subscriptionType { name }
6
+ types {
7
+ ...FullType
8
+ }
9
+ directives {
10
+ name
11
+ description
12
+ locations
13
+ args {
14
+ ...InputValue
15
+ }
16
+ }
17
+ }
18
+ }
19
+
20
+ fragment FullType on __Type {
21
+ kind
22
+ name
23
+ description
24
+ fields(includeDeprecated: true) {
25
+ name
26
+ description
27
+ args {
28
+ ...InputValue
29
+ }
30
+ type {
31
+ ...TypeRef
32
+ }
33
+ isDeprecated
34
+ deprecationReason
35
+ }
36
+ inputFields {
37
+ ...InputValue
38
+ }
39
+ interfaces {
40
+ ...TypeRef
41
+ }
42
+ enumValues(includeDeprecated: true) {
43
+ name
44
+ description
45
+ isDeprecated
46
+ deprecationReason
47
+ }
48
+ possibleTypes {
49
+ ...TypeRef
50
+ }
51
+ }
52
+
53
+ fragment InputValue on __InputValue {
54
+ name
55
+ description
56
+ type { ...TypeRef }
57
+ defaultValue
58
+ }
59
+
60
+ fragment TypeRef on __Type {
61
+ kind
62
+ name
63
+ ofType {
64
+ kind
65
+ name
66
+ ofType {
67
+ kind
68
+ name
69
+ ofType {
70
+ kind
71
+ name
72
+ ofType {
73
+ kind
74
+ name
75
+ ofType {
76
+ kind
77
+ name
78
+ ofType {
79
+ kind
80
+ name
81
+ ofType {
82
+ kind
83
+ name
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }