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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +31 -0
- data/ext/depend +3 -0
- data/ext/extconf.rb +57 -0
- data/ext/graphqlparser/Ast.cpp +346 -0
- data/ext/graphqlparser/Ast.h +1214 -0
- data/ext/graphqlparser/AstNode.h +36 -0
- data/ext/graphqlparser/AstVisitor.h +137 -0
- data/ext/graphqlparser/GraphQLParser.cpp +76 -0
- data/ext/graphqlparser/GraphQLParser.h +55 -0
- data/ext/graphqlparser/JsonVisitor.cpp +161 -0
- data/ext/graphqlparser/JsonVisitor.cpp.inc +456 -0
- data/ext/graphqlparser/JsonVisitor.h +121 -0
- data/ext/graphqlparser/JsonVisitor.h.inc +110 -0
- data/ext/graphqlparser/VERSION +1 -0
- data/ext/graphqlparser/c/GraphQLAst.cpp +324 -0
- data/ext/graphqlparser/c/GraphQLAst.h +180 -0
- data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +44 -0
- data/ext/graphqlparser/c/GraphQLAstNode.cpp +25 -0
- data/ext/graphqlparser/c/GraphQLAstNode.h +33 -0
- data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +21 -0
- data/ext/graphqlparser/c/GraphQLAstToJSON.h +24 -0
- data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +55 -0
- data/ext/graphqlparser/c/GraphQLAstVisitor.h +53 -0
- data/ext/graphqlparser/c/GraphQLParser.cpp +35 -0
- data/ext/graphqlparser/c/GraphQLParser.h +54 -0
- data/ext/graphqlparser/dump_json_ast.cpp +48 -0
- data/ext/graphqlparser/lexer.lpp +324 -0
- data/ext/graphqlparser/parser.ypp +693 -0
- data/ext/graphqlparser/parsergen/lexer.cpp +2633 -0
- data/ext/graphqlparser/parsergen/lexer.h +528 -0
- data/ext/graphqlparser/parsergen/location.hh +189 -0
- data/ext/graphqlparser/parsergen/parser.tab.cpp +3300 -0
- data/ext/graphqlparser/parsergen/parser.tab.hpp +646 -0
- data/ext/graphqlparser/parsergen/position.hh +179 -0
- data/ext/graphqlparser/parsergen/stack.hh +156 -0
- data/ext/graphqlparser/syntaxdefs.h +19 -0
- data/ext/libgraphqlparser/AstNode.h +36 -0
- data/ext/libgraphqlparser/CMakeLists.txt +148 -0
- data/ext/libgraphqlparser/CONTRIBUTING.md +23 -0
- data/ext/libgraphqlparser/GraphQLParser.cpp +76 -0
- data/ext/libgraphqlparser/GraphQLParser.h +55 -0
- data/ext/libgraphqlparser/JsonVisitor.cpp +161 -0
- data/ext/libgraphqlparser/JsonVisitor.h +121 -0
- data/ext/libgraphqlparser/LICENSE +22 -0
- data/ext/libgraphqlparser/README.clang-tidy +7 -0
- data/ext/libgraphqlparser/README.md +84 -0
- data/ext/libgraphqlparser/ast/ast.ast +203 -0
- data/ext/libgraphqlparser/ast/ast.py +61 -0
- data/ext/libgraphqlparser/ast/c.py +100 -0
- data/ext/libgraphqlparser/ast/c.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_impl.py +61 -0
- data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_visitor_impl.py +39 -0
- data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/casing.py +26 -0
- data/ext/libgraphqlparser/ast/casing.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx.py +197 -0
- data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_impl.py +61 -0
- data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +42 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +80 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_visitor.py +64 -0
- data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
- data/ext/libgraphqlparser/ast/js.py +65 -0
- data/ext/libgraphqlparser/ast/license.py +10 -0
- data/ext/libgraphqlparser/ast/license.pyc +0 -0
- data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +25 -0
- data/ext/libgraphqlparser/c/GraphQLAstNode.h +33 -0
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +21 -0
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +24 -0
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +55 -0
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +53 -0
- data/ext/libgraphqlparser/c/GraphQLParser.cpp +35 -0
- data/ext/libgraphqlparser/c/GraphQLParser.h +54 -0
- data/ext/libgraphqlparser/clang-tidy-all.sh +3 -0
- data/ext/libgraphqlparser/cmake/version.cmake +16 -0
- data/ext/libgraphqlparser/dump_json_ast.cpp +48 -0
- data/ext/libgraphqlparser/go/README.md +20 -0
- data/ext/libgraphqlparser/go/callbacks.go +18 -0
- data/ext/libgraphqlparser/go/gotest.go +64 -0
- data/ext/libgraphqlparser/lexer.lpp +324 -0
- data/ext/libgraphqlparser/libgraphqlparser.pc.in +11 -0
- data/ext/libgraphqlparser/parser.ypp +693 -0
- data/ext/libgraphqlparser/parsergen/lexer.cpp +2633 -0
- data/ext/libgraphqlparser/parsergen/lexer.h +528 -0
- data/ext/libgraphqlparser/parsergen/location.hh +189 -0
- data/ext/libgraphqlparser/parsergen/parser.tab.cpp +3300 -0
- data/ext/libgraphqlparser/parsergen/parser.tab.hpp +646 -0
- data/ext/libgraphqlparser/parsergen/position.hh +179 -0
- data/ext/libgraphqlparser/parsergen/stack.hh +156 -0
- data/ext/libgraphqlparser/python/CMakeLists.txt +14 -0
- data/ext/libgraphqlparser/python/README.md +5 -0
- data/ext/libgraphqlparser/python/example.py +31 -0
- data/ext/libgraphqlparser/syntaxdefs.h +19 -0
- data/ext/libgraphqlparser/test/BuildCAPI.c +5 -0
- data/ext/libgraphqlparser/test/CMakeLists.txt +25 -0
- data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +28 -0
- data/ext/libgraphqlparser/test/ParserTests.cpp +352 -0
- data/ext/libgraphqlparser/test/kitchen-sink.graphql +59 -0
- data/ext/libgraphqlparser/test/kitchen-sink.json +1 -0
- data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +78 -0
- data/ext/libgraphqlparser/test/schema-kitchen-sink.json +1 -0
- data/ext/libgraphqlparser/test/valgrind.supp +33 -0
- data/ext/version.cpp +21 -0
- data/lib/generators/graphql/controller_generator.rb +22 -0
- data/lib/generators/graphql/schema_generator.rb +22 -0
- data/lib/generators/graphql/templates/controller.erb +5 -0
- data/lib/generators/graphql/templates/schema.erb +6 -0
- data/lib/graphqlparser.so +0 -0
- data/lib/rails-graphql.rb +2 -0
- data/lib/rails/graphql.rake +1 -0
- data/lib/rails/graphql.rb +185 -0
- data/lib/rails/graphql/adapters/mysql_adapter.rb +0 -0
- data/lib/rails/graphql/adapters/pg_adapter.rb +50 -0
- data/lib/rails/graphql/adapters/sqlite_adapter.rb +39 -0
- data/lib/rails/graphql/argument.rb +220 -0
- data/lib/rails/graphql/callback.rb +124 -0
- data/lib/rails/graphql/collectors.rb +14 -0
- data/lib/rails/graphql/collectors/hash_collector.rb +83 -0
- data/lib/rails/graphql/collectors/idented_collector.rb +73 -0
- data/lib/rails/graphql/collectors/json_collector.rb +114 -0
- data/lib/rails/graphql/config.rb +61 -0
- data/lib/rails/graphql/directive.rb +203 -0
- data/lib/rails/graphql/directive/deprecated_directive.rb +59 -0
- data/lib/rails/graphql/directive/include_directive.rb +24 -0
- data/lib/rails/graphql/directive/skip_directive.rb +24 -0
- data/lib/rails/graphql/errors.rb +42 -0
- data/lib/rails/graphql/event.rb +141 -0
- data/lib/rails/graphql/field.rb +318 -0
- data/lib/rails/graphql/field/input_field.rb +92 -0
- data/lib/rails/graphql/field/mutation_field.rb +52 -0
- data/lib/rails/graphql/field/output_field.rb +96 -0
- data/lib/rails/graphql/field/proxied_field.rb +131 -0
- data/lib/rails/graphql/field/resolved_field.rb +96 -0
- data/lib/rails/graphql/field/scoped_config.rb +22 -0
- data/lib/rails/graphql/field/typed_field.rb +104 -0
- data/lib/rails/graphql/helpers.rb +40 -0
- data/lib/rails/graphql/helpers/attribute_delegator.rb +39 -0
- data/lib/rails/graphql/helpers/inherited_collection.rb +152 -0
- data/lib/rails/graphql/helpers/leaf_from_ar.rb +141 -0
- data/lib/rails/graphql/helpers/registerable.rb +103 -0
- data/lib/rails/graphql/helpers/with_arguments.rb +125 -0
- data/lib/rails/graphql/helpers/with_assignment.rb +113 -0
- data/lib/rails/graphql/helpers/with_callbacks.rb +55 -0
- data/lib/rails/graphql/helpers/with_directives.rb +126 -0
- data/lib/rails/graphql/helpers/with_events.rb +81 -0
- data/lib/rails/graphql/helpers/with_fields.rb +141 -0
- data/lib/rails/graphql/helpers/with_namespace.rb +40 -0
- data/lib/rails/graphql/helpers/with_owner.rb +35 -0
- data/lib/rails/graphql/helpers/with_schema_fields.rb +230 -0
- data/lib/rails/graphql/helpers/with_validator.rb +52 -0
- data/lib/rails/graphql/introspection.rb +53 -0
- data/lib/rails/graphql/native.rb +56 -0
- data/lib/rails/graphql/native/functions.rb +38 -0
- data/lib/rails/graphql/native/location.rb +41 -0
- data/lib/rails/graphql/native/pointers.rb +23 -0
- data/lib/rails/graphql/native/visitor.rb +349 -0
- data/lib/rails/graphql/railtie.rb +85 -0
- data/lib/rails/graphql/railties/base_generator.rb +35 -0
- data/lib/rails/graphql/railties/controller.rb +101 -0
- data/lib/rails/graphql/railties/controller_runtime.rb +40 -0
- data/lib/rails/graphql/railties/log_subscriber.rb +62 -0
- data/lib/rails/graphql/request.rb +343 -0
- data/lib/rails/graphql/request/arguments.rb +93 -0
- data/lib/rails/graphql/request/component.rb +100 -0
- data/lib/rails/graphql/request/component/field.rb +225 -0
- data/lib/rails/graphql/request/component/fragment.rb +118 -0
- data/lib/rails/graphql/request/component/operation.rb +178 -0
- data/lib/rails/graphql/request/component/operation/subscription.rb +16 -0
- data/lib/rails/graphql/request/component/spread.rb +119 -0
- data/lib/rails/graphql/request/component/typename.rb +82 -0
- data/lib/rails/graphql/request/context.rb +51 -0
- data/lib/rails/graphql/request/errors.rb +54 -0
- data/lib/rails/graphql/request/event.rb +112 -0
- data/lib/rails/graphql/request/helpers/directives.rb +64 -0
- data/lib/rails/graphql/request/helpers/selection_set.rb +87 -0
- data/lib/rails/graphql/request/helpers/value_writers.rb +115 -0
- data/lib/rails/graphql/request/steps/organizable.rb +146 -0
- data/lib/rails/graphql/request/steps/prepareable.rb +33 -0
- data/lib/rails/graphql/request/steps/resolveable.rb +32 -0
- data/lib/rails/graphql/request/strategy.rb +249 -0
- data/lib/rails/graphql/request/strategy/dynamic_instance.rb +41 -0
- data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +36 -0
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +28 -0
- data/lib/rails/graphql/schema.rb +272 -0
- data/lib/rails/graphql/shortcuts.rb +77 -0
- data/lib/rails/graphql/source.rb +371 -0
- data/lib/rails/graphql/source/active_record/builders.rb +154 -0
- data/lib/rails/graphql/source/active_record_source.rb +231 -0
- data/lib/rails/graphql/source/scoped_arguments.rb +87 -0
- data/lib/rails/graphql/to_gql.rb +368 -0
- data/lib/rails/graphql/type.rb +138 -0
- data/lib/rails/graphql/type/enum.rb +206 -0
- data/lib/rails/graphql/type/enum/directive_location_enum.rb +30 -0
- data/lib/rails/graphql/type/enum/type_kind_enum.rb +57 -0
- data/lib/rails/graphql/type/input.rb +134 -0
- data/lib/rails/graphql/type/interface.rb +82 -0
- data/lib/rails/graphql/type/object.rb +111 -0
- data/lib/rails/graphql/type/object/directive_object.rb +34 -0
- data/lib/rails/graphql/type/object/enum_value_object.rb +25 -0
- data/lib/rails/graphql/type/object/field_object.rb +54 -0
- data/lib/rails/graphql/type/object/input_value_object.rb +49 -0
- data/lib/rails/graphql/type/object/schema_object.rb +40 -0
- data/lib/rails/graphql/type/object/type_object.rb +136 -0
- data/lib/rails/graphql/type/scalar.rb +71 -0
- data/lib/rails/graphql/type/scalar/bigint_scalar.rb +34 -0
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +30 -0
- data/lib/rails/graphql/type/scalar/boolean_scalar.rb +37 -0
- data/lib/rails/graphql/type/scalar/date_scalar.rb +34 -0
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +32 -0
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +35 -0
- data/lib/rails/graphql/type/scalar/float_scalar.rb +32 -0
- data/lib/rails/graphql/type/scalar/id_scalar.rb +39 -0
- data/lib/rails/graphql/type/scalar/int_scalar.rb +36 -0
- data/lib/rails/graphql/type/scalar/string_scalar.rb +28 -0
- data/lib/rails/graphql/type/scalar/time_scalar.rb +40 -0
- data/lib/rails/graphql/type/union.rb +87 -0
- data/lib/rails/graphql/type_map.rb +347 -0
- data/lib/rails/graphql/version.rb +7 -0
- data/test/assets/introspection-db.json +0 -0
- data/test/assets/introspection-mem.txt +1 -0
- data/test/assets/introspection.gql +91 -0
- data/test/assets/luke.jpg +0 -0
- data/test/assets/mem.gql +428 -0
- data/test/assets/sqlite.gql +423 -0
- data/test/config.rb +80 -0
- data/test/graphql/request/context_test.rb +70 -0
- data/test/graphql/schema_test.rb +190 -0
- data/test/graphql/source_test.rb +237 -0
- data/test/graphql/type/enum_test.rb +203 -0
- data/test/graphql/type/input_test.rb +138 -0
- data/test/graphql/type/interface_test.rb +72 -0
- data/test/graphql/type/object_test.rb +104 -0
- data/test/graphql/type/scalar/bigint_scalar_test.rb +42 -0
- data/test/graphql/type/scalar/binary_scalar_test.rb +17 -0
- data/test/graphql/type/scalar/boolean_scalar_test.rb +40 -0
- data/test/graphql/type/scalar/date_scalar_test.rb +29 -0
- data/test/graphql/type/scalar/date_time_scalar_test.rb +29 -0
- data/test/graphql/type/scalar/decimal_scalar_test.rb +28 -0
- data/test/graphql/type/scalar/float_scalar_test.rb +22 -0
- data/test/graphql/type/scalar/id_scalar_test.rb +26 -0
- data/test/graphql/type/scalar/int_scalar_test.rb +26 -0
- data/test/graphql/type/scalar/string_scalar_test.rb +17 -0
- data/test/graphql/type/scalar/time_scalar_test.rb +36 -0
- data/test/graphql/type/scalar_test.rb +45 -0
- data/test/graphql/type/union_test.rb +82 -0
- data/test/graphql/type_map_test.rb +362 -0
- data/test/graphql/type_test.rb +68 -0
- data/test/graphql_test.rb +55 -0
- data/test/integration/config.rb +56 -0
- data/test/integration/memory/star_wars_introspection_test.rb +144 -0
- data/test/integration/memory/star_wars_query_test.rb +184 -0
- data/test/integration/memory/star_wars_validation_test.rb +99 -0
- data/test/integration/schemas/memory.rb +232 -0
- data/test/integration/schemas/sqlite.rb +82 -0
- data/test/integration/sqlite/star_wars_introspection_test.rb +15 -0
- data/test/integration/sqlite/star_wars_mutation_test.rb +82 -0
- data/test/integration/sqlite/star_wars_query_test.rb +71 -0
- data/test/test_ext.rb +48 -0
- metadata +509 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# = GraphQL InterfaceType
|
7
|
+
#
|
8
|
+
# Interfaces represent a list of named fields and their types.
|
9
|
+
# See http://spec.graphql.org/June2018/#InterfaceTypeDefinition
|
10
|
+
#
|
11
|
+
# This class doesn't implements +valid_output?+ nor any of the output like
|
12
|
+
# methods because the Object class that uses interface already fetches
|
13
|
+
# all the fields for its composition and does the validating and
|
14
|
+
# serializing process.
|
15
|
+
class Interface < Type
|
16
|
+
extend Helpers::WithAssignment
|
17
|
+
extend Helpers::WithFields
|
18
|
+
|
19
|
+
setup! output: true
|
20
|
+
|
21
|
+
self.field_type = Field::OutputField
|
22
|
+
|
23
|
+
# The purpose of instantiating an interface is to have access to its
|
24
|
+
# public methods. It then runs from the strategy perspective, pointing
|
25
|
+
# out any other methods to the manually set event
|
26
|
+
delegate_missing_to :event
|
27
|
+
attr_reader :event
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# TODO: Use inherited attribute for types
|
31
|
+
|
32
|
+
# Stores the list of types associated with the interface so it can
|
33
|
+
# be used during the execution step to find the right object type
|
34
|
+
def types
|
35
|
+
@types ||= Set.new
|
36
|
+
end
|
37
|
+
|
38
|
+
# Get the list of all inherited-aware associated types
|
39
|
+
def all_types
|
40
|
+
(superclass.try(:all_types) || Set.new) + (defined?(@types) ? @types : Set.new)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Check if the other type is equivalent, by checking if the other is
|
44
|
+
# an object and the object implements this interface
|
45
|
+
def =~(other)
|
46
|
+
super || (other.object? && other.implements?(self))
|
47
|
+
end
|
48
|
+
|
49
|
+
# When attaching an interface to an object, copy the fields and add to
|
50
|
+
# the list of types. Pre-existing same-named fields with are not
|
51
|
+
# equivalent produces an exception.
|
52
|
+
def implemented(object)
|
53
|
+
fields.each do |name, field|
|
54
|
+
defined = object.field?(name)
|
55
|
+
invalid = defined && object.fields[name] !~ field
|
56
|
+
raise ArgumentError, <<~MSG.squish if invalid
|
57
|
+
The "#{object.gql_name}" object already has a "#{field.gql_name}" field and it
|
58
|
+
is not equivalent to the one defined on the "#{gql_name}" interface.
|
59
|
+
MSG
|
60
|
+
|
61
|
+
object.proxy_field(field) unless defined
|
62
|
+
end
|
63
|
+
|
64
|
+
types << object
|
65
|
+
end
|
66
|
+
|
67
|
+
def inspect # :nodoc:
|
68
|
+
fields = @fields.values.map(&:inspect)
|
69
|
+
fields = fields.presence && " {#{fields.join(', ')}}"
|
70
|
+
"#<GraphQL::Interface #{gql_name}#{fields}>"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Check if the given object is properly implementing this interface
|
74
|
+
def validate(*)
|
75
|
+
# Don't validate interfaces since the fields are copied and
|
76
|
+
# the interface might have broken field types due to namespaces
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# = GraphQL ObjectType
|
7
|
+
#
|
8
|
+
# Objects represent a list of named fields, each of which yield a value of
|
9
|
+
# a specific type.
|
10
|
+
# See http://spec.graphql.org/June2018/#ObjectTypeDefinition
|
11
|
+
class Object < Type
|
12
|
+
extend ActiveSupport::Autoload
|
13
|
+
extend Helpers::WithAssignment
|
14
|
+
extend Helpers::WithFields
|
15
|
+
|
16
|
+
setup! output: true
|
17
|
+
|
18
|
+
self.field_type = Field::OutputField
|
19
|
+
self.valid_field_types = [
|
20
|
+
Type::Enum,
|
21
|
+
Type::Interface,
|
22
|
+
Type::Object,
|
23
|
+
Type::Scalar,
|
24
|
+
Type::Union,
|
25
|
+
].freeze
|
26
|
+
|
27
|
+
eager_autoload do
|
28
|
+
autoload :DirectiveObject
|
29
|
+
autoload :EnumValueObject
|
30
|
+
autoload :FieldObject
|
31
|
+
autoload :InputValueObject
|
32
|
+
autoload :SchemaObject
|
33
|
+
autoload :TypeObject
|
34
|
+
end
|
35
|
+
|
36
|
+
# Define the methods for accessing the interfaces of the object
|
37
|
+
inherited_collection :interfaces, instance_reader: false
|
38
|
+
|
39
|
+
# The purpose of instantiating an object is to have access to its
|
40
|
+
# public methods. It then runs from the strategy perspective, pointing
|
41
|
+
# out any other methods to the manually set event
|
42
|
+
delegate_missing_to :event
|
43
|
+
attr_reader :event
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# Plain objects can check if a given value is a valid member
|
47
|
+
def valid_member?(value)
|
48
|
+
return true if valid_assignment?(value)
|
49
|
+
checker = value.is_a?(Hash) ? :key? : :respond_to?
|
50
|
+
value = value.with_indifferent_access if value.is_a?(Hash)
|
51
|
+
fields.values.all? { |field| value.public_send(checker, field.method_name) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Check if the other type is equivalent, by checking if the other is
|
55
|
+
# an interface that the current object implements
|
56
|
+
def =~(other)
|
57
|
+
super || (other.interface? && implements?(other))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Use this method to assign interfaces to the object
|
61
|
+
def implements(*others)
|
62
|
+
return if others.blank?
|
63
|
+
|
64
|
+
cache = all_interfaces.dup
|
65
|
+
others.flat_map do |item|
|
66
|
+
item = find_interface!(item)
|
67
|
+
next if cache.include?(item)
|
68
|
+
|
69
|
+
item.implemented(self)
|
70
|
+
interfaces << item
|
71
|
+
cache << item
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Check if the object implements the given +interface+
|
76
|
+
def implements?(interface)
|
77
|
+
(object = find_interface(interface)).present? && all_interfaces.include?(object)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Soft find an object as an +interface+
|
83
|
+
def find_interface(object)
|
84
|
+
find_interface!(object)
|
85
|
+
rescue ArgumentError
|
86
|
+
# The object was not found as an actual interface
|
87
|
+
end
|
88
|
+
|
89
|
+
# Find a given +object+ and ensures it is an interface
|
90
|
+
def find_interface!(object)
|
91
|
+
object = GraphQL.type_map.fetch!(object,
|
92
|
+
namespaces: namespaces,
|
93
|
+
prevent_register: self,
|
94
|
+
) unless object.is_a?(Module) && object < Type::Interface
|
95
|
+
|
96
|
+
return object if object.try(:interface?)
|
97
|
+
raise ArgumentError, <<~MSG.squish
|
98
|
+
The given "#{object}" is not a valid interface.
|
99
|
+
MSG
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def deprecated_directive
|
106
|
+
GraphQL::Directive::DeprecatedDirective
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# The introspection object for directives
|
7
|
+
class Object::DirectiveObject < Object
|
8
|
+
self.assigned_to = 'Rails::GraphQL::Directive'
|
9
|
+
self.spec_object = true
|
10
|
+
|
11
|
+
rename! '__Directive'
|
12
|
+
|
13
|
+
desc <<~DESC
|
14
|
+
Directives provide a way to describe alternate runtime execution
|
15
|
+
and type validation behavior in a GraphQL document.
|
16
|
+
|
17
|
+
In some cases, you need to provide options to alter GraphQL’s execution
|
18
|
+
behavior in ways field arguments will not suffice, such as conditionally
|
19
|
+
including or skipping a field. Directives provide this by describing
|
20
|
+
additional information to the executor.
|
21
|
+
DESC
|
22
|
+
|
23
|
+
field :name, :string, null: false, method_name: :gql_name
|
24
|
+
field :description, :string
|
25
|
+
field :locations, '__DirectiveLocation', full: true
|
26
|
+
field :args, '__InputValue', full: true
|
27
|
+
|
28
|
+
def args
|
29
|
+
all_arguments.values
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# The introspection object for an enum value
|
7
|
+
class Object::EnumValueObject < Object
|
8
|
+
self.spec_object = true
|
9
|
+
|
10
|
+
rename! '__EnumValue'
|
11
|
+
|
12
|
+
desc <<~DESC
|
13
|
+
One of the values of an Enum object. It is unique within the Enum set
|
14
|
+
of values. It's a string representation, not a numeric representation,
|
15
|
+
of a value kept as all caps (ie. ONE_VALUE).
|
16
|
+
DESC
|
17
|
+
|
18
|
+
field :name, :string, null: false
|
19
|
+
field :description, :string
|
20
|
+
field :is_deprecated, :boolean, null: false
|
21
|
+
field :deprecation_reason, :string
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# The introspection object for a field on objects and interfaces
|
7
|
+
class Object::FieldObject < Object
|
8
|
+
self.assigned_to = 'Rails::GraphQL::Field'
|
9
|
+
self.spec_object = true
|
10
|
+
|
11
|
+
delegate :fake_type_object, to: 'Object::TypeObject'
|
12
|
+
|
13
|
+
rename! '__Field'
|
14
|
+
|
15
|
+
desc <<~DESC
|
16
|
+
Fields are the elements that compose both Objects and Interfaces. Each
|
17
|
+
field in these other objects may contain arguments and always yields
|
18
|
+
a value of a specific type.
|
19
|
+
DESC
|
20
|
+
|
21
|
+
field :name, :string, null: false, method_name: :gql_name
|
22
|
+
field :description, :string
|
23
|
+
field :args, '__InputValue', full: true
|
24
|
+
field :type, '__Type', null: false, method_name: :build_type
|
25
|
+
field :is_deprecated, :boolean, null: false, method_name: :deprecated?
|
26
|
+
field :deprecation_reason, :string
|
27
|
+
|
28
|
+
def build_type
|
29
|
+
result = current.type_klass
|
30
|
+
|
31
|
+
if current.array?
|
32
|
+
result = fake_type_object(:non_null, result) unless current.nullable?
|
33
|
+
result = fake_type_object(:list, result)
|
34
|
+
end
|
35
|
+
|
36
|
+
result = fake_type_object(:non_null, result) unless current.null?
|
37
|
+
result
|
38
|
+
end
|
39
|
+
|
40
|
+
def args
|
41
|
+
all_arguments.values
|
42
|
+
end
|
43
|
+
|
44
|
+
def deprecated?
|
45
|
+
current.using?(deprecated_directive)
|
46
|
+
end
|
47
|
+
|
48
|
+
def deprecation_reason
|
49
|
+
current.all_directives.find { |item| item.is_a?(deprecated_directive) }&.args&.reason
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# The introspection object for a input object
|
7
|
+
class Object::InputValueObject < Object
|
8
|
+
self.assigned_to = 'Rails::GraphQL::Field::InputField'
|
9
|
+
self.spec_object = true
|
10
|
+
|
11
|
+
def self.valid_member?(value)
|
12
|
+
value.is_a?(GraphQL::Argument) || super
|
13
|
+
end
|
14
|
+
|
15
|
+
delegate :fake_type_object, to: 'Object::TypeObject'
|
16
|
+
|
17
|
+
rename! '__InputValue'
|
18
|
+
|
19
|
+
desc <<~DESC
|
20
|
+
Alongside with scalars and enums, input value objects allow the user
|
21
|
+
to provide values to arguments on fields and directives. Different
|
22
|
+
from those, input values accepts a list of keyed values, instead of
|
23
|
+
a single value.
|
24
|
+
DESC
|
25
|
+
|
26
|
+
field :name, :string, null: false, method_name: :gql_name
|
27
|
+
field :description, :string
|
28
|
+
field :type, '__Type', null: false, method_name: :build_type
|
29
|
+
field :default_value, :string
|
30
|
+
|
31
|
+
def default_value
|
32
|
+
current.to_json if current.default_value?
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_type
|
36
|
+
result = current.type_klass
|
37
|
+
|
38
|
+
if current.array?
|
39
|
+
result = fake_type_object(:non_null, result) unless current.nullable?
|
40
|
+
result = fake_type_object(:list, result)
|
41
|
+
end
|
42
|
+
|
43
|
+
result = fake_type_object(:non_null, result) unless current.null?
|
44
|
+
result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# The introspection object for a schema object
|
7
|
+
class Object::SchemaObject < Object
|
8
|
+
self.assigned_to = 'Rails::GraphQL::Schema'
|
9
|
+
self.spec_object = true
|
10
|
+
|
11
|
+
rename! '__Schema'
|
12
|
+
|
13
|
+
desc <<~DESC
|
14
|
+
A GraphQL service’s collective type system capabilities are referred
|
15
|
+
to as that service’s "schema". A schema is defined in terms of the
|
16
|
+
types and directives it supports as well as the root operation types
|
17
|
+
for each kind of operation: query, mutation, and subscription; this
|
18
|
+
determines the place in the type system where those operations begin.
|
19
|
+
DESC
|
20
|
+
|
21
|
+
field :types, '__Type', full: true, method_name: :read_types
|
22
|
+
field :query_type, '__Type', null: false
|
23
|
+
field :mutation_type, '__Type'
|
24
|
+
field :subscription_type, '__Type'
|
25
|
+
field :directives, '__Directive', full: true, method_name: :read_directives
|
26
|
+
|
27
|
+
# TODO: make it work for lazy enumerator
|
28
|
+
def read_types
|
29
|
+
event.schema.types(base_class: :Type).force
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: it only works after eager_load!
|
33
|
+
def read_directives
|
34
|
+
Directive.eager_load!
|
35
|
+
event.schema.types(base_class: :Directive).force
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails # :nodoc:
|
4
|
+
module GraphQL # :nodoc:
|
5
|
+
class Type # :nodoc:
|
6
|
+
# The introspection object for any kind of type
|
7
|
+
class Object::TypeObject < Object
|
8
|
+
FAKE_TYPES = {
|
9
|
+
list: {
|
10
|
+
kind: :list,
|
11
|
+
kind_enum: 'LIST',
|
12
|
+
name: 'List',
|
13
|
+
object?: true,
|
14
|
+
description: nil,
|
15
|
+
},
|
16
|
+
non_null: {
|
17
|
+
kind: :non_null,
|
18
|
+
kind_enum: 'NON_NULL',
|
19
|
+
name: 'Non-Null',
|
20
|
+
object?: true,
|
21
|
+
description: nil,
|
22
|
+
},
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
self.assigned_to = 'Rails::GraphQL::Type'
|
26
|
+
self.spec_object = true
|
27
|
+
|
28
|
+
def self.valid_member?(value)
|
29
|
+
value.is_a?(OpenStruct) ? value.try(:object?) : super
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.fake_type_object(type, subtype)
|
33
|
+
OpenStruct.new(**FAKE_TYPES[type].merge(of_type: subtype))
|
34
|
+
end
|
35
|
+
|
36
|
+
rename! '__Type'
|
37
|
+
|
38
|
+
desc <<~DESC
|
39
|
+
The fundamental unit of any GraphQL Schema is the type. There are six
|
40
|
+
kinds of named type definitions in GraphQL, and two wrapping types.
|
41
|
+
|
42
|
+
The most basic type is a +Scalar+. A scalar represents a primitive value,
|
43
|
+
like a string or an integer.
|
44
|
+
|
45
|
+
+Scalars+ and +Enums+ form the leaves in response trees; the intermediate
|
46
|
+
levels are +Object+ types, which define a set of fields.
|
47
|
+
|
48
|
+
An +Interface+ defines a list of fields; +Object+ types that implement
|
49
|
+
that interface are guaranteed to implement those fields.
|
50
|
+
|
51
|
+
A +Union+ defines a list of possible types; similar to interfaces,
|
52
|
+
whenever the type system claims a union will be returned, one of the
|
53
|
+
possible types will be returned.
|
54
|
+
|
55
|
+
Finally, oftentimes it is useful to provide complex structs as inputs
|
56
|
+
to GraphQL field arguments or variables; the +Input Object+ type allows
|
57
|
+
the schema to define exactly what data is expected.
|
58
|
+
DESC
|
59
|
+
|
60
|
+
field :kind, '__TypeKind', null: false,
|
61
|
+
method_name: :kind_enum
|
62
|
+
|
63
|
+
field :name, :string,
|
64
|
+
method_name: :gql_name
|
65
|
+
|
66
|
+
field :description, :string
|
67
|
+
|
68
|
+
field :fields, '__Field', array: true, nullable: false do
|
69
|
+
desc 'OBJECT and INTERFACE only'
|
70
|
+
argument :include_deprecated, :boolean, default: false
|
71
|
+
end
|
72
|
+
|
73
|
+
field :interfaces, '__Type', array: true, nullable: false,
|
74
|
+
desc: 'OBJECT only'
|
75
|
+
|
76
|
+
field :possible_types, '__Type', array: true, nullable: false,
|
77
|
+
desc: 'INTERFACE and UNION only'
|
78
|
+
|
79
|
+
field :enum_values, '__EnumValue', array: true, nullable: false do
|
80
|
+
desc 'ENUM only'
|
81
|
+
argument :include_deprecated, :boolean, default: false
|
82
|
+
end
|
83
|
+
|
84
|
+
field :input_fields, '__InputValue', array: true, nullable: false,
|
85
|
+
desc: 'INPUT_OBJECT only'
|
86
|
+
|
87
|
+
field :of_type, '__Type',
|
88
|
+
desc: 'NON_NULL and LIST only'
|
89
|
+
|
90
|
+
def fields(include_deprecated:)
|
91
|
+
return [] unless current.object? || current.interface?
|
92
|
+
|
93
|
+
list = current.fields.enum_for(:each_value)
|
94
|
+
list = list.reject { |field| field.using?(deprecated_directive) } \
|
95
|
+
unless include_deprecated
|
96
|
+
|
97
|
+
list
|
98
|
+
end
|
99
|
+
|
100
|
+
def enum_values(include_deprecated:)
|
101
|
+
return [] unless current.enum?
|
102
|
+
|
103
|
+
descs = all_value_description
|
104
|
+
deprecated = all_deprecated_values
|
105
|
+
|
106
|
+
list = all_values.lazy
|
107
|
+
list = list.reject { |value| deprecated.key?(value) } \
|
108
|
+
unless include_deprecated
|
109
|
+
|
110
|
+
list.map do |value|
|
111
|
+
OpenStruct.new(
|
112
|
+
name: value,
|
113
|
+
description: descs[value],
|
114
|
+
is_deprecated: deprecated.key?(value),
|
115
|
+
deprecation_reason: deprecated[value],
|
116
|
+
)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def interfaces
|
121
|
+
return [] unless current.object?
|
122
|
+
current.all_interfaces || []
|
123
|
+
end
|
124
|
+
|
125
|
+
def possible_types
|
126
|
+
return all_types if current.interface?
|
127
|
+
current.union? ? all_members : []
|
128
|
+
end
|
129
|
+
|
130
|
+
def input_fields
|
131
|
+
current.input? ? current.fields.enum_for(:each_value) : []
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|