graphql 2.4.5 → 2.5.21
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/lib/generators/graphql/detailed_trace_generator.rb +77 -0
- data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
- data/lib/graphql/analysis/analyzer.rb +2 -1
- data/lib/graphql/analysis/query_complexity.rb +87 -7
- data/lib/graphql/analysis/visitor.rb +37 -40
- data/lib/graphql/analysis.rb +12 -9
- data/lib/graphql/autoload.rb +1 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/current.rb +6 -1
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +24 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +96 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +38 -15
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/source.rb +18 -6
- data/lib/graphql/dataloader.rb +110 -26
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/execution/interpreter/resolve.rb +10 -16
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +58 -5
- data/lib/graphql/execution/interpreter/runtime.rb +229 -93
- data/lib/graphql/execution/interpreter.rb +15 -24
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next/field_resolve_step.rb +690 -0
- data/lib/graphql/execution/next/load_argument_step.rb +60 -0
- data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
- data/lib/graphql/execution/next/runner.rb +389 -0
- data/lib/graphql/execution/next/selections_step.rb +37 -0
- data/lib/graphql/execution/next.rb +69 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +13 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +11 -3
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +25 -16
- data/lib/graphql/language/document_from_schema_definition.rb +2 -1
- data/lib/graphql/language/lexer.rb +16 -5
- data/lib/graphql/language/nodes.rb +8 -1
- data/lib/graphql/language/parser.rb +16 -8
- data/lib/graphql/language/static_visitor.rb +37 -33
- data/lib/graphql/language/visitor.rb +59 -55
- data/lib/graphql/language.rb +21 -12
- data/lib/graphql/pagination/connection.rb +2 -0
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/query/context.rb +6 -10
- data/lib/graphql/query/null_context.rb +9 -3
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query.rb +64 -64
- data/lib/graphql/railtie.rb +1 -1
- data/lib/graphql/schema/addition.rb +3 -1
- data/lib/graphql/schema/always_visible.rb +1 -0
- data/lib/graphql/schema/argument.rb +24 -8
- data/lib/graphql/schema/build_from_definition.rb +113 -54
- data/lib/graphql/schema/directive/flagged.rb +2 -0
- data/lib/graphql/schema/directive.rb +52 -2
- data/lib/graphql/schema/enum.rb +36 -1
- data/lib/graphql/schema/enum_value.rb +1 -1
- data/lib/graphql/schema/field/connection_extension.rb +15 -35
- data/lib/graphql/schema/field/scope_extension.rb +22 -13
- data/lib/graphql/schema/field.rb +101 -51
- data/lib/graphql/schema/field_extension.rb +33 -0
- data/lib/graphql/schema/input_object.rb +45 -38
- data/lib/graphql/schema/interface.rb +2 -1
- data/lib/graphql/schema/list.rb +1 -1
- data/lib/graphql/schema/member/base_dsl_methods.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +56 -19
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +79 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +81 -5
- data/lib/graphql/schema/member/has_interfaces.rb +3 -3
- data/lib/graphql/schema/member/scoped.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/object.rb +18 -8
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/resolver.rb +52 -6
- data/lib/graphql/schema/scalar.rb +1 -6
- data/lib/graphql/schema/subscription.rb +50 -4
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/validator/required_validator.rb +71 -14
- data/lib/graphql/schema/visibility/migration.rb +3 -2
- data/lib/graphql/schema/visibility/profile.rb +115 -23
- data/lib/graphql/schema/visibility.rb +49 -32
- data/lib/graphql/schema/warden.rb +23 -2
- data/lib/graphql/schema.rb +333 -68
- data/lib/graphql/static_validation/all_rules.rb +2 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +79 -17
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +6 -2
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +12 -1
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/subscriptions.rb +1 -1
- data/lib/graphql/testing/helpers.rb +17 -11
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +1 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +9 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +7 -0
- data/lib/graphql/tracing/appsignal_trace.rb +32 -55
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +46 -158
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +184 -34
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +864 -0
- data/lib/graphql/tracing/platform_trace.rb +5 -0
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
- data/lib/graphql/tracing/prometheus_trace.rb +72 -68
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -55
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +64 -94
- data/lib/graphql/tracing/statsd_trace.rb +33 -41
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +111 -1
- data/lib/graphql/tracing.rb +31 -30
- data/lib/graphql/type_kinds.rb +1 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +9 -7
- data/lib/graphql/types/relay/edge_behaviors.rb +5 -4
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/unauthorized_error.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +12 -31
- metadata +174 -11
- data/lib/graphql/backtrace/inspect_result.rb +0 -38
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
|
@@ -18,7 +18,7 @@ module GraphQL
|
|
|
18
18
|
if ctx.respond_to?(:types) && (types = ctx.types).is_a?(self)
|
|
19
19
|
types
|
|
20
20
|
else
|
|
21
|
-
schema.visibility.profile_for(ctx
|
|
21
|
+
schema.visibility.profile_for(ctx)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -31,10 +31,37 @@ module GraphQL
|
|
|
31
31
|
# @return [Symbol, nil]
|
|
32
32
|
attr_reader :name
|
|
33
33
|
|
|
34
|
-
def
|
|
34
|
+
def freeze
|
|
35
|
+
@cached_visible.default_proc = nil
|
|
36
|
+
@cached_visible_fields.default_proc = nil
|
|
37
|
+
@cached_visible_fields.each do |type, fields|
|
|
38
|
+
fields.default_proc = nil
|
|
39
|
+
end
|
|
40
|
+
@cached_visible_arguments.default_proc = nil
|
|
41
|
+
@cached_visible_arguments.each do |type, fields|
|
|
42
|
+
fields.default_proc = nil
|
|
43
|
+
end
|
|
44
|
+
@cached_parent_fields.default_proc = nil
|
|
45
|
+
@cached_parent_fields.each do |type, fields|
|
|
46
|
+
fields.default_proc = nil
|
|
47
|
+
end
|
|
48
|
+
@cached_parent_arguments.default_proc = nil
|
|
49
|
+
@cached_parent_arguments.each do |type, args|
|
|
50
|
+
args.default_proc = nil
|
|
51
|
+
end
|
|
52
|
+
@cached_possible_types.default_proc = nil
|
|
53
|
+
@cached_enum_values.default_proc = nil
|
|
54
|
+
@cached_fields.default_proc = nil
|
|
55
|
+
@cached_arguments.default_proc = nil
|
|
56
|
+
@loadable_possible_types.default_proc = nil
|
|
57
|
+
super
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def initialize(name: nil, context:, schema:, visibility:)
|
|
35
61
|
@name = name
|
|
36
62
|
@context = context
|
|
37
63
|
@schema = schema
|
|
64
|
+
@visibility = visibility
|
|
38
65
|
@all_types = {}
|
|
39
66
|
@all_types_loaded = false
|
|
40
67
|
@unvisited_types = []
|
|
@@ -47,12 +74,21 @@ module GraphQL
|
|
|
47
74
|
end.compare_by_identity
|
|
48
75
|
}.compare_by_identity
|
|
49
76
|
|
|
50
|
-
@cached_visible_arguments = Hash.new do |h,
|
|
51
|
-
h[
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
@cached_visible_arguments = Hash.new do |h, owner|
|
|
78
|
+
h[owner] = Hash.new do |h2, arg|
|
|
79
|
+
h2[arg] = if @cached_visible[arg] && (arg_type = arg.type.unwrap) && @cached_visible[arg_type]
|
|
80
|
+
case owner
|
|
81
|
+
when GraphQL::Schema::Field
|
|
82
|
+
@cached_visible_fields[owner.owner][owner]
|
|
83
|
+
when Class
|
|
84
|
+
@cached_visible[owner]
|
|
85
|
+
else
|
|
86
|
+
raise "Unexpected argument owner for `#{arg.path}`: #{owner.inspect}"
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
false
|
|
90
|
+
end
|
|
91
|
+
end.compare_by_identity
|
|
56
92
|
end.compare_by_identity
|
|
57
93
|
|
|
58
94
|
@cached_parent_fields = Hash.new do |h, type|
|
|
@@ -82,8 +118,10 @@ module GraphQL
|
|
|
82
118
|
end.compare_by_identity
|
|
83
119
|
|
|
84
120
|
@cached_arguments = Hash.new do |h, owner|
|
|
85
|
-
h[owner] = non_duplicate_items(owner.all_argument_definitions, @cached_visible_arguments)
|
|
121
|
+
h[owner] = non_duplicate_items(owner.all_argument_definitions, @cached_visible_arguments[owner])
|
|
86
122
|
end.compare_by_identity
|
|
123
|
+
|
|
124
|
+
@loadable_possible_types = Hash.new { |h, union_type| h[union_type] = union_type.possible_types }.compare_by_identity
|
|
87
125
|
end
|
|
88
126
|
|
|
89
127
|
def field_on_visible_interface?(field, owner)
|
|
@@ -111,7 +149,7 @@ module GraphQL
|
|
|
111
149
|
end
|
|
112
150
|
|
|
113
151
|
def type(type_name)
|
|
114
|
-
t = @
|
|
152
|
+
t = @visibility.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
|
115
153
|
if t
|
|
116
154
|
if t.is_a?(Array)
|
|
117
155
|
vis_t = nil
|
|
@@ -157,7 +195,7 @@ module GraphQL
|
|
|
157
195
|
end
|
|
158
196
|
end
|
|
159
197
|
end
|
|
160
|
-
visible_f
|
|
198
|
+
visible_f&.ensure_loaded
|
|
161
199
|
elsif f && @cached_visible_fields[owner][f.ensure_loaded]
|
|
162
200
|
f
|
|
163
201
|
else
|
|
@@ -178,7 +216,7 @@ module GraphQL
|
|
|
178
216
|
if arg.is_a?(Array)
|
|
179
217
|
visible_arg = nil
|
|
180
218
|
arg.each do |arg_defn|
|
|
181
|
-
if @cached_visible_arguments[arg_defn]
|
|
219
|
+
if @cached_visible_arguments[owner][arg_defn]
|
|
182
220
|
if visible_arg.nil?
|
|
183
221
|
visible_arg = arg_defn
|
|
184
222
|
else
|
|
@@ -188,7 +226,7 @@ module GraphQL
|
|
|
188
226
|
end
|
|
189
227
|
visible_arg
|
|
190
228
|
else
|
|
191
|
-
if arg && @cached_visible_arguments[arg]
|
|
229
|
+
if arg && @cached_visible_arguments[owner][arg]
|
|
192
230
|
arg
|
|
193
231
|
else
|
|
194
232
|
nil
|
|
@@ -239,14 +277,17 @@ module GraphQL
|
|
|
239
277
|
end
|
|
240
278
|
|
|
241
279
|
def directives
|
|
242
|
-
@all_directives ||= @
|
|
243
|
-
@cached_visible[dir] && @
|
|
280
|
+
@all_directives ||= @visibility.all_directives.select { |dir|
|
|
281
|
+
@cached_visible[dir] && @visibility.all_references[dir].any? { |ref| ref == true || (@cached_visible[ref] && referenced?(ref)) }
|
|
244
282
|
}
|
|
245
283
|
end
|
|
246
284
|
|
|
247
285
|
def loadable?(t, _ctx)
|
|
248
|
-
|
|
249
|
-
|
|
286
|
+
@cached_visible[t] && !referenced?(t)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def loadable_possible_types(t, _ctx)
|
|
290
|
+
@loadable_possible_types[t]
|
|
250
291
|
end
|
|
251
292
|
|
|
252
293
|
def loaded_types
|
|
@@ -262,13 +303,51 @@ module GraphQL
|
|
|
262
303
|
@cached_visible[enum_value]
|
|
263
304
|
end
|
|
264
305
|
|
|
306
|
+
def preload
|
|
307
|
+
load_all_types
|
|
308
|
+
@all_types.each do |type_name, type_defn|
|
|
309
|
+
if type_defn.kind.fields?
|
|
310
|
+
fields(type_defn).each do |f|
|
|
311
|
+
field(type_defn, f.graphql_name)
|
|
312
|
+
arguments(f).each do |arg|
|
|
313
|
+
argument(f, arg.graphql_name)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
@schema.introspection_system.dynamic_fields.each do |f|
|
|
317
|
+
field(type_defn, f.graphql_name)
|
|
318
|
+
end
|
|
319
|
+
elsif type_defn.kind.input_object?
|
|
320
|
+
arguments(type_defn).each do |arg|
|
|
321
|
+
argument(type_defn, arg.graphql_name)
|
|
322
|
+
end
|
|
323
|
+
elsif type_defn.kind.enum?
|
|
324
|
+
enum_values(type_defn)
|
|
325
|
+
end
|
|
326
|
+
# Lots more to do here
|
|
327
|
+
end
|
|
328
|
+
@schema.introspection_system.entry_points.each do |f|
|
|
329
|
+
arguments(f).each do |arg|
|
|
330
|
+
argument(f, arg.graphql_name)
|
|
331
|
+
end
|
|
332
|
+
field(@schema.query, f.graphql_name)
|
|
333
|
+
end
|
|
334
|
+
@schema.introspection_system.dynamic_fields.each do |f|
|
|
335
|
+
arguments(f).each do |arg|
|
|
336
|
+
argument(f, arg.graphql_name)
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
end
|
|
341
|
+
|
|
265
342
|
private
|
|
266
343
|
|
|
267
344
|
def non_duplicate_items(definitions, visibility_cache)
|
|
268
345
|
non_dups = []
|
|
346
|
+
names = Set.new
|
|
269
347
|
definitions.each do |defn|
|
|
270
348
|
if visibility_cache[defn]
|
|
271
|
-
if (
|
|
349
|
+
if !names.add?(defn.graphql_name)
|
|
350
|
+
dup_defn = non_dups.find { |d| d.graphql_name == defn.graphql_name }
|
|
272
351
|
raise_duplicate_definition(dup_defn, defn)
|
|
273
352
|
end
|
|
274
353
|
non_dups << defn
|
|
@@ -286,7 +365,7 @@ module GraphQL
|
|
|
286
365
|
@all_types_loaded = true
|
|
287
366
|
visit = Visibility::Visit.new(@schema) do |member|
|
|
288
367
|
if member.is_a?(Module) && member.respond_to?(:kind)
|
|
289
|
-
if @cached_visible[member]
|
|
368
|
+
if @cached_visible[member] && referenced?(member)
|
|
290
369
|
type_name = member.graphql_name
|
|
291
370
|
if (prev_t = @all_types[type_name]) && !prev_t.equal?(member)
|
|
292
371
|
raise_duplicate_definition(member, prev_t)
|
|
@@ -306,16 +385,29 @@ module GraphQL
|
|
|
306
385
|
end
|
|
307
386
|
|
|
308
387
|
def referenced?(type_defn)
|
|
309
|
-
@
|
|
388
|
+
@visibility.all_references[type_defn].any? do |ref|
|
|
389
|
+
case ref
|
|
390
|
+
when GraphQL::Schema::Argument
|
|
391
|
+
@cached_visible_arguments[ref.owner][ref]
|
|
392
|
+
when GraphQL::Schema::Field
|
|
393
|
+
@cached_visible_fields[ref.owner][ref]
|
|
394
|
+
when Module
|
|
395
|
+
@cached_visible[ref]
|
|
396
|
+
when true
|
|
397
|
+
true
|
|
398
|
+
end
|
|
399
|
+
end
|
|
310
400
|
end
|
|
311
401
|
|
|
312
402
|
def possible_types_for(type)
|
|
313
403
|
case type.kind.name
|
|
314
404
|
when "INTERFACE"
|
|
315
405
|
pts = []
|
|
316
|
-
@
|
|
317
|
-
if
|
|
318
|
-
|
|
406
|
+
@visibility.all_interface_type_memberships[type].each do |impl_type, type_memberships|
|
|
407
|
+
if impl_type.kind.object? && referenced?(impl_type) && @cached_visible[impl_type]
|
|
408
|
+
if type_memberships.any? { |itm| @cached_visible[itm] }
|
|
409
|
+
pts << impl_type
|
|
410
|
+
end
|
|
319
411
|
end
|
|
320
412
|
end
|
|
321
413
|
pts
|
|
@@ -10,13 +10,14 @@ module GraphQL
|
|
|
10
10
|
class Visibility
|
|
11
11
|
# @param schema [Class<GraphQL::Schema>]
|
|
12
12
|
# @param profiles [Hash<Symbol => Hash>] A hash of `name => context` pairs for preloading visibility profiles
|
|
13
|
-
# @param preload [Boolean] if `true`, load the default schema profile and all named profiles immediately (defaults to `true` for `Rails.env.production?`)
|
|
13
|
+
# @param preload [Boolean] if `true`, load the default schema profile and all named profiles immediately (defaults to `true` for `Rails.env.production?` and `Rails.env.staging?`)
|
|
14
14
|
# @param migration_errors [Boolean] if `true`, raise an error when `Visibility` and `Warden` return different results
|
|
15
|
-
def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails) ? Rails.env.production? : nil), migration_errors: false)
|
|
15
|
+
def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails.env) ? (Rails.env.production? || Rails.env.staging?) : nil), migration_errors: false)
|
|
16
|
+
profiles&.each { |name, ctx|
|
|
17
|
+
ctx[:visibility_profile] = name
|
|
18
|
+
ctx.freeze
|
|
19
|
+
}
|
|
16
20
|
schema.visibility = self.new(schema, dynamic: dynamic, preload: preload, profiles: profiles, migration_errors: migration_errors)
|
|
17
|
-
if preload
|
|
18
|
-
schema.visibility.preload
|
|
19
|
-
end
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def initialize(schema, dynamic:, preload:, profiles:, migration_errors:)
|
|
@@ -39,6 +40,17 @@ module GraphQL
|
|
|
39
40
|
@types = nil
|
|
40
41
|
@all_references = nil
|
|
41
42
|
@loaded_all = false
|
|
43
|
+
if preload
|
|
44
|
+
self.preload
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def freeze
|
|
49
|
+
load_all
|
|
50
|
+
@visit = true
|
|
51
|
+
@interface_type_memberships.default_proc = nil
|
|
52
|
+
@all_references.default_proc = nil
|
|
53
|
+
super
|
|
42
54
|
end
|
|
43
55
|
|
|
44
56
|
def all_directives
|
|
@@ -61,6 +73,8 @@ module GraphQL
|
|
|
61
73
|
@types[type_name]
|
|
62
74
|
end
|
|
63
75
|
|
|
76
|
+
attr_accessor :types
|
|
77
|
+
|
|
64
78
|
def preload?
|
|
65
79
|
@preload
|
|
66
80
|
end
|
|
@@ -81,9 +95,8 @@ module GraphQL
|
|
|
81
95
|
types_to_visit.compact!
|
|
82
96
|
ensure_all_loaded(types_to_visit)
|
|
83
97
|
@profiles.each do |profile_name, example_ctx|
|
|
84
|
-
|
|
85
|
-
prof
|
|
86
|
-
prof.all_types # force loading
|
|
98
|
+
prof = profile_for(example_ctx)
|
|
99
|
+
prof.preload
|
|
87
100
|
end
|
|
88
101
|
end
|
|
89
102
|
|
|
@@ -145,27 +158,27 @@ module GraphQL
|
|
|
145
158
|
|
|
146
159
|
attr_reader :cached_profiles
|
|
147
160
|
|
|
148
|
-
def profile_for(context
|
|
161
|
+
def profile_for(context)
|
|
149
162
|
if !@profiles.empty?
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
visibility_profile = context[:visibility_profile]
|
|
164
|
+
if @profiles.include?(visibility_profile)
|
|
165
|
+
profile_ctx = @profiles[visibility_profile]
|
|
166
|
+
@cached_profiles[visibility_profile] ||= @schema.visibility_profile_class.new(name: visibility_profile, context: profile_ctx, schema: @schema, visibility: self)
|
|
167
|
+
elsif @dynamic
|
|
168
|
+
if context.is_a?(Query::NullContext)
|
|
169
|
+
top_level_profile
|
|
170
|
+
else
|
|
171
|
+
@schema.visibility_profile_class.new(context: context, schema: @schema, visibility: self)
|
|
159
172
|
end
|
|
160
|
-
elsif
|
|
161
|
-
raise ArgumentError, "
|
|
173
|
+
elsif !context.key?(:visibility_profile)
|
|
174
|
+
raise ArgumentError, "#{@schema} expects a visibility profile, but `visibility_profile:` wasn't passed. Provide a `visibility_profile:` value or add `dynamic: true` to your visibility configuration."
|
|
162
175
|
else
|
|
163
|
-
|
|
176
|
+
raise ArgumentError, "`#{visibility_profile.inspect}` isn't allowed for `visibility_profile:` (must be one of #{@profiles.keys.map(&:inspect).join(", ")}). Or, add `#{visibility_profile.inspect}` to the list of profiles in the schema definition."
|
|
164
177
|
end
|
|
165
178
|
elsif context.is_a?(Query::NullContext)
|
|
166
179
|
top_level_profile
|
|
167
180
|
else
|
|
168
|
-
@schema.visibility_profile_class.new(context: context, schema: @schema)
|
|
181
|
+
@schema.visibility_profile_class.new(context: context, schema: @schema, visibility: self)
|
|
169
182
|
end
|
|
170
183
|
end
|
|
171
184
|
|
|
@@ -178,7 +191,7 @@ module GraphQL
|
|
|
178
191
|
if refresh
|
|
179
192
|
@top_level_profile = nil
|
|
180
193
|
end
|
|
181
|
-
@top_level_profile ||= @schema.visibility_profile_class.new(context:
|
|
194
|
+
@top_level_profile ||= @schema.visibility_profile_class.new(context: @schema.null_context, schema: @schema, visibility: self)
|
|
182
195
|
end
|
|
183
196
|
|
|
184
197
|
private
|
|
@@ -199,7 +212,11 @@ module GraphQL
|
|
|
199
212
|
def load_all(types: nil)
|
|
200
213
|
if @visit.nil?
|
|
201
214
|
# Set up the visit system
|
|
202
|
-
@interface_type_memberships = Hash.new { |h, interface_type|
|
|
215
|
+
@interface_type_memberships = Hash.new { |h, interface_type|
|
|
216
|
+
h[interface_type] = Hash.new { |h2, obj_type|
|
|
217
|
+
h2[obj_type] = []
|
|
218
|
+
}.compare_by_identity
|
|
219
|
+
}.compare_by_identity
|
|
203
220
|
@directives = []
|
|
204
221
|
@types = {} # String => Module
|
|
205
222
|
@all_references = Hash.new { |h, member| h[member] = Set.new.compare_by_identity }.compare_by_identity
|
|
@@ -222,7 +239,9 @@ module GraphQL
|
|
|
222
239
|
elsif member.respond_to?(:interface_type_memberships)
|
|
223
240
|
member.interface_type_memberships.each do |itm|
|
|
224
241
|
@all_references[itm.abstract_type] << member
|
|
225
|
-
|
|
242
|
+
# `itm.object_type` may not actually be `member` if this implementation
|
|
243
|
+
# is inherited from a superclass
|
|
244
|
+
@interface_type_memberships[itm.abstract_type][member] << itm
|
|
226
245
|
end
|
|
227
246
|
elsif member < GraphQL::Schema::Union
|
|
228
247
|
@unions_for_references << member
|
|
@@ -271,13 +290,11 @@ module GraphQL
|
|
|
271
290
|
|
|
272
291
|
# TODO: somehow don't iterate over all these,
|
|
273
292
|
# only the ones that may have been modified
|
|
274
|
-
@interface_type_memberships.each do |int_type,
|
|
275
|
-
|
|
276
|
-
if !
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
# Add new items only:
|
|
280
|
-
@all_references[implementor_type] |= referers
|
|
293
|
+
@interface_type_memberships.each do |int_type, obj_type_memberships|
|
|
294
|
+
referrers = @all_references[int_type].select { |r| r.is_a?(GraphQL::Schema::Field) }
|
|
295
|
+
if !referrers.empty?
|
|
296
|
+
obj_type_memberships.each_key do |impl_type|
|
|
297
|
+
@all_references[impl_type] |= referrers
|
|
281
298
|
end
|
|
282
299
|
end
|
|
283
300
|
end
|
|
@@ -72,6 +72,7 @@ module GraphQL
|
|
|
72
72
|
def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
|
|
73
73
|
def arguments(owner, ctx); owner.arguments(ctx); end
|
|
74
74
|
def loadable?(type, ctx); type.visible?(ctx); end
|
|
75
|
+
def loadable_possible_types(type, ctx); type.possible_types(ctx); end
|
|
75
76
|
def visibility_profile
|
|
76
77
|
@visibility_profile ||= Warden::VisibilityProfile.new(self)
|
|
77
78
|
end
|
|
@@ -106,6 +107,7 @@ module GraphQL
|
|
|
106
107
|
def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
|
|
107
108
|
def reachable_type?(type_name); true; end
|
|
108
109
|
def loadable?(type, _ctx); true; end
|
|
110
|
+
def loadable_possible_types(abstract_type, _ctx); union_type.possible_types; end
|
|
109
111
|
def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
|
|
110
112
|
def possible_types(type_defn); @schema.possible_types(type_defn, Query::NullContext.instance, false); end
|
|
111
113
|
def interfaces(obj_type); obj_type.interfaces; end
|
|
@@ -180,6 +182,10 @@ module GraphQL
|
|
|
180
182
|
@warden.loadable?(t, ctx)
|
|
181
183
|
end
|
|
182
184
|
|
|
185
|
+
def loadable_possible_types(t, ctx)
|
|
186
|
+
@warden.loadable_possible_types(t, ctx)
|
|
187
|
+
end
|
|
188
|
+
|
|
183
189
|
def reachable_type?(type_name)
|
|
184
190
|
!!@warden.reachable_type?(type_name)
|
|
185
191
|
end
|
|
@@ -204,7 +210,7 @@ module GraphQL
|
|
|
204
210
|
@visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
|
|
205
211
|
@visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
|
|
206
212
|
@visible_and_reachable_type = @unions = @unfiltered_interfaces =
|
|
207
|
-
@reachable_type_set = @visibility_profile =
|
|
213
|
+
@reachable_type_set = @visibility_profile = @loadable_possible_types =
|
|
208
214
|
nil
|
|
209
215
|
@skip_warning = schema.plugins.any? { |(plugin, _opts)| plugin == GraphQL::Schema::Warden }
|
|
210
216
|
end
|
|
@@ -226,7 +232,22 @@ module GraphQL
|
|
|
226
232
|
|
|
227
233
|
# @return [Boolean] True if this type is used for `loads:` but not in the schema otherwise and not _explicitly_ hidden.
|
|
228
234
|
def loadable?(type, _ctx)
|
|
229
|
-
|
|
235
|
+
visible_type?(type) &&
|
|
236
|
+
!referenced?(type) &&
|
|
237
|
+
(type.respond_to?(:interfaces) ? interfaces(type).all? { |i| loadable?(i, _ctx) } : true)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# This abstract type was determined to be used for `loads` only.
|
|
241
|
+
# All its possible types are valid possibilities here -- no filtering.
|
|
242
|
+
def loadable_possible_types(abstract_type, _ctx)
|
|
243
|
+
@loadable_possible_types ||= read_through do |t|
|
|
244
|
+
if t.is_a?(Class) # union
|
|
245
|
+
t.possible_types
|
|
246
|
+
else
|
|
247
|
+
@schema.possible_types(abstract_type)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
@loadable_possible_types[abstract_type]
|
|
230
251
|
end
|
|
231
252
|
|
|
232
253
|
# @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
|