graphql 2.0.13 → 2.3.10
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +3 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +6 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +8 -0
- data/lib/graphql/analysis/analyzer.rb +89 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +183 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +92 -1
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/backtrace/table.rb +2 -2
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +1 -1
- data/lib/graphql/backtrace.rb +2 -1
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/dataloader/async_dataloader.rb +88 -0
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +89 -45
- data/lib/graphql/dataloader.rb +115 -142
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
- data/lib/graphql/execution/interpreter/resolve.rb +19 -0
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +331 -455
- data/lib/graphql/execution/interpreter.rb +125 -61
- data/lib/graphql/execution/lazy.rb +6 -12
- data/lib/graphql/execution/lookahead.rb +124 -46
- data/lib/graphql/execution/multiplex.rb +3 -117
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/introspection/directive_type.rb +3 -3
- data/lib/graphql/introspection/dynamic_fields.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +11 -5
- data/lib/graphql/introspection/field_type.rb +2 -2
- data/lib/graphql/introspection/schema_type.rb +10 -13
- data/lib/graphql/introspection/type_type.rb +17 -10
- data/lib/graphql/introspection.rb +3 -2
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +75 -59
- data/lib/graphql/language/lexer.rb +358 -1506
- data/lib/graphql/language/nodes.rb +166 -93
- data/lib/graphql/language/parser.rb +795 -1953
- data/lib/graphql/language/printer.rb +340 -160
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +33 -6
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +117 -112
- data/lib/graphql/query/null_context.rb +12 -25
- data/lib/graphql/query/validation_pipeline.rb +6 -5
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +86 -30
- data/lib/graphql/railtie.rb +9 -6
- data/lib/graphql/rake_task.rb +29 -11
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/schema/addition.rb +59 -23
- data/lib/graphql/schema/always_visible.rb +11 -0
- data/lib/graphql/schema/argument.rb +55 -26
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +56 -32
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +15 -3
- data/lib/graphql/schema/enum.rb +35 -24
- data/lib/graphql/schema/enum_value.rb +2 -3
- data/lib/graphql/schema/field/connection_extension.rb +2 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +147 -107
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/has_single_input_argument.rb +158 -0
- data/lib/graphql/schema/input_object.rb +47 -11
- data/lib/graphql/schema/interface.rb +15 -21
- data/lib/graphql/schema/introspection_system.rb +7 -17
- data/lib/graphql/schema/late_bound_type.rb +10 -0
- data/lib/graphql/schema/list.rb +2 -2
- data/lib/graphql/schema/loader.rb +2 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -14
- data/lib/graphql/schema/member/build_type.rb +11 -3
- data/lib/graphql/schema/member/has_arguments.rb +170 -130
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +100 -38
- data/lib/graphql/schema/member/has_interfaces.rb +65 -10
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +16 -5
- data/lib/graphql/schema/printer.rb +11 -8
- data/lib/graphql/schema/relay_classic_mutation.rb +7 -129
- data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
- data/lib/graphql/schema/resolver.rb +47 -32
- data/lib/graphql/schema/scalar.rb +3 -3
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/subset.rb +397 -0
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +11 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +60 -0
- data/lib/graphql/schema/validator.rb +4 -2
- data/lib/graphql/schema/warden.rb +238 -93
- data/lib/graphql/schema.rb +498 -103
- data/lib/graphql/static_validation/all_rules.rb +2 -1
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/literal_validator.rb +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +10 -10
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +5 -5
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +11 -4
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/event.rb +11 -10
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +20 -13
- data/lib/graphql/testing/helpers.rb +151 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +251 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +183 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +9 -21
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +17 -3
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/sentry_trace.rb +112 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +76 -0
- data/lib/graphql/tracing.rb +20 -40
- data/lib/graphql/type_kinds.rb +7 -4
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +68 -6
- data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
- data/lib/graphql/types/relay/node_behaviors.rb +8 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +27 -20
- data/readme.md +13 -3
- metadata +96 -47
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -269
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/language/lexer.rl +0 -280
- data/lib/graphql/language/parser.y +0 -554
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
- data/lib/graphql/types/relay/default_relay.rb +0 -21
@@ -4,41 +4,19 @@ require 'set'
|
|
4
4
|
|
5
5
|
module GraphQL
|
6
6
|
class Schema
|
7
|
-
# Restrict access to a {GraphQL::Schema} with a user-defined
|
7
|
+
# Restrict access to a {GraphQL::Schema} with a user-defined `visible?` implementations.
|
8
8
|
#
|
9
9
|
# When validating and executing a query, all access to schema members
|
10
10
|
# should go through a warden. If you access the schema directly,
|
11
11
|
# you may show a client something that it shouldn't be allowed to see.
|
12
12
|
#
|
13
|
-
# @example Hiding private fields
|
14
|
-
# private_members = -> (member, ctx) { member.metadata[:private] }
|
15
|
-
# result = Schema.execute(query_string, except: private_members)
|
16
|
-
#
|
17
|
-
# @example Custom filter implementation
|
18
|
-
# # It must respond to `#call(member)`.
|
19
|
-
# class MissingRequiredFlags
|
20
|
-
# def initialize(user)
|
21
|
-
# @user = user
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# # Return `false` if any required flags are missing
|
25
|
-
# def call(member, ctx)
|
26
|
-
# member.metadata[:required_flags].any? do |flag|
|
27
|
-
# !@user.has_flag?(flag)
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# # Then, use the custom filter in query:
|
33
|
-
# missing_required_flags = MissingRequiredFlags.new(current_user)
|
34
|
-
#
|
35
|
-
# # This query can only access members which match the user's flags
|
36
|
-
# result = Schema.execute(query_string, except: missing_required_flags)
|
37
|
-
#
|
38
13
|
# @api private
|
39
14
|
class Warden
|
40
15
|
def self.from_context(context)
|
41
|
-
|
16
|
+
context.warden || PassThruWarden
|
17
|
+
rescue NoMethodError
|
18
|
+
# this might be a hash which won't respond to #warden
|
19
|
+
PassThruWarden
|
42
20
|
end
|
43
21
|
|
44
22
|
# @param visibility_method [Symbol] a Warden method to call for this entry
|
@@ -80,20 +58,144 @@ module GraphQL
|
|
80
58
|
def visible_type?(type, ctx); type.visible?(ctx); end
|
81
59
|
def visible_enum_value?(ev, ctx); ev.visible?(ctx); end
|
82
60
|
def visible_type_membership?(tm, ctx); tm.visible?(ctx); end
|
61
|
+
def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
|
62
|
+
def arguments(owner, ctx); owner.arguments(ctx); end
|
63
|
+
def loadable?(type, ctx); type.visible?(ctx); end
|
64
|
+
def schema_subset
|
65
|
+
@schema_subset ||= Warden::SchemaSubset.new(self)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class NullWarden
|
71
|
+
def initialize(_filter = nil, context:, schema:)
|
72
|
+
@schema = schema
|
73
|
+
@schema_subset = Warden::SchemaSubset.new(self)
|
74
|
+
end
|
75
|
+
|
76
|
+
# @api private
|
77
|
+
module NullSubset
|
78
|
+
def self.new(query)
|
79
|
+
NullWarden.new(context: query.context, schema: query.schema).schema_subset
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
attr_reader :schema_subset
|
84
|
+
|
85
|
+
def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
|
86
|
+
def visible_argument?(arg_defn, _ctx = nil); true; end
|
87
|
+
def visible_type?(type_defn, _ctx = nil); true; end
|
88
|
+
def visible_enum_value?(enum_value, _ctx = nil); true; end
|
89
|
+
def visible_type_membership?(type_membership, _ctx = nil); true; end
|
90
|
+
def interface_type_memberships(obj_type, _ctx = nil); obj_type.interface_type_memberships; end
|
91
|
+
def get_type(type_name); @schema.get_type(type_name); end # rubocop:disable Development/ContextIsPassedCop
|
92
|
+
def arguments(argument_owner, ctx = nil); argument_owner.all_argument_definitions; end
|
93
|
+
def enum_values(enum_defn); enum_defn.enum_values; end # rubocop:disable Development/ContextIsPassedCop
|
94
|
+
def get_argument(parent_type, argument_name); parent_type.get_argument(argument_name); end # rubocop:disable Development/ContextIsPassedCop
|
95
|
+
def types; @schema.types; end # rubocop:disable Development/ContextIsPassedCop
|
96
|
+
def root_type_for_operation(op_name); @schema.root_type_for_operation(op_name); end
|
97
|
+
def directives; @schema.directives.values; end
|
98
|
+
def fields(type_defn); type_defn.all_field_definitions; end # rubocop:disable Development/ContextIsPassedCop
|
99
|
+
def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
|
100
|
+
def reachable_type?(type_name); true; end
|
101
|
+
def loadable?(type, _ctx); true; end
|
102
|
+
def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
|
103
|
+
def possible_types(type_defn); @schema.possible_types(type_defn); end
|
104
|
+
def interfaces(obj_type); obj_type.interfaces; end
|
105
|
+
end
|
106
|
+
|
107
|
+
def schema_subset
|
108
|
+
@schema_subset ||= SchemaSubset.new(self)
|
109
|
+
end
|
110
|
+
|
111
|
+
class SchemaSubset
|
112
|
+
def initialize(warden)
|
113
|
+
@warden = warden
|
114
|
+
end
|
115
|
+
|
116
|
+
def directives
|
117
|
+
@warden.directives
|
118
|
+
end
|
119
|
+
|
120
|
+
def directive_exists?(dir_name)
|
121
|
+
@warden.directives.any? { |d| d.graphql_name == dir_name }
|
122
|
+
end
|
123
|
+
|
124
|
+
def type(name)
|
125
|
+
@warden.get_type(name)
|
126
|
+
end
|
127
|
+
|
128
|
+
def field(owner, field_name)
|
129
|
+
@warden.get_field(owner, field_name)
|
130
|
+
end
|
131
|
+
|
132
|
+
def argument(owner, arg_name)
|
133
|
+
@warden.get_argument(owner, arg_name)
|
134
|
+
end
|
135
|
+
|
136
|
+
def query_root
|
137
|
+
@warden.root_type_for_operation("query")
|
138
|
+
end
|
139
|
+
|
140
|
+
def mutation_root
|
141
|
+
@warden.root_type_for_operation("mutation")
|
142
|
+
end
|
143
|
+
|
144
|
+
def subscription_root
|
145
|
+
@warden.root_type_for_operation("subscription")
|
146
|
+
end
|
147
|
+
|
148
|
+
def arguments(owner)
|
149
|
+
@warden.arguments(owner)
|
150
|
+
end
|
151
|
+
|
152
|
+
def fields(owner)
|
153
|
+
@warden.fields(owner)
|
154
|
+
end
|
155
|
+
|
156
|
+
def possible_types(type)
|
157
|
+
@warden.possible_types(type)
|
158
|
+
end
|
159
|
+
|
160
|
+
def enum_values(enum_type)
|
161
|
+
@warden.enum_values(enum_type)
|
162
|
+
end
|
163
|
+
|
164
|
+
def all_types
|
165
|
+
@warden.reachable_types
|
166
|
+
end
|
167
|
+
|
168
|
+
def interfaces(obj_type)
|
169
|
+
@warden.interfaces(obj_type)
|
170
|
+
end
|
171
|
+
|
172
|
+
def loadable?(t, ctx) # TODO remove ctx here?
|
173
|
+
@warden.loadable?(t, ctx)
|
174
|
+
end
|
175
|
+
|
176
|
+
def reachable_type?(type_name)
|
177
|
+
@warden.reachable_type?(type_name)
|
83
178
|
end
|
84
179
|
end
|
85
180
|
|
86
|
-
# @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
|
87
181
|
# @param context [GraphQL::Query::Context]
|
88
182
|
# @param schema [GraphQL::Schema]
|
89
|
-
def initialize(
|
183
|
+
def initialize(context:, schema:)
|
90
184
|
@schema = schema
|
91
185
|
# Cache these to avoid repeated hits to the inheritance chain when one isn't present
|
92
186
|
@query = @schema.query
|
93
187
|
@mutation = @schema.mutation
|
94
188
|
@subscription = @schema.subscription
|
95
189
|
@context = context
|
96
|
-
@visibility_cache = read_through { |m|
|
190
|
+
@visibility_cache = read_through { |m| schema.visible?(m, context) }
|
191
|
+
@visibility_cache.compare_by_identity
|
192
|
+
# Initialize all ivars to improve object shape consistency:
|
193
|
+
@types = @visible_types = @reachable_types = @visible_parent_fields =
|
194
|
+
@visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
|
195
|
+
@visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
|
196
|
+
@visible_and_reachable_type = @unions = @unfiltered_interfaces =
|
197
|
+
@reachable_type_set = @schema_subset =
|
198
|
+
nil
|
97
199
|
end
|
98
200
|
|
99
201
|
# @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
|
@@ -109,6 +211,11 @@ module GraphQL
|
|
109
211
|
end
|
110
212
|
end
|
111
213
|
|
214
|
+
# @return [Boolean] True if this type is used for `loads:` but not in the schema otherwise and not _explicitly_ hidden.
|
215
|
+
def loadable?(type, _ctx)
|
216
|
+
!reachable_type_set.include?(type) && visible_type?(type)
|
217
|
+
end
|
218
|
+
|
112
219
|
# @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
|
113
220
|
def get_type(type_name)
|
114
221
|
@visible_types ||= read_through do |name|
|
@@ -174,14 +281,29 @@ module GraphQL
|
|
174
281
|
|
175
282
|
# @param argument_owner [GraphQL::Field, GraphQL::InputObjectType]
|
176
283
|
# @return [Array<GraphQL::Argument>] Visible arguments on `argument_owner`
|
177
|
-
def arguments(argument_owner)
|
178
|
-
@visible_arguments ||= read_through { |o|
|
284
|
+
def arguments(argument_owner, ctx = nil)
|
285
|
+
@visible_arguments ||= read_through { |o|
|
286
|
+
args = o.arguments(@context)
|
287
|
+
if args.any?
|
288
|
+
args = args.values
|
289
|
+
args.select! { |a| visible_argument?(a, @context) }
|
290
|
+
args
|
291
|
+
else
|
292
|
+
EmptyObjects::EMPTY_ARRAY
|
293
|
+
end
|
294
|
+
}
|
179
295
|
@visible_arguments[argument_owner]
|
180
296
|
end
|
181
297
|
|
182
298
|
# @return [Array<GraphQL::EnumType::EnumValue>] Visible members of `enum_defn`
|
183
299
|
def enum_values(enum_defn)
|
184
|
-
@visible_enum_arrays ||= read_through { |e|
|
300
|
+
@visible_enum_arrays ||= read_through { |e|
|
301
|
+
values = e.enum_values(@context)
|
302
|
+
if values.size == 0
|
303
|
+
raise GraphQL::Schema::Enum::MissingValuesError.new(e)
|
304
|
+
end
|
305
|
+
values
|
306
|
+
}
|
185
307
|
@visible_enum_arrays[enum_defn]
|
186
308
|
end
|
187
309
|
|
@@ -192,7 +314,13 @@ module GraphQL
|
|
192
314
|
|
193
315
|
# @return [Array<GraphQL::InterfaceType>] Visible interfaces implemented by `obj_type`
|
194
316
|
def interfaces(obj_type)
|
195
|
-
@visible_interfaces ||= read_through { |t|
|
317
|
+
@visible_interfaces ||= read_through { |t|
|
318
|
+
ints = t.interfaces(@context)
|
319
|
+
if ints.any?
|
320
|
+
ints.select! { |i| visible_type?(i) }
|
321
|
+
end
|
322
|
+
ints
|
323
|
+
}
|
196
324
|
@visible_interfaces[obj_type]
|
197
325
|
end
|
198
326
|
|
@@ -233,6 +361,13 @@ module GraphQL
|
|
233
361
|
visible?(type_membership)
|
234
362
|
end
|
235
363
|
|
364
|
+
def interface_type_memberships(obj_type, _ctx = nil)
|
365
|
+
@type_memberships ||= read_through do |obj_t|
|
366
|
+
obj_t.interface_type_memberships
|
367
|
+
end
|
368
|
+
@type_memberships[obj_type]
|
369
|
+
end
|
370
|
+
|
236
371
|
private
|
237
372
|
|
238
373
|
def visible_and_reachable_type?(type_defn)
|
@@ -241,11 +376,26 @@ module GraphQL
|
|
241
376
|
next true if root_type?(type_defn) || type_defn.introspection?
|
242
377
|
|
243
378
|
if type_defn.kind.union?
|
244
|
-
|
379
|
+
possible_types(type_defn).any? && (referenced?(type_defn) || orphan_type?(type_defn))
|
245
380
|
elsif type_defn.kind.interface?
|
246
|
-
|
381
|
+
if possible_types(type_defn).any?
|
382
|
+
true
|
383
|
+
else
|
384
|
+
if @context.respond_to?(:logger) && (logger = @context.logger)
|
385
|
+
logger.debug { "Interface `#{type_defn.graphql_name}` hidden because it has no visible implementers" }
|
386
|
+
end
|
387
|
+
false
|
388
|
+
end
|
247
389
|
else
|
248
|
-
referenced?(type_defn)
|
390
|
+
if referenced?(type_defn)
|
391
|
+
true
|
392
|
+
elsif type_defn.kind.object?
|
393
|
+
# Show this object if it belongs to ...
|
394
|
+
interfaces(type_defn).any? { |t| referenced?(t) } || # an interface which is referenced in the schema
|
395
|
+
union_memberships(type_defn).any? { |t| referenced?(t) || orphan_type?(t) } # or a union which is referenced or added via orphan_types
|
396
|
+
else
|
397
|
+
false
|
398
|
+
end
|
249
399
|
end
|
250
400
|
end
|
251
401
|
|
@@ -300,39 +450,26 @@ module GraphQL
|
|
300
450
|
end
|
301
451
|
|
302
452
|
def referenced?(type_defn)
|
303
|
-
|
304
|
-
graphql_name = type_defn.unwrap.graphql_name
|
305
|
-
members = @references_to[graphql_name] || NO_REFERENCES
|
453
|
+
members = @schema.references_to(type_defn)
|
306
454
|
members.any? { |m| visible?(m) }
|
307
455
|
end
|
308
456
|
|
309
|
-
NO_REFERENCES = [].freeze
|
310
|
-
|
311
457
|
def orphan_type?(type_defn)
|
312
458
|
@schema.orphan_types.include?(type_defn)
|
313
459
|
end
|
314
460
|
|
315
|
-
def visible_abstract_type?(type_defn)
|
316
|
-
type_defn.kind.object? && (
|
317
|
-
interfaces(type_defn).any? ||
|
318
|
-
union_memberships(type_defn).any?
|
319
|
-
)
|
320
|
-
end
|
321
|
-
|
322
|
-
def visible_possible_types?(type_defn)
|
323
|
-
possible_types(type_defn).any? { |t| visible_and_reachable_type?(t) }
|
324
|
-
end
|
325
|
-
|
326
461
|
def visible?(member)
|
327
462
|
@visibility_cache[member]
|
328
463
|
end
|
329
464
|
|
330
465
|
def read_through
|
331
|
-
Hash.new { |h, k| h[k] = yield(k) }
|
466
|
+
h = Hash.new { |h, k| h[k] = yield(k) }
|
467
|
+
h.compare_by_identity
|
468
|
+
h
|
332
469
|
end
|
333
470
|
|
334
471
|
def reachable_type_set
|
335
|
-
return @reachable_type_set if
|
472
|
+
return @reachable_type_set if @reachable_type_set
|
336
473
|
|
337
474
|
@reachable_type_set = Set.new
|
338
475
|
rt_hash = {}
|
@@ -359,54 +496,62 @@ module GraphQL
|
|
359
496
|
end
|
360
497
|
end
|
361
498
|
|
499
|
+
included_interface_possible_types_set = Set.new
|
500
|
+
|
362
501
|
until unvisited_types.empty?
|
363
502
|
type = unvisited_types.pop
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
503
|
+
visit_type(type, unvisited_types, @reachable_type_set, rt_hash, included_interface_possible_types_set, include_interface_possible_types: false)
|
504
|
+
end
|
505
|
+
|
506
|
+
@reachable_type_set
|
507
|
+
end
|
508
|
+
|
509
|
+
def visit_type(type, unvisited_types, visited_type_set, type_by_name_hash, included_interface_possible_types_set, include_interface_possible_types:)
|
510
|
+
if visited_type_set.add?(type) || (include_interface_possible_types && type.kind.interface? && included_interface_possible_types_set.add?(type))
|
511
|
+
type_by_name = type_by_name_hash[type.graphql_name] ||= type
|
512
|
+
if type_by_name != type
|
513
|
+
name_1, name_2 = [type.inspect, type_by_name.inspect].sort
|
514
|
+
raise DuplicateNamesError.new(
|
515
|
+
duplicated_name: type.graphql_name, duplicated_definition_1: name_1, duplicated_definition_2: name_2
|
516
|
+
)
|
517
|
+
end
|
518
|
+
if type.kind.input_object?
|
519
|
+
# recurse into visible arguments
|
520
|
+
arguments(type).each do |argument|
|
521
|
+
argument_type = argument.type.unwrap
|
522
|
+
unvisited_types << argument_type
|
370
523
|
end
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
# recurse into visible
|
379
|
-
|
380
|
-
unvisited_types <<
|
524
|
+
elsif type.kind.union?
|
525
|
+
# recurse into visible possible types
|
526
|
+
possible_types(type).each do |possible_type|
|
527
|
+
unvisited_types << possible_type
|
528
|
+
end
|
529
|
+
elsif type.kind.fields?
|
530
|
+
if type.kind.object?
|
531
|
+
# recurse into visible implemented interfaces
|
532
|
+
interfaces(type).each do |interface|
|
533
|
+
unvisited_types << interface
|
381
534
|
end
|
382
|
-
elsif
|
383
|
-
|
384
|
-
|
385
|
-
possible_types(type).each do |possible_type|
|
386
|
-
unvisited_types << possible_type
|
387
|
-
end
|
388
|
-
elsif type.kind.object?
|
389
|
-
# recurse into visible implemented interfaces
|
390
|
-
interfaces(type).each do |interface|
|
391
|
-
unvisited_types << interface
|
392
|
-
end
|
535
|
+
elsif include_interface_possible_types
|
536
|
+
possible_types(type).each do |pt|
|
537
|
+
unvisited_types << pt
|
393
538
|
end
|
539
|
+
end
|
540
|
+
# Don't visit interface possible types -- it's not enough to justify visibility
|
394
541
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
542
|
+
# recurse into visible fields
|
543
|
+
fields(type).each do |field|
|
544
|
+
field_type = field.type.unwrap
|
545
|
+
# In this case, if it's an interface, we want to include
|
546
|
+
visit_type(field_type, unvisited_types, visited_type_set, type_by_name_hash, included_interface_possible_types_set, include_interface_possible_types: true)
|
547
|
+
# recurse into visible arguments
|
548
|
+
arguments(field).each do |argument|
|
549
|
+
argument_type = argument.type.unwrap
|
550
|
+
unvisited_types << argument_type
|
404
551
|
end
|
405
552
|
end
|
406
553
|
end
|
407
554
|
end
|
408
|
-
|
409
|
-
@reachable_type_set
|
410
555
|
end
|
411
556
|
end
|
412
557
|
end
|