graphql 2.0.27 → 2.2.5
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/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/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 +2 -0
- data/lib/graphql/analysis/ast/analyzer.rb +7 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +80 -128
- data/lib/graphql/analysis/ast/query_depth.rb +7 -2
- data/lib/graphql/analysis/ast/visitor.rb +2 -2
- data/lib/graphql/analysis/ast.rb +15 -11
- data/lib/graphql/backtrace/trace.rb +12 -15
- data/lib/graphql/dataloader/async_dataloader.rb +85 -0
- data/lib/graphql/dataloader/source.rb +11 -3
- data/lib/graphql/dataloader.rb +109 -142
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
- data/lib/graphql/execution/interpreter/runtime.rb +70 -248
- data/lib/graphql/execution/interpreter.rb +1 -7
- data/lib/graphql/execution/lookahead.rb +88 -21
- data/lib/graphql/introspection/dynamic_fields.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -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 +36 -35
- data/lib/graphql/language/lexer.rb +271 -177
- data/lib/graphql/language/nodes.rb +74 -56
- data/lib/graphql/language/parser.rb +697 -1986
- data/lib/graphql/language/printer.rb +299 -146
- data/lib/graphql/language/sanitized_printer.rb +20 -22
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +20 -81
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/connection.rb +28 -1
- 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 +36 -98
- data/lib/graphql/query/null_context.rb +4 -11
- data/lib/graphql/query.rb +12 -21
- data/lib/graphql/railtie.rb +9 -6
- data/lib/graphql/rake_task.rb +3 -12
- data/lib/graphql/schema/argument.rb +6 -1
- data/lib/graphql/schema/build_from_definition.rb +0 -11
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum.rb +3 -3
- data/lib/graphql/schema/field/connection_extension.rb +1 -15
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +8 -5
- data/lib/graphql/schema/has_single_input_argument.rb +156 -0
- data/lib/graphql/schema/input_object.rb +2 -2
- data/lib/graphql/schema/interface.rb +10 -10
- data/lib/graphql/schema/introspection_system.rb +2 -0
- data/lib/graphql/schema/loader.rb +0 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +2 -1
- data/lib/graphql/schema/member/has_arguments.rb +61 -38
- data/lib/graphql/schema/member/has_fields.rb +8 -5
- data/lib/graphql/schema/member/has_interfaces.rb +23 -9
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/object.rb +8 -0
- data/lib/graphql/schema/printer.rb +8 -7
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -128
- data/lib/graphql/schema/resolver.rb +7 -3
- data/lib/graphql/schema/scalar.rb +3 -3
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/union.rb +1 -1
- data/lib/graphql/schema/warden.rb +96 -94
- data/lib/graphql/schema.rb +193 -72
- data/lib/graphql/static_validation/all_rules.rb +1 -1
- data/lib/graphql/static_validation/base_visitor.rb +1 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +5 -5
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -2
- data/lib/graphql/subscriptions/event.rb +8 -2
- data/lib/graphql/subscriptions.rb +14 -9
- data/lib/graphql/testing/helpers.rb +125 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/appoptics_trace.rb +2 -2
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/trace.rb +1 -0
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +32 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +7 -0
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +3 -3
- data/readme.md +12 -2
- metadata +29 -22
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/static_validation/type_stack.rb +0 -216
|
@@ -80,6 +80,22 @@ module GraphQL
|
|
|
80
80
|
selection(field_name, selected_type: selected_type, arguments: arguments).selected?
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# True if this node has a selection with alias matching `alias_name`.
|
|
84
|
+
# If `alias_name` is a String, it is treated as a GraphQL-style (camelized)
|
|
85
|
+
# field name and used verbatim. If `alias_name` is a Symbol, it is
|
|
86
|
+
# treated as a Ruby-style (underscored) name and camelized before comparing.
|
|
87
|
+
#
|
|
88
|
+
# If `arguments:` is provided, each provided key/value will be matched
|
|
89
|
+
# against the arguments in the next selection. This method will return false
|
|
90
|
+
# if any of the given `arguments:` are not present and matching in the next selection.
|
|
91
|
+
# (But, the next selection may contain _more_ than the given arguments.)
|
|
92
|
+
# @param alias_name [String, Symbol]
|
|
93
|
+
# @param arguments [Hash] Arguments which must match in the selection
|
|
94
|
+
# @return [Boolean]
|
|
95
|
+
def selects_alias?(alias_name, arguments: nil)
|
|
96
|
+
alias_selection(alias_name, arguments: arguments).selected?
|
|
97
|
+
end
|
|
98
|
+
|
|
83
99
|
# @return [Boolean] True if this lookahead represents a field that was requested
|
|
84
100
|
def selected?
|
|
85
101
|
true
|
|
@@ -102,9 +118,10 @@ module GraphQL
|
|
|
102
118
|
@query.warden
|
|
103
119
|
.possible_types(selected_type)
|
|
104
120
|
.map { |t| @query.warden.fields(t) }
|
|
105
|
-
.flatten
|
|
121
|
+
.tap(&:flatten!)
|
|
106
122
|
end
|
|
107
123
|
|
|
124
|
+
|
|
108
125
|
if (match_by_orig_name = all_fields.find { |f| f.original_name == field_name })
|
|
109
126
|
match_by_orig_name
|
|
110
127
|
else
|
|
@@ -114,23 +131,29 @@ module GraphQL
|
|
|
114
131
|
@query.get_field(selected_type, guessed_name)
|
|
115
132
|
end
|
|
116
133
|
end
|
|
134
|
+
lookahead_for_selection(next_field_defn, selected_type, arguments)
|
|
135
|
+
end
|
|
117
136
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
end
|
|
137
|
+
# Like {#selection}, but for aliases.
|
|
138
|
+
# It returns a null object (check with {#selected?})
|
|
139
|
+
# @return [GraphQL::Execution::Lookahead]
|
|
140
|
+
def alias_selection(alias_name, selected_type: @selected_type, arguments: nil)
|
|
141
|
+
alias_cache_key = [alias_name, arguments]
|
|
142
|
+
return alias_selections[key] if alias_selections.key?(alias_name)
|
|
125
143
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
144
|
+
alias_node = lookup_alias_node(ast_nodes, alias_name)
|
|
145
|
+
return NULL_LOOKAHEAD unless alias_node
|
|
146
|
+
|
|
147
|
+
next_field_defn = @query.get_field(selected_type, alias_node.name)
|
|
148
|
+
|
|
149
|
+
alias_arguments = @query.arguments_for(alias_node, next_field_defn)
|
|
150
|
+
if alias_arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments)
|
|
151
|
+
alias_arguments = alias_arguments.keyword_arguments
|
|
133
152
|
end
|
|
153
|
+
|
|
154
|
+
return NULL_LOOKAHEAD if arguments && arguments != alias_arguments
|
|
155
|
+
|
|
156
|
+
alias_selections[alias_cache_key] = lookahead_for_selection(next_field_defn, selected_type, alias_arguments, alias_name)
|
|
134
157
|
end
|
|
135
158
|
|
|
136
159
|
# Like {#selection}, but for all nodes.
|
|
@@ -258,7 +281,7 @@ module GraphQL
|
|
|
258
281
|
end
|
|
259
282
|
find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
|
|
260
283
|
when GraphQL::Language::Nodes::FragmentSpread
|
|
261
|
-
frag_defn =
|
|
284
|
+
frag_defn = lookup_fragment(ast_selection)
|
|
262
285
|
# Again, assuming a valid AST
|
|
263
286
|
on_type = @query.get_type(frag_defn.type.name)
|
|
264
287
|
subselections_on_type = subselections_by_type[on_type] ||= {}
|
|
@@ -271,11 +294,11 @@ module GraphQL
|
|
|
271
294
|
|
|
272
295
|
# If a selection on `node` matches `field_name` (which is backed by `field_defn`)
|
|
273
296
|
# and matches the `arguments:` constraints, then add that node to `matches`
|
|
274
|
-
def find_selected_nodes(node, field_defn, arguments:, matches:)
|
|
297
|
+
def find_selected_nodes(node, field_name, field_defn, arguments:, matches:, alias_name: NOT_CONFIGURED)
|
|
275
298
|
return if skipped_by_directive?(node)
|
|
276
299
|
case node
|
|
277
300
|
when GraphQL::Language::Nodes::Field
|
|
278
|
-
if node.name ==
|
|
301
|
+
if node.name == field_name && (NOT_CONFIGURED.equal?(alias_name) || node.alias == alias_name)
|
|
279
302
|
if arguments.nil? || arguments.empty?
|
|
280
303
|
# No constraint applied
|
|
281
304
|
matches << node
|
|
@@ -284,10 +307,10 @@ module GraphQL
|
|
|
284
307
|
end
|
|
285
308
|
end
|
|
286
309
|
when GraphQL::Language::Nodes::InlineFragment
|
|
287
|
-
node.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
|
|
310
|
+
node.selections.each { |s| find_selected_nodes(s, field_name, field_defn, arguments: arguments, matches: matches, alias_name: alias_name) }
|
|
288
311
|
when GraphQL::Language::Nodes::FragmentSpread
|
|
289
|
-
frag_defn =
|
|
290
|
-
frag_defn.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
|
|
312
|
+
frag_defn = lookup_fragment(node)
|
|
313
|
+
frag_defn.selections.each { |s| find_selected_nodes(s, field_name, field_defn, arguments: arguments, matches: matches, alias_name: alias_name) }
|
|
291
314
|
else
|
|
292
315
|
raise "Unexpected selection comparison on #{node.class.name} (#{node})"
|
|
293
316
|
end
|
|
@@ -306,6 +329,50 @@ module GraphQL
|
|
|
306
329
|
query_kwargs.key?(arg_name_sym) && query_kwargs[arg_name_sym] == arg_value
|
|
307
330
|
end
|
|
308
331
|
end
|
|
332
|
+
|
|
333
|
+
def lookahead_for_selection(field_defn, selected_type, arguments, alias_name = NOT_CONFIGURED)
|
|
334
|
+
return NULL_LOOKAHEAD unless field_defn
|
|
335
|
+
|
|
336
|
+
next_nodes = []
|
|
337
|
+
field_name = field_defn.name
|
|
338
|
+
@ast_nodes.each do |ast_node|
|
|
339
|
+
ast_node.selections.each do |selection|
|
|
340
|
+
find_selected_nodes(selection, field_name, field_defn, arguments: arguments, matches: next_nodes, alias_name: alias_name)
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
return NULL_LOOKAHEAD if next_nodes.empty?
|
|
345
|
+
|
|
346
|
+
Lookahead.new(query: @query, ast_nodes: next_nodes, field: field_defn, owner_type: selected_type)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def alias_selections
|
|
350
|
+
return @alias_selections if defined?(@alias_selections)
|
|
351
|
+
@alias_selections ||= {}
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def lookup_alias_node(nodes, name)
|
|
355
|
+
return if nodes.empty?
|
|
356
|
+
|
|
357
|
+
nodes.flat_map(&:children)
|
|
358
|
+
.flat_map { |child| unwrap_fragments(child) }
|
|
359
|
+
.find { |child| child.is_a?(GraphQL::Language::Nodes::Field) && child.alias == name }
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def unwrap_fragments(node)
|
|
363
|
+
case node
|
|
364
|
+
when GraphQL::Language::Nodes::InlineFragment
|
|
365
|
+
node.children
|
|
366
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
|
367
|
+
lookup_fragment(node).children
|
|
368
|
+
else
|
|
369
|
+
[node]
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def lookup_fragment(ast_selection)
|
|
374
|
+
@query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
|
|
375
|
+
end
|
|
309
376
|
end
|
|
310
377
|
end
|
|
311
378
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
module GraphQL
|
|
3
3
|
module Introspection
|
|
4
4
|
class DynamicFields < Introspection::BaseObject
|
|
5
|
-
field :__typename, String, "The name of this type", null: false
|
|
5
|
+
field :__typename, String, "The name of this type", null: false, dynamic_introspection: true
|
|
6
6
|
|
|
7
7
|
def __typename
|
|
8
8
|
object.class.graphql_name
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
module GraphQL
|
|
3
3
|
module Introspection
|
|
4
4
|
class EntryPoints < Introspection::BaseObject
|
|
5
|
-
field :__schema, GraphQL::Schema::LateBoundType.new("__Schema"), "This GraphQL schema", null: false
|
|
6
|
-
field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system" do
|
|
5
|
+
field :__schema, GraphQL::Schema::LateBoundType.new("__Schema"), "This GraphQL schema", null: false, dynamic_introspection: true
|
|
6
|
+
field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system", dynamic_introspection: true do
|
|
7
7
|
argument :name, String
|
|
8
8
|
end
|
|
9
9
|
|
|
@@ -47,10 +47,10 @@ module GraphQL
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
# Remove leading & trailing blank lines
|
|
50
|
-
while lines.size > 0 && lines
|
|
50
|
+
while lines.size > 0 && contains_only_whitespace?(lines.first)
|
|
51
51
|
lines.shift
|
|
52
52
|
end
|
|
53
|
-
while lines.size > 0 && lines
|
|
53
|
+
while lines.size > 0 && contains_only_whitespace?(lines.last)
|
|
54
54
|
lines.pop
|
|
55
55
|
end
|
|
56
56
|
|
|
@@ -59,40 +59,56 @@ module GraphQL
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def self.print(str, indent: '')
|
|
62
|
-
|
|
62
|
+
line_length = 120 - indent.length
|
|
63
|
+
block_str = "".dup
|
|
64
|
+
triple_quotes = "\"\"\"\n"
|
|
65
|
+
block_str << indent
|
|
66
|
+
block_str << triple_quotes
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
if str.include?("\n")
|
|
69
|
+
str.split("\n") do |line|
|
|
70
|
+
if line == ''
|
|
71
|
+
block_str << "\n"
|
|
72
|
+
else
|
|
73
|
+
break_line(line, line_length) do |subline|
|
|
74
|
+
block_str << indent
|
|
75
|
+
block_str << subline
|
|
76
|
+
block_str << "\n"
|
|
77
|
+
end
|
|
73
78
|
end
|
|
74
79
|
end
|
|
80
|
+
else
|
|
81
|
+
break_line(str, line_length) do |subline|
|
|
82
|
+
block_str << indent
|
|
83
|
+
block_str << subline
|
|
84
|
+
block_str << "\n"
|
|
85
|
+
end
|
|
75
86
|
end
|
|
76
87
|
|
|
77
|
-
block_str <<
|
|
88
|
+
block_str << indent
|
|
89
|
+
block_str << triple_quotes
|
|
78
90
|
end
|
|
79
91
|
|
|
80
92
|
private
|
|
81
93
|
|
|
82
94
|
def self.break_line(line, length)
|
|
83
|
-
return
|
|
95
|
+
return yield(line) if line.length < length + 5
|
|
84
96
|
|
|
85
97
|
parts = line.split(Regexp.new("((?: |^).{15,#{length - 40}}(?= |$))"))
|
|
86
|
-
return
|
|
98
|
+
return yield(line) if parts.length < 4
|
|
87
99
|
|
|
88
|
-
|
|
100
|
+
yield(parts.slice!(0, 3).join)
|
|
89
101
|
|
|
90
102
|
parts.each_with_index do |part, i|
|
|
91
103
|
next if i % 2 == 1
|
|
92
|
-
|
|
104
|
+
yield "#{part[1..-1]}#{parts[i + 1]}"
|
|
93
105
|
end
|
|
94
106
|
|
|
95
|
-
|
|
107
|
+
nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.contains_only_whitespace?(line)
|
|
111
|
+
line.match?(/^\s*$/)
|
|
96
112
|
end
|
|
97
113
|
end
|
|
98
114
|
end
|
|
@@ -14,7 +14,7 @@ module GraphQL
|
|
|
14
14
|
# @param include_built_in_directives [Boolean] Whether or not to include built in directives in the AST
|
|
15
15
|
class DocumentFromSchemaDefinition
|
|
16
16
|
def initialize(
|
|
17
|
-
schema, context: nil,
|
|
17
|
+
schema, context: nil, include_introspection_types: false,
|
|
18
18
|
include_built_in_directives: false, include_built_in_scalars: false, always_include_schema: false
|
|
19
19
|
)
|
|
20
20
|
@schema = schema
|
|
@@ -26,21 +26,11 @@ module GraphQL
|
|
|
26
26
|
|
|
27
27
|
schema_context = schema.context_class.new(query: nil, object: nil, schema: schema, values: context)
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
filter,
|
|
35
|
-
schema: @schema,
|
|
36
|
-
context: schema_context,
|
|
37
|
-
)
|
|
38
|
-
else
|
|
39
|
-
@schema.warden_class.new(
|
|
40
|
-
schema: @schema,
|
|
41
|
-
context: schema_context,
|
|
42
|
-
)
|
|
43
|
-
end
|
|
29
|
+
|
|
30
|
+
@warden = @schema.warden_class.new(
|
|
31
|
+
schema: @schema,
|
|
32
|
+
context: schema_context,
|
|
33
|
+
)
|
|
44
34
|
|
|
45
35
|
schema_context.warden = @warden
|
|
46
36
|
end
|
|
@@ -52,24 +42,30 @@ module GraphQL
|
|
|
52
42
|
end
|
|
53
43
|
|
|
54
44
|
def build_schema_node
|
|
55
|
-
schema_options = {
|
|
56
|
-
# `@schema.directives` is covered by `build_definition_nodes`
|
|
57
|
-
directives: definition_directives(@schema, :schema_directives),
|
|
58
|
-
}
|
|
59
45
|
if !schema_respects_root_name_conventions?(@schema)
|
|
60
|
-
|
|
46
|
+
GraphQL::Language::Nodes::SchemaDefinition.new(
|
|
61
47
|
query: (q = warden.root_type_for_operation("query")) && q.graphql_name,
|
|
62
48
|
mutation: (m = warden.root_type_for_operation("mutation")) && m.graphql_name,
|
|
63
49
|
subscription: (s = warden.root_type_for_operation("subscription")) && s.graphql_name,
|
|
64
|
-
|
|
50
|
+
directives: definition_directives(@schema, :schema_directives)
|
|
51
|
+
)
|
|
52
|
+
else
|
|
53
|
+
# A plain `schema ...` _must_ include root type definitions.
|
|
54
|
+
# If the only difference is directives, then you have to use `extend schema`
|
|
55
|
+
GraphQL::Language::Nodes::SchemaExtension.new(directives: definition_directives(@schema, :schema_directives))
|
|
65
56
|
end
|
|
66
|
-
GraphQL::Language::Nodes::SchemaDefinition.new(schema_options)
|
|
67
57
|
end
|
|
68
58
|
|
|
69
59
|
def build_object_type_node(object_type)
|
|
60
|
+
ints = warden.interfaces(object_type)
|
|
61
|
+
if ints.any?
|
|
62
|
+
ints.sort_by!(&:graphql_name)
|
|
63
|
+
ints.map! { |iface| build_type_name_node(iface) }
|
|
64
|
+
end
|
|
65
|
+
|
|
70
66
|
GraphQL::Language::Nodes::ObjectTypeDefinition.new(
|
|
71
67
|
name: object_type.graphql_name,
|
|
72
|
-
interfaces:
|
|
68
|
+
interfaces: ints,
|
|
73
69
|
fields: build_field_nodes(warden.fields(object_type)),
|
|
74
70
|
description: object_type.description,
|
|
75
71
|
directives: directives(object_type),
|
|
@@ -190,7 +186,8 @@ module GraphQL
|
|
|
190
186
|
of_type: build_type_name_node(type.of_type)
|
|
191
187
|
)
|
|
192
188
|
else
|
|
193
|
-
|
|
189
|
+
@cached_type_name_nodes ||= {}
|
|
190
|
+
@cached_type_name_nodes[type.graphql_name] ||= GraphQL::Language::Nodes::TypeName.new(name: type.graphql_name)
|
|
194
191
|
end
|
|
195
192
|
end
|
|
196
193
|
|
|
@@ -247,9 +244,13 @@ module GraphQL
|
|
|
247
244
|
end
|
|
248
245
|
|
|
249
246
|
def build_argument_nodes(arguments)
|
|
250
|
-
arguments
|
|
251
|
-
.map { |arg| build_argument_node(arg) }
|
|
252
|
-
.sort_by(&:name)
|
|
247
|
+
if arguments.any?
|
|
248
|
+
nodes = arguments.map { |arg| build_argument_node(arg) }
|
|
249
|
+
nodes.sort_by!(&:name)
|
|
250
|
+
nodes
|
|
251
|
+
else
|
|
252
|
+
arguments
|
|
253
|
+
end
|
|
253
254
|
end
|
|
254
255
|
|
|
255
256
|
def build_directive_nodes(directives)
|
|
@@ -263,16 +264,16 @@ module GraphQL
|
|
|
263
264
|
if !include_built_in_directives
|
|
264
265
|
dirs_to_build = dirs_to_build.reject { |directive| directive.default_directive? }
|
|
265
266
|
end
|
|
266
|
-
|
|
267
|
+
definitions = build_directive_nodes(dirs_to_build)
|
|
267
268
|
|
|
268
269
|
type_nodes = build_type_definition_nodes(warden.reachable_types)
|
|
269
270
|
|
|
270
271
|
if @include_one_of
|
|
271
272
|
# This may have been set to true when iterating over all types
|
|
272
|
-
|
|
273
|
+
definitions.concat(build_directive_nodes([GraphQL::Schema::Directive::OneOf]))
|
|
273
274
|
end
|
|
274
275
|
|
|
275
|
-
definitions
|
|
276
|
+
definitions.concat(type_nodes)
|
|
276
277
|
if include_schema_node?
|
|
277
278
|
definitions.unshift(build_schema_node)
|
|
278
279
|
end
|
|
@@ -295,9 +296,9 @@ module GraphQL
|
|
|
295
296
|
end
|
|
296
297
|
|
|
297
298
|
def build_field_nodes(fields)
|
|
298
|
-
fields
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
f_nodes = fields.map { |field| build_field_node(field) }
|
|
300
|
+
f_nodes.sort_by!(&:name)
|
|
301
|
+
f_nodes
|
|
301
302
|
end
|
|
302
303
|
|
|
303
304
|
private
|
|
@@ -320,7 +321,7 @@ module GraphQL
|
|
|
320
321
|
|
|
321
322
|
def definition_directives(member, directives_method)
|
|
322
323
|
dirs = if !member.respond_to?(directives_method) || member.directives.empty?
|
|
323
|
-
|
|
324
|
+
EmptyObjects::EMPTY_ARRAY
|
|
324
325
|
else
|
|
325
326
|
member.public_send(directives_method).map do |dir|
|
|
326
327
|
args = []
|