graphql 2.3.10 → 2.3.11
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_generator.rb +46 -0
- data/lib/graphql/current.rb +52 -0
- data/lib/graphql/dataloader.rb +4 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/runtime.rb +2 -8
- data/lib/graphql/execution/interpreter.rb +2 -0
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/schema_type.rb +1 -1
- data/lib/graphql/language/nodes.rb +2 -2
- data/lib/graphql/query/context.rb +4 -2
- data/lib/graphql/query/null_context.rb +0 -4
- data/lib/graphql/query.rb +2 -6
- data/lib/graphql/schema/build_from_definition.rb +8 -1
- data/lib/graphql/schema/directive/flagged.rb +1 -1
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/interface.rb +20 -4
- data/lib/graphql/schema/introspection_system.rb +3 -2
- data/lib/graphql/schema/member/has_arguments.rb +7 -3
- data/lib/graphql/schema/subset.rb +215 -102
- data/lib/graphql/schema/types_migration.rb +185 -0
- data/lib/graphql/schema/warden.rb +4 -7
- data/lib/graphql/schema.rb +30 -22
- data/lib/graphql/testing/helpers.rb +6 -3
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fd32c95924aac8818df81050ba408953617ee69edf0b1e20a16b4927e198230
|
4
|
+
data.tar.gz: a938a1fbde00c6ba934e63f40248b890bc7cbb6d0374d51dd138a88acbc05465
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 595f05e3c28c15e05e65543d48493e101d92ac1238deb0ec9682b2b853293041438652ccdab3dbb9c4242d9b93b29e10da82851f7985ac286916a77697850e0d
|
7
|
+
data.tar.gz: 90c3315b9d03b6c8eb4cee5e44578ec6b968cfe6de5feeaf160ecdbce2428a6a774edff7e06d7e2afaae4a5e33faeb809b629fae486ae1737bcf8bd9d298a0b1
|
@@ -45,6 +45,13 @@ module Graphql
|
|
45
45
|
# post "/graphql", to: "graphql#execute"
|
46
46
|
# ```
|
47
47
|
#
|
48
|
+
# Add ActiveRecord::QueryLogs metadata:
|
49
|
+
# ```ruby
|
50
|
+
# current_graphql_operation: -> { GraphQL::Current.operation_name },
|
51
|
+
# current_graphql_field: -> { GraphQL::Current.field&.path },
|
52
|
+
# current_dataloader_source: -> { GraphQL::Current.dataloader_source_class },
|
53
|
+
# ```
|
54
|
+
#
|
48
55
|
# Accept a `--batch` option which adds `GraphQL::Batch` setup.
|
49
56
|
#
|
50
57
|
# Use `--skip-graphiql` to skip `graphiql-rails` installation.
|
@@ -92,6 +99,11 @@ module Graphql
|
|
92
99
|
default: false,
|
93
100
|
desc: "Use GraphQL Playground over Graphiql as IDE"
|
94
101
|
|
102
|
+
class_option :skip_query_logs,
|
103
|
+
type: :boolean,
|
104
|
+
default: false,
|
105
|
+
desc: "Skip ActiveRecord::QueryLogs hooks in config/application.rb"
|
106
|
+
|
95
107
|
# These two options are taken from Rails' own generators'
|
96
108
|
class_option :api,
|
97
109
|
type: :boolean,
|
@@ -180,6 +192,40 @@ RUBY
|
|
180
192
|
install_relay
|
181
193
|
end
|
182
194
|
|
195
|
+
if !options[:skip_query_logs]
|
196
|
+
config_file = "config/application.rb"
|
197
|
+
current_app_rb = File.read(Rails.root.join(config_file))
|
198
|
+
existing_log_tags_pattern = /config.active_record.query_log_tags = \[\n?(\s*:[a-z_]+,?\s*\n?|\s*#[^\]]*\n)*/m
|
199
|
+
existing_log_tags = existing_log_tags_pattern.match(current_app_rb)
|
200
|
+
if existing_log_tags && behavior == :invoke
|
201
|
+
code = <<-RUBY
|
202
|
+
# GraphQL-Ruby query log tags:
|
203
|
+
current_graphql_operation: -> { GraphQL::Current.operation_name },
|
204
|
+
current_graphql_field: -> { GraphQL::Current.field&.path },
|
205
|
+
current_dataloader_source: -> { GraphQL::Current.dataloader_source_class },
|
206
|
+
RUBY
|
207
|
+
if !existing_log_tags.to_s.end_with?(",")
|
208
|
+
code = ",\n#{code} "
|
209
|
+
end
|
210
|
+
# Try to insert this code _after_ any plain symbol entries in the array of query log tags:
|
211
|
+
after_code = existing_log_tags_pattern
|
212
|
+
else
|
213
|
+
code = <<-RUBY
|
214
|
+
config.active_record.query_log_tags_enabled = true
|
215
|
+
config.active_record.query_log_tags = [
|
216
|
+
# Rails query log tags:
|
217
|
+
:application, :controller, :action, :job,
|
218
|
+
# GraphQL-Ruby query log tags:
|
219
|
+
current_graphql_operation: -> { GraphQL::Current.operation_name },
|
220
|
+
current_graphql_field: -> { GraphQL::Current.field&.path },
|
221
|
+
current_dataloader_source: -> { GraphQL::Current.dataloader_source_class },
|
222
|
+
]
|
223
|
+
RUBY
|
224
|
+
after_code = "class Application < Rails::Application\n"
|
225
|
+
end
|
226
|
+
insert_into_file(config_file, code, after: after_code)
|
227
|
+
end
|
228
|
+
|
183
229
|
if gemfile_modified?
|
184
230
|
say "Gemfile has been modified, make sure you `bundle install`"
|
185
231
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
# This module exposes Fiber-level runtime information.
|
5
|
+
#
|
6
|
+
# It won't work across unrelated fibers, although it will work in child Fibers.
|
7
|
+
#
|
8
|
+
# @example Setting Up ActiveRecord::QueryLogs
|
9
|
+
#
|
10
|
+
# config.active_record.query_log_tags = [
|
11
|
+
# :namespaced_controller,
|
12
|
+
# :action,
|
13
|
+
# :job,
|
14
|
+
# # ...
|
15
|
+
# {
|
16
|
+
# # GraphQL runtime info:
|
17
|
+
# current_graphql_operation: -> { GraphQL::Current.operation_name },
|
18
|
+
# current_graphql_field: -> { GraphQL::Current.field&.path },
|
19
|
+
# current_dataloader_source: -> { GraphQL::Current.dataloader_source_class },
|
20
|
+
# # ...
|
21
|
+
# },
|
22
|
+
# ]
|
23
|
+
#
|
24
|
+
module Current
|
25
|
+
# @return [String, nil] Comma-joined operation names for the currently-running {Multiplex}. `nil` if all operations are anonymous.
|
26
|
+
def self.operation_name
|
27
|
+
if (m = Fiber[:__graphql_current_multiplex])
|
28
|
+
m.context[:__graphql_current_operation_name] ||= begin
|
29
|
+
names = m.queries.map { |q| q.selected_operation_name }
|
30
|
+
if names.all?(&:nil?)
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
names.join(",")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @see GraphQL::Field#path for a string identifying this field
|
42
|
+
# @return [GraphQL::Field, nil] The currently-running field, if there is one.
|
43
|
+
def self.field
|
44
|
+
Thread.current[:__graphql_runtime_info]&.values&.first&.current_field
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Class, nil] The currently-running {Dataloader::Source} class, if there is one.
|
48
|
+
def self.dataloader_source_class
|
49
|
+
Fiber[:__graphql_current_dataloader_source]&.class
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/graphql/dataloader.rb
CHANGED
@@ -271,7 +271,10 @@ module GraphQL
|
|
271
271
|
|
272
272
|
if pending_sources
|
273
273
|
spawn_fiber do
|
274
|
-
pending_sources.each
|
274
|
+
pending_sources.each do |source|
|
275
|
+
Fiber[:__graphql_current_dataloader_source] = source
|
276
|
+
source.run_pending_keys
|
277
|
+
end
|
275
278
|
end
|
276
279
|
end
|
277
280
|
end
|
@@ -8,22 +8,17 @@ module GraphQL
|
|
8
8
|
@query = query
|
9
9
|
@dataloader = query.context.dataloader
|
10
10
|
@storage = Hash.new do |h, argument_owner|
|
11
|
-
|
11
|
+
h[argument_owner] = if argument_owner.arguments_statically_coercible?
|
12
12
|
shared_values_cache = {}
|
13
13
|
Hash.new do |h2, ignored_parent_object|
|
14
14
|
h2[ignored_parent_object] = shared_values_cache
|
15
|
-
end
|
15
|
+
end.compare_by_identity
|
16
16
|
else
|
17
17
|
Hash.new do |h2, parent_object|
|
18
|
-
|
19
|
-
|
20
|
-
h2[parent_object] = args_by_node
|
21
|
-
end
|
18
|
+
h2[parent_object] = {}.compare_by_identity
|
19
|
+
end.compare_by_identity
|
22
20
|
end
|
23
|
-
|
24
|
-
h[argument_owner] = args_by_parent
|
25
|
-
end
|
26
|
-
@storage.compare_by_identity
|
21
|
+
end.compare_by_identity
|
27
22
|
end
|
28
23
|
|
29
24
|
def fetch(ast_node, argument_owner, parent_object)
|
@@ -53,8 +53,7 @@ module GraphQL
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
# { Class => Boolean }
|
56
|
-
@lazy_cache = {}
|
57
|
-
@lazy_cache.compare_by_identity
|
56
|
+
@lazy_cache = {}.compare_by_identity
|
58
57
|
end
|
59
58
|
|
60
59
|
def final_result
|
@@ -727,12 +726,7 @@ module GraphQL
|
|
727
726
|
end
|
728
727
|
|
729
728
|
def get_current_runtime_state
|
730
|
-
current_state = Thread.current[:__graphql_runtime_info] ||=
|
731
|
-
per_query_state = {}
|
732
|
-
per_query_state.compare_by_identity
|
733
|
-
per_query_state
|
734
|
-
end
|
735
|
-
|
729
|
+
current_state = Thread.current[:__graphql_runtime_info] ||= {}.compare_by_identity
|
736
730
|
current_state[@query] ||= CurrentState.new
|
737
731
|
end
|
738
732
|
|
@@ -34,6 +34,7 @@ module GraphQL
|
|
34
34
|
end
|
35
35
|
|
36
36
|
multiplex = Execution::Multiplex.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
|
37
|
+
Fiber[:__graphql_current_multiplex] = multiplex
|
37
38
|
multiplex.current_trace.execute_multiplex(multiplex: multiplex) do
|
38
39
|
schema = multiplex.schema
|
39
40
|
queries = multiplex.queries
|
@@ -136,6 +137,7 @@ module GraphQL
|
|
136
137
|
queries.map { |q| q.result_values ||= {} }
|
137
138
|
raise
|
138
139
|
ensure
|
140
|
+
Fiber[:__graphql_current_multiplex] = nil
|
139
141
|
queries.map { |query|
|
140
142
|
runtime = query.context.namespace(:interpreter_runtime)[:runtime]
|
141
143
|
if runtime
|
@@ -15,8 +15,8 @@ module GraphQL
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def __type(name:)
|
18
|
-
if context.types.reachable_type?(name)
|
19
|
-
|
18
|
+
if context.types.reachable_type?(name) && (type = context.types.type(name))
|
19
|
+
type
|
20
20
|
elsif (type = context.schema.extra_types.find { |t| t.graphql_name == name })
|
21
21
|
type
|
22
22
|
else
|
@@ -34,11 +34,11 @@ module GraphQL
|
|
34
34
|
attr_reader :filename
|
35
35
|
|
36
36
|
def line
|
37
|
-
@line ||= @source
|
37
|
+
@line ||= @source&.line_at(@pos)
|
38
38
|
end
|
39
39
|
|
40
40
|
def col
|
41
|
-
@col ||= @source
|
41
|
+
@col ||= @source&.column_at(@pos)
|
42
42
|
end
|
43
43
|
|
44
44
|
def definition_line
|
@@ -82,12 +82,14 @@ module GraphQL
|
|
82
82
|
@provided_values[key] = value
|
83
83
|
end
|
84
84
|
|
85
|
-
def_delegators :@query, :trace
|
85
|
+
def_delegators :@query, :trace
|
86
86
|
|
87
87
|
def types
|
88
|
-
@query.types
|
88
|
+
@types ||= @query.types
|
89
89
|
end
|
90
90
|
|
91
|
+
attr_writer :types
|
92
|
+
|
91
93
|
RUNTIME_METADATA_KEYS = Set.new([:current_object, :current_arguments, :current_field, :current_path])
|
92
94
|
# @!method []=(key, value)
|
93
95
|
# Reassign `key` to the hash passed to {Schema#execute} as `context:`
|
data/lib/graphql/query.rb
CHANGED
@@ -106,8 +106,8 @@ module GraphQL
|
|
106
106
|
end
|
107
107
|
|
108
108
|
if use_schema_subset
|
109
|
-
@schema_subset = @schema.subset_class.new(
|
110
|
-
@warden = Schema::Warden::NullWarden.new(context:
|
109
|
+
@schema_subset = @schema.subset_class.new(context: @context, schema: @schema)
|
110
|
+
@warden = Schema::Warden::NullWarden.new(context: @context, schema: @schema)
|
111
111
|
else
|
112
112
|
@schema_subset = nil
|
113
113
|
@warden = warden
|
@@ -187,10 +187,6 @@ module GraphQL
|
|
187
187
|
@query_string ||= (document ? document.to_query_string : nil)
|
188
188
|
end
|
189
189
|
|
190
|
-
def interpreter?
|
191
|
-
true
|
192
|
-
end
|
193
|
-
|
194
190
|
attr_accessor :multiplex
|
195
191
|
|
196
192
|
# @return [GraphQL::Tracing::Trace]
|
@@ -127,11 +127,12 @@ module GraphQL
|
|
127
127
|
builder = self
|
128
128
|
|
129
129
|
found_types = types.values
|
130
|
+
object_types = found_types.select { |t| t.respond_to?(:kind) && t.kind.object? }
|
130
131
|
schema_class = Class.new(schema_superclass) do
|
131
132
|
begin
|
132
133
|
# Add these first so that there's some chance of resolving late-bound types
|
133
134
|
add_type_and_traverse(found_types, root: false)
|
134
|
-
orphan_types(
|
135
|
+
orphan_types(object_types)
|
135
136
|
query query_root_type
|
136
137
|
mutation mutation_root_type
|
137
138
|
subscription subscription_root_type
|
@@ -141,6 +142,12 @@ module GraphQL
|
|
141
142
|
raise InvalidDocumentError, "Type \"#{type_name}\" not found in document.", err_backtrace
|
142
143
|
end
|
143
144
|
|
145
|
+
object_types.each do |t|
|
146
|
+
t.interfaces.each do |int_t|
|
147
|
+
int_t.orphan_types(t)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
144
151
|
if default_resolve.respond_to?(:resolve_type)
|
145
152
|
def self.resolve_type(*args)
|
146
153
|
self.definition_default_resolve.resolve_type(*args)
|
@@ -7,7 +7,7 @@ module GraphQL
|
|
7
7
|
# In this case, the server hides types and fields _entirely_, unless the current context has certain `:flags` present.
|
8
8
|
class Flagged < GraphQL::Schema::Directive
|
9
9
|
def initialize(target, **options)
|
10
|
-
if target.is_a?(Module)
|
10
|
+
if target.is_a?(Module)
|
11
11
|
# This is type class of some kind, `include` will put this module
|
12
12
|
# in between the type class itself and its super class, so `super` will work fine
|
13
13
|
target.include(VisibleByFlag)
|
@@ -50,7 +50,7 @@ module GraphQL
|
|
50
50
|
if field.has_default_page_size? && !value.has_default_page_size_override?
|
51
51
|
value.default_page_size = field.default_page_size
|
52
52
|
end
|
53
|
-
if
|
53
|
+
if (custom_t = context.schema.connections.edge_class_for_field(@field))
|
54
54
|
value.edge_class = custom_t
|
55
55
|
end
|
56
56
|
value
|
@@ -82,13 +82,29 @@ module GraphQL
|
|
82
82
|
super
|
83
83
|
end
|
84
84
|
|
85
|
+
# Register other Interface or Object types as implementers of this Interface.
|
86
|
+
#
|
87
|
+
# When those Interfaces or Objects aren't used as the return values of fields,
|
88
|
+
# they may have to be registered using this method so that GraphQL-Ruby can find them.
|
89
|
+
# @param types [Class, Module]
|
90
|
+
# @return [Array<Module, Class>] Implementers of this interface, if they're registered
|
85
91
|
def orphan_types(*types)
|
86
92
|
if types.any?
|
87
|
-
@orphan_types
|
93
|
+
@orphan_types ||= []
|
94
|
+
@orphan_types.concat(types)
|
88
95
|
else
|
89
|
-
|
90
|
-
|
91
|
-
|
96
|
+
if defined?(@orphan_types)
|
97
|
+
all_orphan_types = @orphan_types.dup
|
98
|
+
if defined?(super)
|
99
|
+
all_orphan_types += super
|
100
|
+
all_orphan_types.uniq!
|
101
|
+
end
|
102
|
+
all_orphan_types
|
103
|
+
elsif defined?(super)
|
104
|
+
super
|
105
|
+
else
|
106
|
+
EmptyObjects::EMPTY_ARRAY
|
107
|
+
end
|
92
108
|
end
|
93
109
|
end
|
94
110
|
|
@@ -25,7 +25,7 @@ module GraphQL
|
|
25
25
|
load_constant(:DirectiveLocationEnum)
|
26
26
|
]
|
27
27
|
@types = {}
|
28
|
-
@possible_types = {}.
|
28
|
+
@possible_types = {}.compare_by_identity
|
29
29
|
type_defns.each do |t|
|
30
30
|
@types[t.graphql_name] = t
|
31
31
|
@possible_types[t] = [t]
|
@@ -90,7 +90,8 @@ module GraphQL
|
|
90
90
|
def resolve_late_binding(late_bound_type)
|
91
91
|
case late_bound_type
|
92
92
|
when GraphQL::Schema::LateBoundType
|
93
|
-
|
93
|
+
type_name = late_bound_type.name
|
94
|
+
@types[type_name] || @schema.get_type(type_name)
|
94
95
|
when GraphQL::Schema::List
|
95
96
|
resolve_late_binding(late_bound_type.of_type).to_list_type
|
96
97
|
when GraphQL::Schema::NonNull
|
@@ -198,9 +198,13 @@ module GraphQL
|
|
198
198
|
end
|
199
199
|
|
200
200
|
def all_argument_definitions
|
201
|
-
|
202
|
-
|
203
|
-
|
201
|
+
if own_arguments.any?
|
202
|
+
all_defns = own_arguments.values
|
203
|
+
all_defns.flatten!
|
204
|
+
all_defns
|
205
|
+
else
|
206
|
+
EmptyObjects::EMPTY_ARRAY
|
207
|
+
end
|
204
208
|
end
|
205
209
|
|
206
210
|
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
|