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
@@ -3,8 +3,8 @@
|
|
3
3
|
require 'concurrent/map'
|
4
4
|
require 'active_support/core_ext/class/subclasses'
|
5
5
|
|
6
|
-
module Rails
|
7
|
-
module GraphQL
|
6
|
+
module Rails
|
7
|
+
module GraphQL
|
8
8
|
# = GraphQL Type Map
|
9
9
|
#
|
10
10
|
# Inspired by ActiveRecord::Type::TypeMap, this class stores all the things
|
@@ -19,26 +19,42 @@ module Rails # :nodoc:
|
|
19
19
|
class TypeMap
|
20
20
|
FILTER_REGISTER_TRACE = /((inherited|initialize)'$|schema\.rb:\d+)/.freeze
|
21
21
|
|
22
|
-
|
23
|
-
# Be aware of the order because hard reset is based in this order
|
24
|
-
mattr_accessor :base_classes, instance_writer: false, default: {
|
25
|
-
Type: false,
|
26
|
-
Directive: false,
|
27
|
-
Schema: false,
|
28
|
-
}
|
22
|
+
NsList = Class.new(Set)
|
29
23
|
|
30
|
-
|
31
|
-
|
24
|
+
# Store all the base classes that are managed by the Type Map
|
25
|
+
mattr_accessor :base_classes, instance_writer: false,
|
26
|
+
default: Set.new(%i[Type Directive Schema])
|
27
|
+
|
28
|
+
# Get the current version of the Type Map. On each reset, the version is
|
29
|
+
# changed and can be used to invalidate cache and similar things
|
30
|
+
def version
|
31
|
+
@version ||= GraphQL.config.version&.first(8) || SecureRandom.hex(8)
|
32
32
|
end
|
33
33
|
|
34
34
|
# Reset the state of the type mapper
|
35
35
|
def reset!
|
36
36
|
@objects = 0 # Number of types and directives defined
|
37
|
-
|
38
|
-
@pending = []
|
39
|
-
@callbacks = Hash.new { |h, k| h[k] = [] }
|
37
|
+
@version = nil # Make sure to not keep the same version
|
40
38
|
@skip_register = nil
|
41
39
|
|
40
|
+
@pending = Concurrent::Array.new
|
41
|
+
@reported_fallbacks = Concurrent::Set.new
|
42
|
+
|
43
|
+
# Initialize the callbacks
|
44
|
+
@callbacks = Concurrent::Map.new do |hc, key|
|
45
|
+
hc.fetch_or_store(key, Concurrent::Array.new)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initialize the dependencies
|
49
|
+
@dependencies = Concurrent::Map.new do |hd, key|
|
50
|
+
hd.fetch_or_store(key, Concurrent::Array.new)
|
51
|
+
end
|
52
|
+
|
53
|
+
# A registered list of modules and to which namespaces they are
|
54
|
+
# associated with
|
55
|
+
@module_namespaces = Concurrent::Map.new
|
56
|
+
|
57
|
+
# Initialize the index structure
|
42
58
|
@index = Concurrent::Map.new do |h1, key1| # Namespaces
|
43
59
|
base_class = Concurrent::Map.new do |h2, key2| # Base classes
|
44
60
|
ensure_base_class!(key2)
|
@@ -48,141 +64,76 @@ module Rails # :nodoc:
|
|
48
64
|
h1.fetch_or_store(key1, base_class)
|
49
65
|
end
|
50
66
|
|
51
|
-
|
67
|
+
# Provide the first dependencies
|
68
|
+
seed_dependencies!
|
52
69
|
end
|
53
70
|
|
54
71
|
alias initialize reset!
|
55
72
|
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
remove_instance_variable(:@checkpoint) if defined?(@checkpoint)
|
60
|
-
|
61
|
-
reset!
|
62
|
-
base_classes.each_key do |base_class|
|
63
|
-
GraphQL.const_get(base_class).descendants.each(&:register!)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Save or restore a checkpoint that can the type map can be reseted to
|
68
|
-
# TODO: With hard reset, we might not need checkpoint anymore
|
69
|
-
def use_checkpoint!
|
70
|
-
return reset! if defined?(@checkpoint)
|
71
|
-
|
72
|
-
register_pending!
|
73
|
-
@checkpoint = objects
|
73
|
+
# Add a list of dependencies to the type map, so it can lazy load them
|
74
|
+
def add_dependencies(*list, to:)
|
75
|
+
@dependencies[to].concat(list.flatten.compact)
|
74
76
|
end
|
75
77
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
if @index[namespace].key?(base_class)
|
82
|
-
end if @index.key?(namespace)
|
83
|
-
end.flatten.compact.uniq.select do |obj|
|
84
|
-
obj.respond_to?(:register!)
|
85
|
-
end
|
78
|
+
# Mark the given object to be registered later, when a fetch is triggered
|
79
|
+
# TODO: Improve this with a Backtrace Cleaner
|
80
|
+
def postpone_registration(object)
|
81
|
+
source = caller(3).find { |item| item !~ FILTER_REGISTER_TRACE }
|
82
|
+
@pending << [object, source]
|
86
83
|
end
|
87
84
|
|
88
|
-
#
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
return result unless result.nil?
|
95
|
-
|
96
|
-
raise ArgumentError, <<~MSG.squish if base_classes[base_class]
|
97
|
-
Unable to find #{args.first.inspect} #{base_class} object.
|
98
|
-
MSG
|
99
|
-
|
100
|
-
GraphQL.const_get(base_class).eager_load!
|
101
|
-
fetch!(*args, **xargs)
|
85
|
+
# Associate the given +module+ to a given +namespace+. If registered
|
86
|
+
# objects have no namespaces, but its +module_parents+ have been
|
87
|
+
# associated, then use the value
|
88
|
+
# TODO: Maybe turn this into a 1-to-Many association
|
89
|
+
def associate(namespace, mod)
|
90
|
+
@module_namespaces[mod] = namespace
|
102
91
|
end
|
103
92
|
|
104
|
-
#
|
105
|
-
#
|
106
|
-
def
|
107
|
-
if
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
namespaces = xargs[:namespaces]
|
113
|
-
namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
|
114
|
-
namespaces += [:base] unless xargs.fetch(:exclusive, false)
|
115
|
-
|
116
|
-
possibilities = Array.wrap(key_or_name)
|
117
|
-
possibilities += Array.wrap(xargs[:fallback]) if xargs.key?(:fallback)
|
118
|
-
|
119
|
-
namespaces.uniq.find do |namespace|
|
120
|
-
possibilities.find do |item|
|
121
|
-
result = dig(namespace, xargs.fetch(:base_class, :Type), item)
|
122
|
-
return result.call unless result.nil?
|
123
|
-
end
|
93
|
+
# Grab all the +module_parents+ from the object and try to return the
|
94
|
+
# first matching result
|
95
|
+
def associated_namespace_of(object)
|
96
|
+
return if @module_namespaces.empty?
|
97
|
+
object.module_parents.find do |mod|
|
98
|
+
ns = @module_namespaces[mod]
|
99
|
+
break ns unless ns.nil?
|
124
100
|
end
|
125
|
-
ensure
|
126
|
-
skip_register.pop
|
127
|
-
end
|
128
|
-
|
129
|
-
# Checks if a given key or name is already defined under the same base
|
130
|
-
# class and namespace. If +exclusive+ is set to +false+, then it won't
|
131
|
-
# check the +:base+ namespace when not found on the given namespace.
|
132
|
-
def exist?(name_or_key, base_class: :Type, namespaces: :base, exclusive: false)
|
133
|
-
namespaces = namespaces.is_a?(Set) ? namespaces.to_a : Array.wrap(namespaces)
|
134
|
-
namespaces += [:base] unless exclusive
|
135
|
-
namespaces.uniq.any? { |namespace| dig(namespace, base_class, name_or_key).present? }
|
136
|
-
end
|
137
|
-
|
138
|
-
# Find if a given object is already defined. If +exclusive+ is set to
|
139
|
-
# +false+, then it won't check the +:base+ namespace
|
140
|
-
def object_exist?(object, **xargs)
|
141
|
-
xargs[:base_class] = find_base_class(object)
|
142
|
-
xargs[:namespaces] ||= object.namespaces
|
143
|
-
exist?(object, **xargs)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Mark the given object to be registered later, when a fetch is triggered
|
147
|
-
# TODO: Improve this with a Backtracer Cleaner
|
148
|
-
def postpone_registration(object)
|
149
|
-
source = caller(3).find { |item| item !~ FILTER_REGISTER_TRACE }
|
150
|
-
@pending << [object, source]
|
151
101
|
end
|
152
102
|
|
153
103
|
# Register a given object, which must be a class where the namespaces and
|
154
104
|
# the base class can be inferred
|
155
105
|
def register(object)
|
156
|
-
namespaces = object.namespaces
|
157
|
-
namespaces
|
106
|
+
namespaces = sanitize_namespaces(namespaces: object.namespaces, exclusive: true)
|
107
|
+
namespaces << :base if namespaces.empty?
|
158
108
|
|
159
|
-
base_namespace = namespaces.shift || :base
|
160
109
|
base_class = find_base_class(object)
|
161
110
|
ensure_base_class!(base_class)
|
162
111
|
|
163
112
|
# Cache the name, the key, and the alias proc
|
113
|
+
object_base = namespaces.first
|
164
114
|
object_name = object.gql_name
|
165
115
|
object_key = object.to_sym
|
166
116
|
alias_proc = -> do
|
167
|
-
fetch(object_key,
|
168
|
-
base_class: base_class,
|
169
|
-
namespaces: base_namespace,
|
170
|
-
exclusive: true,
|
171
|
-
)
|
117
|
+
fetch(object_key, base_class: base_class, namespaces: object_base, exclusive: true)
|
172
118
|
end
|
173
119
|
|
174
|
-
#
|
175
|
-
|
120
|
+
# TODO Warn when the base key is being assigned to a different object
|
121
|
+
# Register the main type object for both key and name
|
122
|
+
add(object_base, base_class, object_key, object)
|
123
|
+
add(object_base, base_class, object_name, alias_proc)
|
176
124
|
|
177
125
|
# Register all the aliases plus the object name
|
178
|
-
aliases = object.try(:aliases)
|
179
|
-
|
180
|
-
add(
|
126
|
+
aliases = object.try(:aliases)
|
127
|
+
aliases&.each do |alias_name|
|
128
|
+
add(object_base, base_class, alias_name, alias_proc)
|
181
129
|
end
|
182
130
|
|
183
131
|
# For each remaining namespace, register a key and a name alias
|
184
|
-
namespaces.
|
185
|
-
|
132
|
+
if namespaces.size > 1
|
133
|
+
keys_and_names = [object_key, object_name, *aliases]
|
134
|
+
namespaces.drop(1).product(keys_and_names) do |(namespace, key_or_name)|
|
135
|
+
add(namespace, base_class, key_or_name, alias_proc)
|
136
|
+
end
|
186
137
|
end
|
187
138
|
|
188
139
|
# Return the object for chain purposes
|
@@ -190,22 +141,32 @@ module Rails # :nodoc:
|
|
190
141
|
object
|
191
142
|
end
|
192
143
|
|
144
|
+
# Unregister all the provided objects by simply assigning nil to their
|
145
|
+
# final value on the index
|
146
|
+
def unregister(*objects)
|
147
|
+
objects.each do |object|
|
148
|
+
namespaces = sanitize_namespaces(namespaces: object.namespaces, exclusive: true)
|
149
|
+
namespaces << :base if namespaces.empty?
|
150
|
+
base_class = find_base_class(object)
|
151
|
+
|
152
|
+
@objects -= 1
|
153
|
+
@index[namespaces.first][base_class][object.to_sym] = nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
193
157
|
# Register an item alias. Either provide a block that trigger the fetch
|
194
158
|
# method to return that item, or a key from the same namespace and base
|
195
159
|
# class
|
196
160
|
def register_alias(name_or_key, key = nil, **xargs, &block)
|
197
|
-
raise ArgumentError,
|
161
|
+
raise ArgumentError, (+<<~MSG).squish unless key.nil? ^ block.nil?
|
198
162
|
Provide either a key or a block in order to register an alias.
|
199
163
|
MSG
|
200
164
|
|
201
165
|
base_class = xargs.delete(:base_class) || :Type
|
202
166
|
ensure_base_class!(base_class)
|
203
167
|
|
204
|
-
namespaces = xargs
|
205
|
-
namespaces
|
206
|
-
namespaces << xargs.delete(:namespace)
|
207
|
-
|
208
|
-
namespaces = namespaces.compact.presence || [:base]
|
168
|
+
namespaces = sanitize_namespaces(**xargs, exclusive: true)
|
169
|
+
namespaces << :base if namespaces.empty?
|
209
170
|
|
210
171
|
block ||= -> do
|
211
172
|
fetch(key, base_class: base_class, namespaces: namespaces, exclusive: true)
|
@@ -214,57 +175,131 @@ module Rails # :nodoc:
|
|
214
175
|
namespaces.each { |ns| add(ns, base_class, name_or_key, block) }
|
215
176
|
end
|
216
177
|
|
178
|
+
# Same as +fetch+ but it will raise an exception or retry depending if the
|
179
|
+
# base type was already loaded or not
|
180
|
+
def fetch!(key_or_name, base_class: :Type, fallback: nil, **xargs)
|
181
|
+
xargs[:base_class] = base_class
|
182
|
+
|
183
|
+
result = fetch(key_or_name, **xargs)
|
184
|
+
return result unless result.nil?
|
185
|
+
|
186
|
+
new_loads = load_dependencies!(**xargs)
|
187
|
+
result = fetch(key_or_name, **xargs) if new_loads
|
188
|
+
|
189
|
+
if result.nil? && fallback
|
190
|
+
result = fetch(fallback, **xargs)
|
191
|
+
report_fallback(key_or_name, result, base_class)
|
192
|
+
end
|
193
|
+
|
194
|
+
raise NotFoundError, (+<<~MSG).squish if result.nil?
|
195
|
+
Unable to find #{key_or_name.inspect} #{base_class} object.
|
196
|
+
MSG
|
197
|
+
|
198
|
+
result
|
199
|
+
end
|
200
|
+
|
201
|
+
# Find the given key or name inside the base class either on the given
|
202
|
+
# namespace or in the base +:base+ namespace
|
203
|
+
def fetch(key_or_name, prevent_register: nil, **xargs)
|
204
|
+
if prevent_register != true
|
205
|
+
items = prevent_register == true ? nil : ::Array.wrap(prevent_register)
|
206
|
+
skip_register << items.to_set
|
207
|
+
register_pending!
|
208
|
+
end
|
209
|
+
|
210
|
+
possibilities = ::Array.wrap(key_or_name)
|
211
|
+
possibilities << xargs[:fallback] if xargs.key?(:fallback)
|
212
|
+
|
213
|
+
base_class = xargs.fetch(:base_class, :Type)
|
214
|
+
sanitize_namespaces(**xargs).find do |namespace|
|
215
|
+
possibilities.find do |item|
|
216
|
+
next if (result = dig(namespace, base_class, item)).nil?
|
217
|
+
next if (result.is_a?(Proc) && (result = result.call).nil?)
|
218
|
+
return result
|
219
|
+
end
|
220
|
+
end
|
221
|
+
ensure
|
222
|
+
skip_register.pop
|
223
|
+
end
|
224
|
+
|
225
|
+
# Checks if a given key or name is already defined under the same base
|
226
|
+
# class and namespace. If +exclusive+ is set to +false+, then it won't
|
227
|
+
# check the +:base+ namespace when not found on the given namespace.
|
228
|
+
def exist?(name_or_key, **xargs)
|
229
|
+
!fetch(name_or_key, **xargs, prevent_register: true).nil?
|
230
|
+
end
|
231
|
+
|
232
|
+
# Find if a given object is already defined. If +exclusive+ is set to
|
233
|
+
# +false+, then it won't check the +:base+ namespace
|
234
|
+
def object_exist?(object, **xargs)
|
235
|
+
xargs[:base_class] = find_base_class(object)
|
236
|
+
xargs[:namespaces] ||= object.namespaces
|
237
|
+
exist?(object, **xargs)
|
238
|
+
end
|
239
|
+
|
217
240
|
# Iterate over the types of the given +base_class+ that are defined on the
|
218
241
|
# given +namespaces+.
|
219
|
-
def each_from(namespaces, base_class:
|
242
|
+
def each_from(namespaces, base_class: nil, exclusive: false, base_classes: nil, &block)
|
243
|
+
namespaces = sanitize_namespaces(namespaces: namespaces, exclusive: exclusive)
|
244
|
+
load_dependencies!(_ns: namespaces)
|
220
245
|
register_pending!
|
221
246
|
|
222
|
-
|
223
|
-
|
247
|
+
iterated = Set.new
|
248
|
+
base_classes = GraphQL.enumerate(base_class || base_classes || :Type)
|
249
|
+
enumerator = Enumerator::Lazy.new(namespaces) do |yielder, namespace|
|
250
|
+
next unless @index.key?(namespace)
|
224
251
|
|
225
|
-
|
226
|
-
|
227
|
-
|
252
|
+
base_classes.each do |a_base_class|
|
253
|
+
@index[namespace][a_base_class]&.each do |key, value|
|
254
|
+
value = value.is_a?(Proc) ? value.call : value
|
255
|
+
next if value.blank? || iterated.include?(value.gql_name)
|
228
256
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
iterated << value
|
233
|
-
yielder << value
|
257
|
+
iterated << value.gql_name
|
258
|
+
yielder << value
|
259
|
+
end
|
234
260
|
end
|
235
261
|
end
|
236
262
|
|
237
263
|
block.present? ? enumerator.each(&block) : enumerator
|
238
264
|
end
|
239
265
|
|
266
|
+
# Get the list of all registered objects
|
267
|
+
# TODO: Maybe keep it as a lazy enumerator
|
268
|
+
def objects(base_classes: nil, namespaces: nil)
|
269
|
+
base_classes ||= self.class.base_classes
|
270
|
+
each_from(namespaces || @index.keys, base_classes: base_classes).select do |obj|
|
271
|
+
obj.is_a?(Helpers::Registerable)
|
272
|
+
end.force
|
273
|
+
end
|
274
|
+
|
240
275
|
# Add a callback that will trigger when a type is registered under the
|
241
276
|
# given set of settings of this method
|
242
|
-
def after_register(name_or_key, base_class: :Type,
|
243
|
-
item = fetch(name_or_key,
|
244
|
-
prevent_register: true,
|
245
|
-
base_class: base_class,
|
246
|
-
namespaces: namespaces,
|
247
|
-
)
|
248
|
-
|
277
|
+
def after_register(name_or_key, base_class: :Type, **xargs, &block)
|
278
|
+
item = fetch(name_or_key, prevent_register: true, base_class: base_class, **xargs)
|
249
279
|
return block.call(item) unless item.nil?
|
250
280
|
|
251
|
-
namespaces =
|
252
|
-
|
253
|
-
|
254
|
-
callbacks[name_or_key] << ->(n, b, result) do
|
281
|
+
namespaces = sanitize_namespaces(**xargs)
|
282
|
+
callback = ->(n, b, result) do
|
255
283
|
return unless b === base_class && (n === :base || namespaces.include?(n))
|
256
284
|
block.call(result)
|
257
|
-
|
285
|
+
true
|
258
286
|
end
|
287
|
+
|
288
|
+
callbacks[name_or_key].unshift(callback)
|
259
289
|
end
|
260
290
|
|
261
|
-
def inspect
|
262
|
-
|
291
|
+
def inspect
|
292
|
+
dependencies = @dependencies.each_pair.map do |key, list|
|
293
|
+
+("#{key}: #{list.size}")
|
294
|
+
end.join(', ')
|
295
|
+
|
296
|
+
(+<<~INFO).squish << '>'
|
263
297
|
#<Rails::GraphQL::TypeMap [index]
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
298
|
+
@namespaces=#{@index.size}
|
299
|
+
@base_classes=#{base_classes.size}
|
300
|
+
@objects=#{@objects}
|
301
|
+
@pending=#{@pending.size}
|
302
|
+
@dependencies={#{dependencies}}
|
268
303
|
INFO
|
269
304
|
end
|
270
305
|
|
@@ -278,14 +313,25 @@ module Rails # :nodoc:
|
|
278
313
|
return unless callbacks.key?(key)
|
279
314
|
|
280
315
|
result = nil
|
281
|
-
|
282
|
-
|
316
|
+
callbacks[key].delete_if do |callback|
|
317
|
+
result ||= raw_result.is_a?(Proc) ? raw_result.call : raw_result
|
318
|
+
callback.call(namespace, base_class, result)
|
283
319
|
end
|
284
320
|
|
285
|
-
removeables.compact.reverse_each(&callbacks[key].method(:delete_at))
|
286
321
|
callbacks.delete(key) if callbacks[key].empty?
|
287
322
|
end
|
288
323
|
|
324
|
+
# Make sure to parse the provided options and names and return a
|
325
|
+
# quality list of namespaces
|
326
|
+
def sanitize_namespaces(**xargs)
|
327
|
+
xargs[:_ns] ||= begin
|
328
|
+
result = xargs[:namespaces] || xargs[:namespace]
|
329
|
+
result = result.is_a?(Set) ? result.dup : Array.wrap(result).to_set
|
330
|
+
result << :base unless xargs.fetch(:exclusive, false)
|
331
|
+
result
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
289
335
|
# A list of classes to prevent the registration, since they might be
|
290
336
|
# the source of a fetch
|
291
337
|
def skip_register
|
@@ -296,27 +342,38 @@ module Rails # :nodoc:
|
|
296
342
|
def register_pending!
|
297
343
|
return if @pending.blank?
|
298
344
|
|
299
|
-
skip = skip_register.
|
345
|
+
skip = skip_register.compact.reduce(:+)
|
300
346
|
keep = []
|
301
|
-
validate = []
|
302
347
|
|
303
348
|
while (klass, source = @pending.shift)
|
304
349
|
next if klass.registered?
|
305
350
|
|
306
|
-
if skip
|
351
|
+
if skip&.include?(klass)
|
307
352
|
keep << [klass, source]
|
308
353
|
else
|
309
|
-
|
354
|
+
klass.register!
|
310
355
|
end
|
311
356
|
end
|
312
|
-
|
313
|
-
validate.compact.each(&:call)
|
314
357
|
rescue DefinitionError => e
|
315
|
-
raise e.class, e.message
|
358
|
+
raise e.class, +"#{e.message}\n Defined at: #{source}"
|
316
359
|
ensure
|
317
360
|
@pending += keep unless keep.nil?
|
318
361
|
end
|
319
362
|
|
363
|
+
# Check the given namespaces and load any pending dependency, it returns
|
364
|
+
# true if anything was actually loaded
|
365
|
+
def load_dependencies!(**xargs)
|
366
|
+
sanitize_namespaces(**xargs).reduce(false) do |result, namespace|
|
367
|
+
next result if (list = @dependencies[namespace]).empty?
|
368
|
+
|
369
|
+
while (src = list.shift)
|
370
|
+
src.is_a?(Proc) ? src.call : require(src)
|
371
|
+
end
|
372
|
+
|
373
|
+
true
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
320
377
|
# Since concurrent map doesn't implement this method, use this to
|
321
378
|
# navigate through the index
|
322
379
|
def dig(*parts)
|
@@ -336,12 +393,47 @@ module Rails # :nodoc:
|
|
336
393
|
base_class.name.demodulize.to_sym
|
337
394
|
end
|
338
395
|
|
396
|
+
# This is the minimum set of dependencies that Type Map needs
|
397
|
+
# TODO: Maybe add even looser dependency
|
398
|
+
def seed_dependencies!
|
399
|
+
@dependencies[:base] += [
|
400
|
+
"#{__dir__}/type/scalar",
|
401
|
+
"#{__dir__}/type/object",
|
402
|
+
"#{__dir__}/type/interface",
|
403
|
+
"#{__dir__}/type/union",
|
404
|
+
"#{__dir__}/type/enum",
|
405
|
+
"#{__dir__}/type/input",
|
406
|
+
|
407
|
+
"#{__dir__}/type/scalar/int_scalar",
|
408
|
+
"#{__dir__}/type/scalar/float_scalar",
|
409
|
+
"#{__dir__}/type/scalar/string_scalar",
|
410
|
+
"#{__dir__}/type/scalar/boolean_scalar",
|
411
|
+
"#{__dir__}/type/scalar/id_scalar",
|
412
|
+
|
413
|
+
"#{__dir__}/directive/deprecated_directive",
|
414
|
+
"#{__dir__}/directive/include_directive",
|
415
|
+
"#{__dir__}/directive/skip_directive",
|
416
|
+
]
|
417
|
+
end
|
418
|
+
|
339
419
|
# Make sure that the given key is a valid base class key
|
340
420
|
def ensure_base_class!(key)
|
341
|
-
raise ArgumentError,
|
421
|
+
raise ArgumentError, (+<<~MSG).squish unless base_classes.include?(key)
|
342
422
|
Unsupported base class "#{key.inspect}".
|
343
423
|
MSG
|
344
424
|
end
|
425
|
+
|
426
|
+
# Warn whenever a new key was resolved as a fallback
|
427
|
+
def report_fallback(key_or_name, result, base_class)
|
428
|
+
return if @reported_fallbacks.include?(key_or_name)
|
429
|
+
|
430
|
+
@reported_fallbacks << key_or_name
|
431
|
+
GraphQL.logger.warn((+<<~MSG).squish)
|
432
|
+
\e[95m[GraphQL]
|
433
|
+
\e[33m#{base_class} "#{key_or_name}" is not defined,
|
434
|
+
using #{result.gql_name} instead.\e[0m
|
435
|
+
MSG
|
436
|
+
end
|
345
437
|
end
|
346
438
|
end
|
347
439
|
end
|