rails-graphql 0.2.1 → 1.0.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/console.rb +18 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +1 -54
- data/ext/gql_parser.c +646 -0
- data/ext/shared.c +482 -0
- data/ext/shared.h +177 -0
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
- data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
- data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
- data/lib/rails/graphql/alternative/field_set.rb +36 -0
- data/lib/rails/graphql/alternative/mutation.rb +17 -0
- data/lib/rails/graphql/alternative/query.rb +93 -0
- data/lib/rails/graphql/alternative/subscription.rb +17 -0
- data/lib/rails/graphql/alternative.rb +20 -0
- data/lib/rails/graphql/argument.rb +21 -24
- data/lib/rails/graphql/callback.rb +24 -9
- data/lib/rails/graphql/collectors/hash_collector.rb +14 -6
- data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
- data/lib/rails/graphql/collectors/json_collector.rb +22 -17
- data/lib/rails/graphql/collectors.rb +4 -4
- data/lib/rails/graphql/config.rb +130 -15
- data/lib/rails/graphql/directive/cached_directive.rb +33 -0
- data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
- data/lib/rails/graphql/directive/include_directive.rb +5 -4
- data/lib/rails/graphql/directive/skip_directive.rb +5 -4
- data/lib/rails/graphql/directive.rb +118 -63
- data/lib/rails/graphql/errors.rb +33 -4
- data/lib/rails/graphql/event.rb +16 -5
- data/lib/rails/graphql/field/authorized_field.rb +19 -3
- data/lib/rails/graphql/field/input_field.rb +11 -10
- data/lib/rails/graphql/field/mutation_field.rb +42 -7
- data/lib/rails/graphql/field/output_field.rb +102 -13
- data/lib/rails/graphql/field/proxied_field.rb +31 -22
- data/lib/rails/graphql/field/resolved_field.rb +26 -24
- data/lib/rails/graphql/field/scoped_config.rb +10 -4
- data/lib/rails/graphql/field/subscription_field.rb +140 -0
- data/lib/rails/graphql/field/typed_field.rb +43 -22
- data/lib/rails/graphql/field.rb +70 -56
- data/lib/rails/graphql/global_id.rb +85 -0
- data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +50 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +43 -0
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +87 -0
- data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
- data/lib/rails/graphql/helpers/instantiable.rb +15 -0
- data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
- data/lib/rails/graphql/helpers/registerable.rb +44 -62
- data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
- data/lib/rails/graphql/helpers/with_arguments.rb +31 -27
- data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
- data/lib/rails/graphql/helpers/with_callbacks.rb +25 -8
- data/lib/rails/graphql/helpers/with_description.rb +71 -0
- data/lib/rails/graphql/helpers/with_directives.rb +54 -30
- data/lib/rails/graphql/helpers/with_events.rb +21 -23
- data/lib/rails/graphql/helpers/with_fields.rb +76 -22
- data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
- data/lib/rails/graphql/helpers/with_name.rb +43 -0
- data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
- data/lib/rails/graphql/helpers/with_owner.rb +8 -7
- data/lib/rails/graphql/helpers/with_schema_fields.rb +137 -55
- data/lib/rails/graphql/helpers/with_validator.rb +9 -9
- data/lib/rails/graphql/helpers.rb +10 -3
- data/lib/rails/graphql/introspection.rb +43 -36
- data/lib/rails/graphql/railtie.rb +88 -33
- data/lib/rails/graphql/railties/base_generator.rb +3 -9
- data/lib/rails/graphql/railties/channel.rb +157 -0
- data/lib/rails/graphql/railties/controller.rb +62 -17
- data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
- data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
- data/lib/rails/graphql/request/arguments.rb +24 -49
- data/lib/rails/graphql/request/backtrace.rb +191 -0
- data/lib/rails/graphql/request/component/field.rb +86 -65
- data/lib/rails/graphql/request/component/fragment.rb +72 -24
- data/lib/rails/graphql/request/component/operation/subscription.rb +164 -4
- data/lib/rails/graphql/request/component/operation.rb +63 -31
- data/lib/rails/graphql/request/component/spread.rb +68 -25
- data/lib/rails/graphql/request/component/typename.rb +27 -12
- data/lib/rails/graphql/request/component.rb +75 -36
- data/lib/rails/graphql/request/context.rb +18 -8
- data/lib/rails/graphql/request/errors.rb +16 -6
- data/lib/rails/graphql/request/event.rb +19 -8
- data/lib/rails/graphql/request/helpers/directives.rb +68 -27
- data/lib/rails/graphql/request/helpers/selection_set.rb +51 -25
- data/lib/rails/graphql/request/helpers/value_writers.rb +18 -16
- data/lib/rails/graphql/request/prepared_data.rb +98 -0
- data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
- data/lib/rails/graphql/request/steps/organizable.rb +110 -48
- data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +20 -7
- data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +15 -6
- data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
- data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
- data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
- data/lib/rails/graphql/request/strategy.rb +131 -75
- data/lib/rails/graphql/request/subscription.rb +80 -0
- data/lib/rails/graphql/request.rb +305 -86
- data/lib/rails/graphql/schema.rb +240 -48
- data/lib/rails/graphql/shortcuts.rb +22 -3
- data/lib/rails/graphql/source/active_record/builders.rb +49 -35
- data/lib/rails/graphql/source/active_record_source.rb +70 -54
- data/lib/rails/graphql/source/base.rb +111 -0
- data/lib/rails/graphql/source/builder.rb +128 -0
- data/lib/rails/graphql/source/scoped_arguments.rb +31 -19
- data/lib/rails/graphql/source.rb +89 -213
- data/lib/rails/graphql/subscription/provider/action_cable.rb +112 -0
- data/lib/rails/graphql/subscription/provider/base.rb +191 -0
- data/lib/rails/graphql/subscription/provider.rb +18 -0
- data/lib/rails/graphql/subscription/store/base.rb +145 -0
- data/lib/rails/graphql/subscription/store/memory.rb +127 -0
- data/lib/rails/graphql/subscription/store.rb +19 -0
- data/lib/rails/graphql/subscription.rb +17 -0
- data/lib/rails/graphql/to_gql.rb +29 -32
- data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
- data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
- data/lib/rails/graphql/type/enum.rb +34 -48
- data/lib/rails/graphql/type/input.rb +74 -23
- data/lib/rails/graphql/type/interface.rb +16 -26
- data/lib/rails/graphql/type/object/directive_object.rb +4 -4
- data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
- data/lib/rails/graphql/type/object/field_object.rb +24 -6
- data/lib/rails/graphql/type/object/input_value_object.rb +3 -3
- data/lib/rails/graphql/type/object/schema_object.rb +5 -8
- data/lib/rails/graphql/type/object/type_object.rb +29 -19
- data/lib/rails/graphql/type/object.rb +26 -23
- data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
- data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
- data/lib/rails/graphql/type/scalar/date_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/json_scalar.rb +39 -0
- data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
- data/lib/rails/graphql/type/scalar/time_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar.rb +25 -22
- data/lib/rails/graphql/type/union.rb +14 -16
- data/lib/rails/graphql/type.rb +34 -25
- data/lib/rails/graphql/type_map.rb +256 -164
- data/lib/rails/graphql/uri.rb +166 -0
- data/lib/rails/graphql/version.rb +15 -3
- data/lib/rails/graphql.rake +3 -0
- data/lib/rails/graphql.rb +85 -52
- data/lib/rails-graphql.rb +1 -1
- data/test/assets/en.yml +29 -0
- data/test/assets/introspection-mem.txt +1 -1
- data/test/assets/mem.gql +18 -45
- data/test/assets/mysql.gql +392 -0
- data/test/assets/sqlite.gql +21 -12
- data/test/assets/translate.gql +335 -0
- data/test/config.rb +18 -8
- data/test/graphql/schema_test.rb +12 -19
- data/test/graphql/source_test.rb +8 -75
- data/test/graphql/type/enum_test.rb +207 -203
- data/test/graphql/type/input_test.rb +14 -9
- data/test/graphql/type/interface_test.rb +4 -4
- data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
- data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
- data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
- data/test/graphql/type_map_test.rb +51 -66
- data/test/graphql/type_test.rb +0 -19
- data/test/graphql_test.rb +1 -1
- data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
- data/test/integration/config.rb +36 -3
- data/test/integration/customization_test.rb +39 -0
- data/test/integration/global_id_test.rb +99 -0
- data/test/integration/memory/star_wars_introspection_test.rb +24 -16
- data/test/integration/memory/star_wars_query_test.rb +54 -3
- data/test/integration/memory/star_wars_validation_test.rb +1 -1
- data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
- data/test/integration/persisted_query_test.rb +87 -0
- data/test/integration/resolver_precedence_test.rb +154 -0
- data/test/integration/schemas/memory.rb +22 -7
- data/test/integration/schemas/mysql.rb +62 -0
- data/test/integration/schemas/sqlite.rb +21 -12
- data/test/integration/sqlite/star_wars_global_id_test.rb +83 -0
- data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
- data/test/integration/sqlite/star_wars_query_test.rb +14 -1
- data/test/integration/translate_test.rb +61 -0
- data/test/test_ext.rb +16 -13
- metadata +108 -157
- data/ext/depend +0 -3
- data/ext/graphqlparser/Ast.cpp +0 -346
- data/ext/graphqlparser/Ast.h +0 -1214
- data/ext/graphqlparser/AstNode.h +0 -36
- data/ext/graphqlparser/AstVisitor.h +0 -137
- data/ext/graphqlparser/GraphQLParser.cpp +0 -76
- data/ext/graphqlparser/GraphQLParser.h +0 -55
- data/ext/graphqlparser/JsonVisitor.cpp +0 -161
- data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
- data/ext/graphqlparser/JsonVisitor.h +0 -121
- data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
- data/ext/graphqlparser/VERSION +0 -1
- data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
- data/ext/graphqlparser/c/GraphQLAst.h +0 -180
- data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
- data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/graphqlparser/c/GraphQLParser.h +0 -54
- data/ext/graphqlparser/dump_json_ast.cpp +0 -48
- data/ext/graphqlparser/lexer.lpp +0 -324
- data/ext/graphqlparser/parser.ypp +0 -693
- data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/graphqlparser/parsergen/lexer.h +0 -528
- data/ext/graphqlparser/parsergen/location.hh +0 -189
- data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/graphqlparser/parsergen/position.hh +0 -179
- data/ext/graphqlparser/parsergen/stack.hh +0 -156
- data/ext/graphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/AstNode.h +0 -36
- data/ext/libgraphqlparser/CMakeLists.txt +0 -148
- data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
- data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
- data/ext/libgraphqlparser/GraphQLParser.h +0 -55
- data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
- data/ext/libgraphqlparser/JsonVisitor.h +0 -121
- data/ext/libgraphqlparser/LICENSE +0 -22
- data/ext/libgraphqlparser/README.clang-tidy +0 -7
- data/ext/libgraphqlparser/README.md +0 -84
- data/ext/libgraphqlparser/ast/ast.ast +0 -203
- data/ext/libgraphqlparser/ast/ast.py +0 -61
- data/ext/libgraphqlparser/ast/c.py +0 -100
- data/ext/libgraphqlparser/ast/c.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_impl.py +0 -61
- data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
- data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/casing.py +0 -26
- data/ext/libgraphqlparser/ast/casing.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx.py +0 -197
- data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
- data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
- data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
- data/ext/libgraphqlparser/ast/js.py +0 -65
- data/ext/libgraphqlparser/ast/license.py +0 -10
- data/ext/libgraphqlparser/ast/license.pyc +0 -0
- data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
- data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
- data/ext/libgraphqlparser/cmake/version.cmake +0 -16
- data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
- data/ext/libgraphqlparser/go/README.md +0 -20
- data/ext/libgraphqlparser/go/callbacks.go +0 -18
- data/ext/libgraphqlparser/go/gotest.go +0 -64
- data/ext/libgraphqlparser/lexer.lpp +0 -324
- data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
- data/ext/libgraphqlparser/parser.ypp +0 -693
- data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
- data/ext/libgraphqlparser/parsergen/location.hh +0 -189
- data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/libgraphqlparser/parsergen/position.hh +0 -179
- data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
- data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
- data/ext/libgraphqlparser/python/README.md +0 -5
- data/ext/libgraphqlparser/python/example.py +0 -31
- data/ext/libgraphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
- data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
- data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
- data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
- data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
- data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
- data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/valgrind.supp +0 -33
- data/ext/version.cpp +0 -21
- data/lib/graphqlparser.so +0 -0
- data/lib/rails/graphql/native/functions.rb +0 -38
- data/lib/rails/graphql/native/location.rb +0 -41
- data/lib/rails/graphql/native/pointers.rb +0 -23
- data/lib/rails/graphql/native/visitor.rb +0 -349
- data/lib/rails/graphql/native.rb +0 -56
- data/test/integration/schemas/authorization.rb +0 -12
@@ -1,80 +1,104 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
class Request
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
class Request
|
6
6
|
# = GraphQL Request Component
|
7
7
|
#
|
8
8
|
# Component is an abstraction of any possible type of object represented
|
9
9
|
# by a not of the document of a request. This class helps building
|
10
10
|
# cross-component features, like holding event listeners, setting up
|
11
|
-
#
|
11
|
+
# common initializer and providing helpers
|
12
12
|
class Component
|
13
13
|
extend ActiveSupport::Autoload
|
14
14
|
|
15
15
|
include Request::Organizable
|
16
|
-
include Request::
|
17
|
-
include Request::
|
16
|
+
include Request::Preparable
|
17
|
+
include Request::Resolvable
|
18
18
|
|
19
19
|
class << self
|
20
20
|
# Return the kind of the component
|
21
21
|
def kind
|
22
22
|
@kind ||= name.demodulize.underscore.to_sym
|
23
23
|
end
|
24
|
-
|
25
|
-
# Helper to memoize results from parent delegation
|
26
|
-
def parent_memoize(*methods)
|
27
|
-
methods.each do |method_name|
|
28
|
-
define_method(method_name) do
|
29
|
-
result = parent.public_send(method_name)
|
30
|
-
define_singleton_method(method_name) { result }
|
31
|
-
result
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
24
|
end
|
36
25
|
|
37
|
-
|
38
|
-
|
39
|
-
delegate :schema, :visitor, :response, :strategy, to: :request
|
26
|
+
delegate :visitor, :response, :strategy, to: :request
|
40
27
|
delegate :find_type!, :find_directive!, :trigger_event, to: :strategy
|
41
|
-
delegate :memo, to: :operation
|
28
|
+
delegate :memo, :schema, to: :operation
|
42
29
|
delegate :kind, to: :class
|
43
30
|
|
44
31
|
alias of_type? is_a?
|
45
32
|
|
46
33
|
eager_autoload do
|
47
34
|
autoload :Field
|
48
|
-
autoload :Fragment
|
49
35
|
autoload :Operation
|
50
|
-
autoload :Spread
|
51
|
-
autoload :Typename
|
52
36
|
end
|
53
37
|
|
54
|
-
|
38
|
+
autoload :Fragment
|
39
|
+
autoload :Spread
|
40
|
+
autoload :Typename
|
41
|
+
|
42
|
+
def initialize(node)
|
55
43
|
@node = node
|
56
|
-
@data = data
|
57
44
|
end
|
58
45
|
|
59
46
|
# Check if the component is in a invalid state
|
60
47
|
def invalid?
|
61
|
-
defined?(@invalid) && @invalid
|
48
|
+
defined?(@invalid) && @invalid.present?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Check if the component is marked as skipped
|
52
|
+
def skipped?
|
53
|
+
defined?(@skipped) && @skipped
|
54
|
+
end
|
55
|
+
|
56
|
+
# Just a fancy name for invalid or skipped
|
57
|
+
def unresolvable?
|
58
|
+
invalid? || skipped?
|
62
59
|
end
|
63
60
|
|
64
61
|
# Mark the component as invalid
|
65
|
-
def invalidate!
|
66
|
-
@invalid =
|
62
|
+
def invalidate!(type = true)
|
63
|
+
@invalid = type
|
64
|
+
end
|
65
|
+
|
66
|
+
# Skip the component
|
67
|
+
def skip!
|
68
|
+
@skipped = true
|
67
69
|
end
|
68
70
|
|
69
|
-
#
|
71
|
+
# Normally, components are not assignable, only fields are
|
70
72
|
def assignable?
|
71
73
|
false
|
72
74
|
end
|
73
75
|
|
76
|
+
# Get an identifier of the component
|
77
|
+
def hash
|
78
|
+
@node.hash
|
79
|
+
end
|
80
|
+
|
81
|
+
# Build the cache object
|
82
|
+
def cache_dump
|
83
|
+
hash = { node: @node }
|
84
|
+
hash[:invalid] = @invalid if defined?(@invalid) && @invalid != :authorization
|
85
|
+
hash[:skipped] = @skipped if defined?(@skipped) && @skipped
|
86
|
+
hash.merge!(super)
|
87
|
+
hash
|
88
|
+
end
|
89
|
+
|
90
|
+
# Organize from cache data
|
91
|
+
def cache_load(data)
|
92
|
+
@node = data[:node]
|
93
|
+
@invalid = data[:invalid] if data.key?(:invalid)
|
94
|
+
@skipped = data[:skipped] if data.key?(:skipped)
|
95
|
+
super
|
96
|
+
end
|
97
|
+
|
74
98
|
protected
|
75
99
|
|
76
100
|
# It's extremely important to have a way to access the current request
|
77
|
-
# since not all objects stores
|
101
|
+
# since not all objects stores a direct pointer to it
|
78
102
|
def request
|
79
103
|
raise NotImplementedError
|
80
104
|
end
|
@@ -86,13 +110,28 @@ module Rails # :nodoc:
|
|
86
110
|
|
87
111
|
# Run a given block and ensure to capture exceptions to set them as
|
88
112
|
# errors
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
invalidate! if invalidate
|
113
|
+
def report_exception(error)
|
114
|
+
Backtrace.print(error, self, request)
|
115
|
+
|
93
116
|
stack_path = request.stack_to_path
|
94
117
|
stack_path << gql_name if respond_to?(:gql_name) && gql_name.present?
|
95
|
-
request.exception_to_error(error,
|
118
|
+
request.exception_to_error(error, self, path: stack_path, stage: strategy.stage.to_s)
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# Properly transform values to string gid
|
124
|
+
def all_to_gid(enum)
|
125
|
+
(enum.is_a?(Enumerable) ? enum : enum.then).each do |item|
|
126
|
+
item.to_gid.to_s
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Properly recover values from gid string
|
131
|
+
def all_from_gid(enum)
|
132
|
+
(enum.is_a?(Enumerable) ? enum : enum.then).each do |item|
|
133
|
+
GraphQL::GlobalID.find(item)
|
134
|
+
end
|
96
135
|
end
|
97
136
|
end
|
98
137
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
class Request
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
class Request
|
6
6
|
# = GraphQL Request Context
|
7
7
|
#
|
8
8
|
# This class is used as context for the response while processing fields,
|
@@ -23,9 +23,14 @@ module Rails # :nodoc:
|
|
23
23
|
@stack.shift
|
24
24
|
end
|
25
25
|
|
26
|
-
#
|
27
|
-
def
|
28
|
-
@stack
|
26
|
+
# Return a duplicated version of the stack, for safety
|
27
|
+
def stack
|
28
|
+
@stack.dup
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get a value at the given +index+
|
32
|
+
def at(index)
|
33
|
+
@stack[index]
|
29
34
|
end
|
30
35
|
|
31
36
|
# Get all ancestors objects
|
@@ -33,10 +38,15 @@ module Rails # :nodoc:
|
|
33
38
|
@stack[1..-1]
|
34
39
|
end
|
35
40
|
|
41
|
+
# Find the parent object
|
42
|
+
def parent
|
43
|
+
at(1)
|
44
|
+
end
|
45
|
+
|
36
46
|
# Get the current value, which basically means basically the first item
|
37
|
-
# on the current
|
47
|
+
# on the current stack
|
38
48
|
def current_value
|
39
|
-
|
49
|
+
at(0)
|
40
50
|
end
|
41
51
|
|
42
52
|
# Change the current value, either form hits or the actual value
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
class Request
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
class Request
|
6
6
|
# = GraphQL Request Errors
|
7
7
|
#
|
8
|
-
# This class is inspired by +ActiveModel::
|
8
|
+
# This class is inspired by +ActiveModel::Errors+. The idea is to hold all
|
9
9
|
# the errors that happened during the execution of a request. It also
|
10
10
|
# helps to export such information to the result object.
|
11
11
|
class Errors
|
@@ -27,7 +27,7 @@ module Rails # :nodoc:
|
|
27
27
|
@items.deep_dup
|
28
28
|
end
|
29
29
|
|
30
|
-
# Add +message+ to the list of errors. Any other
|
30
|
+
# Add +message+ to the list of errors. Any other keyword argument will
|
31
31
|
# be used on set on the +:extensions+ part.
|
32
32
|
#
|
33
33
|
# ==== Options
|
@@ -42,12 +42,22 @@ module Rails # :nodoc:
|
|
42
42
|
item['locations'] ||= [{ line: line.to_i, column: col.to_i }] \
|
43
43
|
if line.present? && col.present?
|
44
44
|
|
45
|
-
item['path'] = path if path.present? && path.is_a?(Array)
|
45
|
+
item['path'] = path if path.present? && path.is_a?(::Array)
|
46
46
|
item['extensions'] = extra.deep_stringify_keys if extra.present?
|
47
47
|
item['locations']&.map!(&:stringify_keys)
|
48
48
|
|
49
49
|
@items << item.compact
|
50
50
|
end
|
51
|
+
|
52
|
+
# Dump the necessary information from errors to a cached operation
|
53
|
+
def cache_dump
|
54
|
+
@items.select { |item| item.dig('extensions', 'stage') == 'organize' }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Load the necessary information from a cached request data
|
58
|
+
def cache_load(data)
|
59
|
+
@items += data
|
60
|
+
end
|
51
61
|
end
|
52
62
|
end
|
53
63
|
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
class Request
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
class Request
|
6
6
|
# = GraphQL Request Event
|
7
7
|
#
|
8
8
|
# A small extension of the original event to support extra methods and
|
9
9
|
# helpers when performing events during a request
|
10
10
|
class Event < GraphQL::Event
|
11
|
-
OBJECT_BASED_READERS = %i[fragment
|
11
|
+
OBJECT_BASED_READERS = %i[fragment spread].freeze
|
12
12
|
|
13
|
-
delegate :
|
13
|
+
delegate :errors, :context, to: :request
|
14
14
|
delegate :instance_for, to: :strategy
|
15
|
-
delegate :memo, to: :source
|
15
|
+
delegate :memo, :schema, to: :source
|
16
|
+
delegate :subscription_field, to: :schema
|
16
17
|
|
17
18
|
attr_reader :strategy, :request, :index
|
18
19
|
|
@@ -33,6 +34,11 @@ module Rails # :nodoc:
|
|
33
34
|
super(name, source, **data)
|
34
35
|
end
|
35
36
|
|
37
|
+
# If the source is a field, than also compare to the actual field
|
38
|
+
def same_source?(other)
|
39
|
+
super || (source.try(:kind) == :field && source.field == other)
|
40
|
+
end
|
41
|
+
|
36
42
|
# Provide a way to access the current field value
|
37
43
|
def current_value
|
38
44
|
resolver&.current_value
|
@@ -45,6 +51,11 @@ module Rails # :nodoc:
|
|
45
51
|
resolver&.override_value(value)
|
46
52
|
end
|
47
53
|
|
54
|
+
# Get the operation for the current source
|
55
|
+
def operation
|
56
|
+
(object.kind == :operation) ? object : source.operation
|
57
|
+
end
|
58
|
+
|
48
59
|
# Return the strategy context as the resolver
|
49
60
|
def resolver
|
50
61
|
strategy.context
|
@@ -52,7 +63,7 @@ module Rails # :nodoc:
|
|
52
63
|
|
53
64
|
# Return the actual field when the source is a request field
|
54
65
|
def field
|
55
|
-
source.field if source.try(:kind)
|
66
|
+
source.field if source.try(:kind) == :field
|
56
67
|
end
|
57
68
|
|
58
69
|
# Check if the event source is of the given +type+
|
@@ -99,7 +110,7 @@ module Rails # :nodoc:
|
|
99
110
|
# it will return the object
|
100
111
|
def method_missing(method_name, *args, **xargs, &block)
|
101
112
|
if OBJECT_BASED_READERS.include?(method_name)
|
102
|
-
object if object.kind
|
113
|
+
object if object.kind == method_name
|
103
114
|
elsif current_value&.respond_to?(method_name)
|
104
115
|
current_value&.public_send(method_name, *args, **xargs, &block)
|
105
116
|
else
|
@@ -1,62 +1,103 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
class Request
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
class Request
|
6
6
|
# Helper module to collect the directives from fragments, operations, and
|
7
7
|
# fields.
|
8
8
|
module Directives
|
9
9
|
# Get the list of listeners from directives set during the request only
|
10
|
-
def
|
11
|
-
|
10
|
+
def directive_listeners
|
11
|
+
return unless directives?
|
12
|
+
return @directive_listeners if defined?(@directive_listeners)
|
13
|
+
@directive_listeners = directives.map(&:all_listeners).compact.reduce(:+)
|
12
14
|
end
|
13
15
|
|
16
|
+
alias all_listeners directive_listeners
|
17
|
+
|
14
18
|
# Get the list of events from directives set during the request only and
|
15
19
|
# then caches it by request
|
16
|
-
def
|
17
|
-
|
18
|
-
|
20
|
+
def directive_events
|
21
|
+
return unless directives?
|
22
|
+
@directive_events ||= begin
|
23
|
+
directives.map(&:all_events).compact.inject({}) do |lhash, rhash|
|
24
|
+
Helpers.merge_hash_array(lhash, rhash)
|
25
|
+
end
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
29
|
+
alias all_events directive_events
|
30
|
+
|
31
|
+
# Check if the current component is using a directive
|
32
|
+
def using?(item)
|
33
|
+
return false unless directives?
|
34
|
+
|
35
|
+
directive = (item.is_a?(Symbol) || item.is_a?(String)) ? find_directive!(item) : item
|
36
|
+
(directive < GraphQL::Directive) && directives.any?(directive)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Build the cache object
|
40
|
+
def cache_dump
|
41
|
+
return super unless defined?(@directives)
|
42
|
+
|
43
|
+
super.merge(directives: all_to_gid(@directives.transform_values))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Organize from cache data
|
47
|
+
def cache_load(data)
|
48
|
+
return super unless data.key?(:directives)
|
49
|
+
|
50
|
+
@directives = all_from_gid(data[:directives].transform_values).freeze
|
51
|
+
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
22
55
|
protected
|
23
56
|
|
24
57
|
# Make sure to always return a set
|
25
58
|
def directives
|
26
|
-
@directives
|
59
|
+
@directives if directives?
|
27
60
|
end
|
28
61
|
|
29
|
-
|
62
|
+
# Check if any execution directive was added
|
63
|
+
def directives?
|
64
|
+
defined?(@directives)
|
65
|
+
end
|
30
66
|
|
31
67
|
# Helper parser for directives that also collect necessary variables
|
32
|
-
def parse_directives(location = nil)
|
33
|
-
|
34
|
-
|
35
|
-
visitor.collect_directives(*data[:directives]) do |data|
|
36
|
-
instance = find_directive!(data[:name])
|
68
|
+
def parse_directives(nodes, location = nil)
|
69
|
+
return if nodes.nil?
|
37
70
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
71
|
+
list = nil
|
72
|
+
nodes.each do |(name, arguments)|
|
73
|
+
instance = find_directive!(name.to_s)
|
74
|
+
values = arguments&.each_with_object({}) do |(name, value, var_name), hash|
|
75
|
+
hash[name.to_s] = var_name.nil? ? value : var_name
|
42
76
|
end
|
43
77
|
|
44
|
-
|
45
|
-
|
78
|
+
args = directive_arguments(instance)
|
79
|
+
args = collect_arguments(args, values)
|
46
80
|
|
47
|
-
|
48
|
-
|
49
|
-
|
81
|
+
(list ||= []) << instance.new(request.build(Request::Arguments, args))
|
82
|
+
rescue ArgumentsError => error
|
83
|
+
raise ArgumentsError, (+<<~MSG).squish
|
84
|
+
Invalid arguments for @#{instance.gql_name} directive
|
85
|
+
added to #{gql_name} #{kind}: #{error.message}.
|
86
|
+
MSG
|
50
87
|
end
|
51
88
|
|
89
|
+
event = Event.new(:attach, strategy, self, phase: :execution)
|
90
|
+
list = GraphQL.directives_to_set(list, [], event, location: location || kind)
|
91
|
+
|
52
92
|
@directives = list.freeze
|
53
93
|
end
|
54
94
|
|
55
95
|
# Get and cache all the arguments for this given +directive+
|
56
96
|
def directive_arguments(directive)
|
57
|
-
request.
|
58
|
-
|
59
|
-
|
97
|
+
request.nested_cache(:arguments, directive) do
|
98
|
+
directive.all_arguments&.each_value&.with_object({}) do |directive, hash|
|
99
|
+
hash[directive.gql_name] = directive
|
100
|
+
end
|
60
101
|
end
|
61
102
|
end
|
62
103
|
end
|
@@ -1,43 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
class Request
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
class Request
|
6
6
|
# Helper module to collect the fields from fragments, operations, and also
|
7
7
|
# other fields.
|
8
8
|
module SelectionSet
|
9
9
|
attr_reader :selection
|
10
10
|
|
11
|
+
# Build the cache object
|
12
|
+
def cache_dump
|
13
|
+
return super unless defined?(@selection)
|
14
|
+
|
15
|
+
selection = @selection.transform_values do |field|
|
16
|
+
field.cache_dump.merge(type: field.class)
|
17
|
+
end
|
18
|
+
|
19
|
+
super.merge(selection: selection)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Organize from cache data
|
23
|
+
def cache_load(data)
|
24
|
+
return super unless data.key?(:selection)
|
25
|
+
|
26
|
+
@selection = data[:selection].transform_values do |data|
|
27
|
+
component = request.build_from_cache(data[:type])
|
28
|
+
component.instance_variable_set(:@parent, self)
|
29
|
+
component.cache_load(data)
|
30
|
+
component
|
31
|
+
end.freeze
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
11
36
|
protected
|
12
37
|
|
13
|
-
# Helper parser for selection fields that also
|
38
|
+
# Helper parser for selection fields that also assign the actual
|
14
39
|
# field defined under the schema structure
|
15
|
-
def parse_selection
|
40
|
+
def parse_selection(nodes)
|
41
|
+
return if nodes.nil?
|
42
|
+
|
16
43
|
@selection = {}
|
17
44
|
assigners = Hash.new { |h, k| h[k] = [] }
|
18
45
|
|
19
|
-
|
20
|
-
component = add_component(
|
21
|
-
assigners[component.name] << component if component.assignable?
|
22
|
-
end
|
46
|
+
nodes.each do |node|
|
47
|
+
component = add_component(node)
|
48
|
+
assigners[component.name.to_s] << component if component.assignable?
|
49
|
+
end
|
23
50
|
|
24
|
-
|
51
|
+
assign_fields!(assigners)
|
25
52
|
@selection.freeze
|
26
53
|
end
|
27
54
|
|
28
55
|
# Using +fields_source+, find the needed ones to be assigned to the
|
29
56
|
# current requested fields. As shown by benchmark, since the index is
|
30
57
|
# based on Symbols, the best way to find +gql_name+ based fields is
|
31
|
-
# through
|
32
|
-
def
|
58
|
+
# through iteration and search. Complexity O(n)
|
59
|
+
def assign_fields!(assigners)
|
33
60
|
pending = assigners.map(&:size).reduce(:+) || 0
|
34
61
|
return if pending.zero?
|
35
62
|
|
36
|
-
fields_source
|
63
|
+
fields_source&.each_value do |field|
|
37
64
|
next unless assigners.key?(field.gql_name)
|
38
65
|
|
39
66
|
items = assigners[field.gql_name]
|
40
|
-
items.each_with_object(field).each(&:
|
67
|
+
items.each_with_object(field).each(&:assign_to)
|
41
68
|
break if (pending -= items.size) === 0
|
42
69
|
end
|
43
70
|
end
|
@@ -45,20 +72,19 @@ module Rails # :nodoc:
|
|
45
72
|
# Recursive operation that perform the organization step for the
|
46
73
|
# selection
|
47
74
|
def organize_fields
|
48
|
-
selection.each_value(&:organize!) if selection.
|
75
|
+
selection.each_value(&:organize!) if selection.present?
|
49
76
|
end
|
50
77
|
|
51
78
|
# Find all the fields that have a prepare step and execute them
|
52
79
|
def prepare_fields
|
53
|
-
|
54
|
-
(strategy.listeners[:prepare] & selection.values).each(&:prepare!)
|
80
|
+
selection.each_value(&:prepare!) if selection.present?
|
55
81
|
end
|
56
82
|
|
57
83
|
# Trigger the process of resolving the value of all the fields. Since
|
58
84
|
# complex object may or may not be inside an array, this helps to
|
59
85
|
# decide if a new stack should be started or not
|
60
86
|
def resolve_fields(object = nil)
|
61
|
-
return unless selection.
|
87
|
+
return unless selection.present?
|
62
88
|
|
63
89
|
items = selection.each_value
|
64
90
|
items = items.each_with_object(object) unless object.nil?
|
@@ -70,15 +96,15 @@ module Rails # :nodoc:
|
|
70
96
|
|
71
97
|
private
|
72
98
|
|
73
|
-
def add_component(
|
74
|
-
item_name =
|
99
|
+
def add_component(node)
|
100
|
+
item_name = node[1] || node[0]
|
75
101
|
|
76
|
-
if
|
77
|
-
selection[selection.size] = request.build(Component::Spread, self, node
|
78
|
-
elsif
|
79
|
-
selection[item_name] ||= request.build(Component::Typename, self, node
|
102
|
+
if node.of_type?(:spread)
|
103
|
+
selection[selection.size] = request.build(Component::Spread, self, node)
|
104
|
+
elsif node[0] === '__typename'
|
105
|
+
selection[item_name] ||= request.build(Component::Typename, self, node)
|
80
106
|
else
|
81
|
-
selection[item_name] ||= request.build(Component::Field, self, node
|
107
|
+
selection[item_name] ||= request.build(Component::Field, self, node)
|
82
108
|
end
|
83
109
|
end
|
84
110
|
end
|