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,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
|