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,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
5
|
# = GraphQL Base Generator
|
6
6
|
#
|
7
7
|
# A module to help generators to operate
|
@@ -22,13 +22,7 @@ module Rails # :nodoc:
|
|
22
22
|
|
23
23
|
def app_module_name
|
24
24
|
require File.expand_path('config/application', destination_root)
|
25
|
-
|
26
|
-
app_class = Rails.application.class
|
27
|
-
source_name = app_class.respond_to?(:module_parent_name) \
|
28
|
-
? :module_parent_name \
|
29
|
-
: :parent_name
|
30
|
-
|
31
|
-
app_class.send(source_name)
|
25
|
+
Rails.application.class.name.chomp('::Application')
|
32
26
|
end
|
33
27
|
end
|
34
28
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
# = GraphQL Channel
|
6
|
+
#
|
7
|
+
# The channel helper methods that allow GraphQL to be performed on an
|
8
|
+
# Action Cable channel. It also provides structure fro working with
|
9
|
+
# subscriptions
|
10
|
+
module Channel
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
# Each channel is assigned to a GraphQL schema on which the requests
|
15
|
+
# will be performed from. It can be a string or the class
|
16
|
+
class_attribute :gql_schema, instance_accessor: false
|
17
|
+
|
18
|
+
# Set it up a callback after unsubscribed so that all the subscriptions
|
19
|
+
# can be properly unsubscribed
|
20
|
+
after_unsubscribe :gql_clear_subscriptions
|
21
|
+
end
|
22
|
+
|
23
|
+
# The default action of the helper to perform GraphQL requests. Any other
|
24
|
+
# action cab be added and use the granular methods here provided
|
25
|
+
def execute(data)
|
26
|
+
transmit(gql_request_response(data))
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
# Identifies if the received request within +data+ should be threated as
|
32
|
+
# a compiled request
|
33
|
+
def gql_compiled_request?(*)
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get the response of a request withing the given +data+
|
38
|
+
def gql_request_response(data)
|
39
|
+
xargs = gql_params(data)
|
40
|
+
schema, context, query = xargs.extract!(:schema, :context, :query).values
|
41
|
+
|
42
|
+
request = gql_request(schema)
|
43
|
+
request.context = context
|
44
|
+
request.execute(query, **xargs)
|
45
|
+
|
46
|
+
gql_merge_subscriptions(request)
|
47
|
+
gql_response(request)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Merge the subscriptions in this channel and the ones that were added
|
51
|
+
# by the last request
|
52
|
+
def gql_merge_subscriptions(request)
|
53
|
+
gql_subscriptions.merge!(request.subscriptions)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Properly format the response of the provided +request+ so it can be
|
57
|
+
# transmitted
|
58
|
+
def gql_response(request)
|
59
|
+
{ result: request.response.as_json, more: request.subscriptions? }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Build the necessary params from the provided data
|
63
|
+
def gql_params(data)
|
64
|
+
cache_key = gql_query_cache_key(
|
65
|
+
data['query_cache_key'],
|
66
|
+
data['query_cache_version'],
|
67
|
+
)
|
68
|
+
|
69
|
+
{
|
70
|
+
query: data['query'],
|
71
|
+
origin: self,
|
72
|
+
variables: gql_variables(data),
|
73
|
+
operation_name: data['operation_name'] || data['operationName'],
|
74
|
+
compiled: gql_compiled_request?(data),
|
75
|
+
context: gql_context(data),
|
76
|
+
schema: gql_schema(data),
|
77
|
+
hash: cache_key,
|
78
|
+
as: :hash,
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
# The list of ids of subscription and to which field they are
|
83
|
+
# associated with
|
84
|
+
def gql_subscriptions
|
85
|
+
@gql_subscriptions ||= {}
|
86
|
+
end
|
87
|
+
|
88
|
+
# The instance of a GraphQL request. It can't simply perform using
|
89
|
+
# +execute+, because it is important to check if any subscription was
|
90
|
+
# generated
|
91
|
+
def gql_request(schema = gql_schema)
|
92
|
+
@gql_request ||= ::Rails::GraphQL::Request.new(schema)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get the cache key of the query for persisted queries
|
96
|
+
def gql_query_cache_key(key = nil, version = nil)
|
97
|
+
CacheKey.new(key, version) if key.present?
|
98
|
+
end
|
99
|
+
|
100
|
+
# The schema on which the requests will be performed from
|
101
|
+
def gql_schema(*)
|
102
|
+
schema = self.class.gql_schema
|
103
|
+
schema = schema.constantize if schema.is_a?(String)
|
104
|
+
schema ||= gql_application_default_schema
|
105
|
+
return schema if schema.is_a?(Module) && schema < ::Rails::GraphQL::Schema
|
106
|
+
|
107
|
+
raise ExecutionError, (+<<~MSG).squish
|
108
|
+
Unable to find a valid schema for #{self.class.name},
|
109
|
+
defined value: #{schema.inspect}.
|
110
|
+
MSG
|
111
|
+
end
|
112
|
+
|
113
|
+
# Get the GraphQL context for a requests
|
114
|
+
# +ActionCable::Channel::Base#extract_action+
|
115
|
+
def gql_context(data)
|
116
|
+
{ action: (data['action'] || :receive).to_sym }
|
117
|
+
end
|
118
|
+
|
119
|
+
# Get the GraphQL variables for a request
|
120
|
+
def gql_variables(data)
|
121
|
+
variables = data['variables']
|
122
|
+
|
123
|
+
case variables
|
124
|
+
when ::ActionController::Parameters then variables.permit!.to_h
|
125
|
+
when String then variables.present? ? JSON.parse(variables) : {}
|
126
|
+
when Hash then variables
|
127
|
+
else {}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Remove all subscriptions
|
132
|
+
def gql_clear_subscriptions
|
133
|
+
gql_remove_subscription(*gql_subscriptions.keys) unless gql_subscriptions.empty?
|
134
|
+
end
|
135
|
+
|
136
|
+
# Remove one or more subscriptions
|
137
|
+
def gql_remove_subscriptions(*sids)
|
138
|
+
gql_schema.remove_subscriptions(*sids)
|
139
|
+
end
|
140
|
+
|
141
|
+
alias gql_remove_subscription gql_remove_subscriptions
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
# Find the default application schema
|
146
|
+
def gql_application_default_schema
|
147
|
+
app_class = Rails.application.class
|
148
|
+
source_name = app_class.respond_to?(:module_parent_name) \
|
149
|
+
? :module_parent_name \
|
150
|
+
: :parent_name
|
151
|
+
|
152
|
+
klass = "::GraphQL::#{app_class.public_send(source_name)}Schema".constantize
|
153
|
+
self.class.gql_schema = klass
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -1,15 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
5
|
# = GraphQL Controller
|
6
6
|
#
|
7
7
|
# The controller helper methods that allow GraphQL to be performed on a
|
8
|
-
# Rails Controller class
|
8
|
+
# Rails Controller class
|
9
9
|
module Controller
|
10
10
|
extend ActiveSupport::Concern
|
11
11
|
|
12
|
-
REQUEST_XARGS = %i[operation_name variables context schema].freeze
|
12
|
+
REQUEST_XARGS = %i[operation_name variables context schema query_cache_key].freeze
|
13
|
+
DESCRIBE_HEADER = <<~TXT.freeze
|
14
|
+
"""
|
15
|
+
Use the following HTTP params to modify this result:
|
16
|
+
without_descriptions => Hide all descriptions
|
17
|
+
without_spec => Hide all default spec types
|
18
|
+
"""
|
19
|
+
TXT
|
13
20
|
|
14
21
|
included do
|
15
22
|
# Each controller is assigned to a GraphQL schema on which the requests
|
@@ -24,10 +31,7 @@ module Rails # :nodoc:
|
|
24
31
|
|
25
32
|
# GET /describe
|
26
33
|
def describe
|
27
|
-
render plain:
|
28
|
-
with_descriptions: !params.key?(:without_descriptions),
|
29
|
-
with_spec: !params.key?(:without_spec),
|
30
|
-
)
|
34
|
+
render plain: gql_schema_header + gql_describe_schema + gql_schema_footer
|
31
35
|
end
|
32
36
|
|
33
37
|
protected
|
@@ -37,23 +41,46 @@ module Rails # :nodoc:
|
|
37
41
|
render json: gql_request(*args, **xargs)
|
38
42
|
end
|
39
43
|
|
44
|
+
# Shows a text representation of the schema
|
45
|
+
def gql_describe_schema(schema = gql_schema)
|
46
|
+
schema.to_gql(
|
47
|
+
with_descriptions: !params.key?(:without_descriptions),
|
48
|
+
with_spec: !params.key?(:without_spec),
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
40
52
|
# Execute a GraphQL request
|
41
53
|
def gql_request(query, **xargs)
|
42
|
-
request_xargs = REQUEST_XARGS.
|
43
|
-
result
|
54
|
+
request_xargs = REQUEST_XARGS.each_with_object({}) do |setting, result|
|
55
|
+
result[setting] ||= (xargs[setting] || send(:"gql_#{setting}"))
|
44
56
|
end
|
45
57
|
|
58
|
+
request_xargs[:hash] ||= gql_query_cache_key
|
59
|
+
request_xargs[:origin] ||= self
|
60
|
+
|
61
|
+
request_xargs = request_xargs.except(*%i[query_cache_key query_cache_version])
|
46
62
|
::Rails::GraphQL::Request.execute(query, **request_xargs)
|
47
63
|
end
|
48
64
|
|
65
|
+
# Print a header of the current schema for the description process
|
66
|
+
# TODO: Maybe add a way to detect from which file the schema is being loaded
|
67
|
+
def gql_schema_header
|
68
|
+
ns = +" [#{gql_schema.namespace}]" if gql_schema.namespace != :base
|
69
|
+
+"#{DESCRIBE_HEADER}# Schema #{gql_schema.name}#{ns}\n"
|
70
|
+
end
|
71
|
+
|
49
72
|
# The schema on which the requests will be performed from
|
50
73
|
def gql_schema
|
74
|
+
return @gql_schema if defined?(@gql_schema)
|
75
|
+
|
51
76
|
schema = self.class.gql_schema
|
52
|
-
schema = schema.
|
53
|
-
schema ||=
|
54
|
-
|
77
|
+
schema = schema.constantize if schema.is_a?(String)
|
78
|
+
schema ||= gql_application_default_schema
|
79
|
+
|
80
|
+
return @gql_schema = schema if schema.is_a?(Module) &&
|
81
|
+
schema < ::Rails::GraphQL::Schema
|
55
82
|
|
56
|
-
raise ExecutionError,
|
83
|
+
raise ExecutionError, (+<<~MSG).squish
|
57
84
|
Unable to find a valid schema for #{self.class.name},
|
58
85
|
defined value: #{schema.inspect}.
|
59
86
|
MSG
|
@@ -64,9 +91,15 @@ module Rails # :nodoc:
|
|
64
91
|
params[:query]
|
65
92
|
end
|
66
93
|
|
94
|
+
# Get the cache key of the query for persisted queries
|
95
|
+
def gql_query_cache_key(key = nil, version = nil)
|
96
|
+
return unless (key ||= params[:query_cache_key]).present?
|
97
|
+
CacheKey.new(key, version || params[:query_cache_version])
|
98
|
+
end
|
99
|
+
|
67
100
|
# Get the GraphQL operation name
|
68
101
|
def gql_operation_name
|
69
|
-
params[:operationName]
|
102
|
+
params[:operationName] || params[:operation_name]
|
70
103
|
end
|
71
104
|
|
72
105
|
# Get the GraphQL context for a requests
|
@@ -84,16 +117,28 @@ module Rails # :nodoc:
|
|
84
117
|
end
|
85
118
|
end
|
86
119
|
|
120
|
+
# Show the footer of the describe page
|
121
|
+
def gql_schema_footer
|
122
|
+
$/ + $/ + '# Version: ' + gql_version + $/ +
|
123
|
+
'# Rails GraphQL ' + ::Rails::GraphQL::VERSION::STRING +
|
124
|
+
' (Spec ' + ::GQLParser::VERSION + ')'
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get the version of the running instance of GraphQL
|
128
|
+
def gql_version
|
129
|
+
::Rails::GraphQL.type_map.version
|
130
|
+
end
|
131
|
+
|
87
132
|
private
|
88
133
|
|
89
134
|
# Find the default application schema
|
90
|
-
def
|
135
|
+
def gql_application_default_schema
|
91
136
|
app_class = Rails.application.class
|
92
137
|
source_name = app_class.respond_to?(:module_parent_name) \
|
93
138
|
? :module_parent_name \
|
94
139
|
: :parent_name
|
95
140
|
|
96
|
-
klass = "::GraphQL::#{app_class.
|
141
|
+
klass = "::GraphQL::#{app_class.public_send(source_name)}Schema".constantize
|
97
142
|
self.class.gql_schema = klass
|
98
143
|
end
|
99
144
|
end
|
@@ -2,20 +2,20 @@
|
|
2
2
|
|
3
3
|
require 'active_support/core_ext/module/attr_internal'
|
4
4
|
|
5
|
-
module Rails
|
6
|
-
module GraphQL
|
5
|
+
module Rails
|
6
|
+
module GraphQL
|
7
7
|
# = GraphQL Controller Runtime
|
8
8
|
#
|
9
9
|
# Tool that calculates the runtime of a GraphQL operation. This works
|
10
10
|
# similar to how Rails ActiveRecord calculate its execution time while
|
11
|
-
# performing a request
|
11
|
+
# performing a request
|
12
12
|
module ControllerRuntime
|
13
13
|
extend ActiveSupport::Concern
|
14
14
|
|
15
|
-
module ClassMethods
|
15
|
+
module ClassMethods
|
16
16
|
def log_process_action(payload)
|
17
17
|
messages, gql_runtime = super, payload[:gql_runtime]
|
18
|
-
messages << format('GraphQL: %.1fms', gql_runtime.to_f) if gql_runtime
|
18
|
+
messages << format(+'GraphQL: %.1fms', gql_runtime.to_f) if gql_runtime
|
19
19
|
messages
|
20
20
|
end
|
21
21
|
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require "active_support/parameter_filter"
|
4
|
+
|
5
|
+
module Rails
|
6
|
+
module GraphQL
|
5
7
|
# = GraphQL Log Subscriber
|
6
8
|
#
|
7
|
-
# This is the log tracker that
|
8
|
-
# has to report on logs that a query was performed
|
9
|
-
class LogSubscriber < ::ActiveSupport::LogSubscriber
|
9
|
+
# This is the log tracker that works the same way as ActiveRecord when it
|
10
|
+
# has to report on logs that a query was performed
|
11
|
+
class LogSubscriber < ::ActiveSupport::LogSubscriber
|
10
12
|
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
11
13
|
|
14
|
+
REMOVE_COMMENTS = /#(?=(?:[^"]*"[^"]*")*[^"]*$).*/
|
15
|
+
|
12
16
|
def self.runtime
|
13
17
|
RuntimeRegistry.gql_runtime ||= 0
|
14
18
|
end
|
@@ -22,23 +26,65 @@ module Rails # :nodoc:
|
|
22
26
|
return unless logger.debug?
|
23
27
|
|
24
28
|
payload = event.payload
|
29
|
+
cached = '[CACHE]' if payload[:cached]
|
30
|
+
doc = payload[:document]&.gsub(REMOVE_COMMENTS, '')&.squish
|
31
|
+
|
32
|
+
desc = +"#{header(event, cached)} #{doc}"
|
33
|
+
desc << debug_variables(payload[:variables]) unless payload[:variables].blank?
|
34
|
+
|
35
|
+
debug(desc)
|
36
|
+
end
|
37
|
+
|
38
|
+
def compile(event)
|
39
|
+
return unless logger.debug?
|
40
|
+
|
41
|
+
payload = event.payload
|
42
|
+
doc = payload[:document].gsub(REMOVE_COMMENTS, '').squish
|
43
|
+
|
44
|
+
helper = ActiveSupport::NumberHelper::NumberToHumanSizeConverter
|
45
|
+
total = helper.convert(payload[:total], EMPTY_HASH)
|
46
|
+
|
47
|
+
debug(+"#{header(event, 'Compile')} #{total} #{doc}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate(event)
|
51
|
+
return unless logger.debug?
|
52
|
+
|
53
|
+
payload = event.payload
|
54
|
+
doc = payload[:document].gsub(REMOVE_COMMENTS, '').squish
|
55
|
+
valid = payload[:result] ? color('YES', GREEN) : color('NO', RED)
|
56
|
+
|
57
|
+
debug(+"#{header(event, 'Valid?')} #{valid} #{doc}")
|
58
|
+
end
|
59
|
+
|
60
|
+
def subscription(event)
|
61
|
+
return unless logger.info?
|
25
62
|
|
26
|
-
|
27
|
-
name.
|
28
|
-
|
63
|
+
item, type, provider = event.payload.values_at(:item, :type, :provider)
|
64
|
+
provider = provider.class.name.sub(/\ARails::GraphQL::Subscription::/, '')
|
65
|
+
duration = event.duration.round(1)
|
29
66
|
|
30
|
-
|
31
|
-
|
32
|
-
|
67
|
+
desc = +"#{header(event, provider)} Subscription #{type}"
|
68
|
+
|
69
|
+
unless item.nil?
|
70
|
+
hex = { added: GREEN, removed: RED, updated: BLUE }[type]
|
71
|
+
|
72
|
+
if type == :updated
|
73
|
+
desc << +": #{color(item.sid, hex)}"
|
74
|
+
else
|
75
|
+
desc << +": [#{color(item.sid, hex)}] #{item.schema}.#{item.field.gql_name}"
|
76
|
+
desc << +" [#{(item.scope === null_subscription_scope ? nil : item.scope).inspect}"
|
77
|
+
desc << +", #{item.args.as_json.inspect}]"
|
78
|
+
end
|
33
79
|
end
|
34
80
|
|
35
|
-
|
81
|
+
info(desc)
|
36
82
|
end
|
37
83
|
|
38
84
|
private
|
39
85
|
|
40
86
|
def logger
|
41
|
-
GraphQL.
|
87
|
+
GraphQL.logger
|
42
88
|
end
|
43
89
|
|
44
90
|
def debug(*)
|
@@ -47,14 +93,35 @@ module Rails # :nodoc:
|
|
47
93
|
log_query_source if GraphQL.config.verbose_logs
|
48
94
|
end
|
49
95
|
|
96
|
+
def header(event, suffix = '')
|
97
|
+
duration = event.duration.round(1)
|
98
|
+
parts = [' GraphQL', suffix.presence, event.payload[:name]]
|
99
|
+
parts << "(#{duration}ms)" unless duration.zero?
|
100
|
+
|
101
|
+
color(parts.compact.join(' '), MAGENTA, true)
|
102
|
+
end
|
103
|
+
|
104
|
+
def debug_variables(vars)
|
105
|
+
vars = JSON.pretty_generate(parameter_filter.filter(vars))
|
106
|
+
+' ' << '(' << vars.squish << ')'
|
107
|
+
end
|
108
|
+
|
50
109
|
def log_query_source
|
51
110
|
source = extract_query_source_location(caller)
|
52
|
-
logger.debug(" ↳ #{source}") if source
|
111
|
+
logger.debug(+" ↳ #{source}") if source
|
53
112
|
end
|
54
113
|
|
55
114
|
def extract_query_source_location(locations)
|
56
115
|
backtrace_cleaner.clean(locations.lazy).first
|
57
116
|
end
|
117
|
+
|
118
|
+
def parameter_filter
|
119
|
+
ActiveSupport::ParameterFilter.new(GraphQL.config.filter_parameters)
|
120
|
+
end
|
121
|
+
|
122
|
+
def null_subscription_scope
|
123
|
+
Request::Subscription::NULL_SCOPE
|
124
|
+
end
|
58
125
|
end
|
59
126
|
end
|
60
127
|
|
@@ -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 Arguments
|
7
7
|
#
|
8
8
|
# This is an extension of an +OpenStruct+ since argument values can be
|
@@ -14,14 +14,33 @@ module Rails # :nodoc:
|
|
14
14
|
# the spread and operation.
|
15
15
|
class Arguments < OpenStruct
|
16
16
|
THREAD_KEY = :_rails_graphql_operation
|
17
|
-
|
17
|
+
|
18
|
+
class Lazy < Delegator
|
19
|
+
attr_reader :var_name
|
20
|
+
|
21
|
+
def self.[](key)
|
22
|
+
new(key)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(var_name)
|
26
|
+
@var_name = var_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def __getobj__
|
30
|
+
Arguments.operation&.variables&.dig(var_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def __setobj__(*)
|
34
|
+
raise FrozenError
|
35
|
+
end
|
36
|
+
end
|
18
37
|
|
19
38
|
delegate :key?, to: :@table
|
20
39
|
|
21
40
|
class << self
|
22
41
|
# Easy access to the easy loader method
|
23
42
|
def lazy
|
24
|
-
|
43
|
+
Lazy
|
25
44
|
end
|
26
45
|
|
27
46
|
# Get the current operation thread safely
|
@@ -42,50 +61,6 @@ module Rails # :nodoc:
|
|
42
61
|
def scoped?
|
43
62
|
operation.present?
|
44
63
|
end
|
45
|
-
|
46
|
-
# If it's running under a scope, transform proc based values
|
47
|
-
def transform(value)
|
48
|
-
return if value.nil?
|
49
|
-
scoped? && value.is_a?(Proc) ? value.call(operation) : value
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Transform any proc by its actual value before returning the hash
|
54
|
-
def to_h(*)
|
55
|
-
super.transform_values(&self.class.method(:transform))
|
56
|
-
end
|
57
|
-
|
58
|
-
# Before iterating, transform any needed value
|
59
|
-
def each_pair
|
60
|
-
enum = to_h.to_enum
|
61
|
-
return enum unless block_given?
|
62
|
-
enum.each { |v| yield v }
|
63
|
-
self
|
64
|
-
end
|
65
|
-
|
66
|
-
# rubocop:disable Style/MissingRespondToMissing
|
67
|
-
# Transform the value before returning
|
68
|
-
def method_missing(*)
|
69
|
-
self.class.transform(super)
|
70
|
-
end
|
71
|
-
# rubocop:enable Style/MissingRespondToMissing
|
72
|
-
|
73
|
-
# Transform the value before returning
|
74
|
-
def [](*)
|
75
|
-
self.class.transform(super)
|
76
|
-
end
|
77
|
-
|
78
|
-
# Transform the value before returning
|
79
|
-
def dig(name, *names)
|
80
|
-
result = self.class.transform(super(name))
|
81
|
-
names.empty? ? result : result&.dig(*names)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Override the freeze method to just freeze the table and do not create
|
85
|
-
# the getters and setter methods
|
86
|
-
def freeze
|
87
|
-
@table.freeze
|
88
|
-
super
|
89
64
|
end
|
90
65
|
end
|
91
66
|
end
|