graphql 1.7.14 → 1.8.0.pre1
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 +5 -5
- data/lib/generators/graphql/function_generator.rb +1 -1
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +1 -6
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/graphql.rb +2 -0
- data/lib/graphql/argument.rb +0 -1
- data/lib/graphql/backwards_compatibility.rb +2 -3
- data/lib/graphql/base_type.rb +18 -16
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -117
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -14
- data/lib/graphql/define/assign_object_field.rb +5 -12
- data/lib/graphql/deprecated_dsl.rb +28 -0
- data/lib/graphql/directive.rb +0 -1
- data/lib/graphql/enum_type.rb +1 -3
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/execution/multiplex.rb +29 -12
- data/lib/graphql/field.rb +5 -20
- data/lib/graphql/function.rb +12 -0
- data/lib/graphql/input_object_type.rb +1 -3
- data/lib/graphql/internal_representation/node.rb +14 -26
- data/lib/graphql/internal_representation/visit.rb +6 -3
- data/lib/graphql/introspection/arguments_field.rb +0 -1
- data/lib/graphql/introspection/enum_values_field.rb +0 -1
- data/lib/graphql/introspection/fields_field.rb +0 -1
- data/lib/graphql/introspection/input_fields_field.rb +0 -1
- data/lib/graphql/introspection/interfaces_field.rb +0 -1
- data/lib/graphql/introspection/of_type_field.rb +0 -1
- data/lib/graphql/introspection/possible_types_field.rb +0 -1
- data/lib/graphql/introspection/schema_field.rb +0 -1
- data/lib/graphql/introspection/type_by_name_field.rb +0 -1
- data/lib/graphql/introspection/typename_field.rb +0 -1
- data/lib/graphql/language.rb +0 -3
- data/lib/graphql/language/generation.rb +182 -3
- data/lib/graphql/language/lexer.rb +69 -144
- data/lib/graphql/language/lexer.rl +4 -15
- data/lib/graphql/language/nodes.rb +76 -136
- data/lib/graphql/language/parser.rb +621 -668
- data/lib/graphql/language/parser.y +11 -17
- data/lib/graphql/language/token.rb +3 -10
- data/lib/graphql/object_type.rb +6 -1
- data/lib/graphql/query.rb +13 -8
- data/lib/graphql/query/arguments.rb +33 -48
- data/lib/graphql/query/context.rb +1 -0
- data/lib/graphql/query/literal_input.rb +1 -4
- data/lib/graphql/relay/connection_resolve.rb +3 -0
- data/lib/graphql/relay/global_id_resolve.rb +5 -1
- data/lib/graphql/relay/relation_connection.rb +19 -14
- data/lib/graphql/schema.rb +219 -12
- data/lib/graphql/schema/argument.rb +33 -0
- data/lib/graphql/schema/build_from_definition.rb +18 -64
- data/lib/graphql/schema/enum.rb +76 -0
- data/lib/graphql/schema/field.rb +127 -0
- data/lib/graphql/schema/field/dynamic_resolve.rb +63 -0
- data/lib/graphql/schema/field/unwrapped_resolve.rb +20 -0
- data/lib/graphql/schema/input_object.rb +61 -0
- data/lib/graphql/schema/interface.rb +32 -0
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/member.rb +97 -0
- data/lib/graphql/schema/member/build_type.rb +106 -0
- data/lib/graphql/schema/member/has_fields.rb +56 -0
- data/lib/graphql/schema/member/instrumentation.rb +113 -0
- data/lib/graphql/schema/member/list_type_proxy.rb +21 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +21 -0
- data/lib/graphql/schema/object.rb +65 -0
- data/lib/graphql/schema/printer.rb +266 -33
- data/lib/graphql/schema/scalar.rb +25 -0
- data/lib/graphql/schema/traversal.rb +26 -17
- data/lib/graphql/schema/union.rb +48 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -11
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -7
- data/lib/graphql/tracing.rb +0 -1
- data/lib/graphql/tracing/platform_tracing.rb +7 -20
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -3
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/dummy/app/channels/graphql_channel.rb +1 -22
- data/spec/dummy/log/development.log +0 -239
- data/spec/dummy/log/test.log +0 -204
- data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -4
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/generators/graphql/function_generator_spec.rb +0 -26
- data/spec/generators/graphql/loader_generator_spec.rb +0 -24
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/backtrace_spec.rb +0 -10
- data/spec/graphql/base_type_spec.rb +5 -19
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +1 -3
- data/spec/graphql/enum_type_spec.rb +5 -18
- data/spec/graphql/execution/execute_spec.rb +1 -1
- data/spec/graphql/execution/multiplex_spec.rb +2 -2
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +2 -15
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +0 -1
- data/spec/graphql/language/generation_spec.rb +186 -21
- data/spec/graphql/language/lexer_spec.rb +1 -21
- data/spec/graphql/language/nodes_spec.rb +12 -21
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/query/arguments_spec.rb +15 -37
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/query_spec.rb +5 -31
- data/spec/graphql/rake_task_spec.rb +1 -3
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mutation_spec.rb +3 -3
- data/spec/graphql/relay/relation_connection_spec.rb +1 -65
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -86
- data/spec/graphql/schema/enum_spec.rb +60 -0
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/input_object_spec.rb +43 -0
- data/spec/graphql/schema/interface_spec.rb +98 -0
- data/spec/graphql/schema/object_spec.rb +119 -0
- data/spec/graphql/schema/printer_spec.rb +15 -92
- data/spec/graphql/schema/scalar_spec.rb +40 -0
- data/spec/graphql/schema/union_spec.rb +35 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +25 -23
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -10
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +1 -1
- data/spec/graphql/tracing/platform_tracing_spec.rb +1 -60
- data/spec/support/dummy/schema.rb +25 -39
- data/spec/support/jazz.rb +334 -0
- data/spec/support/lazy_helpers.rb +21 -23
- data/spec/support/star_wars/data.rb +7 -6
- data/spec/support/star_wars/schema.rb +109 -142
- metadata +39 -33
- data/lib/graphql/execution/instrumentation.rb +0 -82
- data/lib/graphql/language/block_string.rb +0 -47
- data/lib/graphql/language/document_from_schema_definition.rb +0 -277
- data/lib/graphql/language/printer.rb +0 -351
- data/lib/graphql/tracing/data_dog_tracing.rb +0 -49
- data/spec/graphql/execution/instrumentation_spec.rb +0 -165
- data/spec/graphql/language/block_string_spec.rb +0 -70
- data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
- data/spec/graphql/language/printer_spec.rb +0 -203
data/lib/graphql/field.rb
CHANGED
@@ -102,7 +102,7 @@ module GraphQL
|
|
102
102
|
# @example Calculating the complexity of a list field
|
103
103
|
# field :items, types[ItemType] do
|
104
104
|
# argument :limit, !types.Int
|
105
|
-
# #
|
105
|
+
# # Mulitply the child complexity by the possible items on the list
|
106
106
|
# complexity ->(ctx, args, child_complexity) { child_complexity * args[:limit] }
|
107
107
|
# end
|
108
108
|
#
|
@@ -130,8 +130,6 @@ module GraphQL
|
|
130
130
|
:relay_node_field,
|
131
131
|
:relay_nodes_field,
|
132
132
|
:subscription_scope,
|
133
|
-
:trace,
|
134
|
-
:introspection,
|
135
133
|
argument: GraphQL::Define::AssignArgument
|
136
134
|
|
137
135
|
ensure_defined(
|
@@ -139,8 +137,7 @@ module GraphQL
|
|
139
137
|
:mutation, :arguments, :complexity, :function,
|
140
138
|
:resolve, :resolve=, :lazy_resolve, :lazy_resolve=, :lazy_resolve_proc, :resolve_proc,
|
141
139
|
:type, :type=, :name=, :property=, :hash_key=,
|
142
|
-
:relay_node_field, :relay_nodes_field, :edges?, :edge_class, :subscription_scope
|
143
|
-
:introspection?
|
140
|
+
:relay_node_field, :relay_nodes_field, :edges?, :edge_class, :subscription_scope
|
144
141
|
)
|
145
142
|
|
146
143
|
# @return [Boolean] True if this is the Relay find-by-id field
|
@@ -185,16 +182,10 @@ module GraphQL
|
|
185
182
|
attr_accessor :arguments_class
|
186
183
|
|
187
184
|
attr_writer :connection
|
188
|
-
attr_writer :introspection
|
189
185
|
|
190
186
|
# @return [nil, String] Prefix for subscription names from this field
|
191
187
|
attr_accessor :subscription_scope
|
192
188
|
|
193
|
-
# @return [Boolean] True if this field should be traced. By default, fields are only traced if they are not a ScalarType or EnumType.
|
194
|
-
attr_accessor :trace
|
195
|
-
|
196
|
-
attr_accessor :ast_node
|
197
|
-
|
198
189
|
# @return [Boolean]
|
199
190
|
def connection?
|
200
191
|
@connection
|
@@ -221,20 +212,14 @@ module GraphQL
|
|
221
212
|
@connection = false
|
222
213
|
@connection_max_page_size = nil
|
223
214
|
@edge_class = nil
|
224
|
-
@trace = nil
|
225
|
-
@introspection = false
|
226
215
|
end
|
227
216
|
|
228
217
|
def initialize_copy(other)
|
218
|
+
ensure_defined
|
229
219
|
super
|
230
220
|
@arguments = other.arguments.dup
|
231
221
|
end
|
232
222
|
|
233
|
-
# @return [Boolean] Is this field a predefined introspection field?
|
234
|
-
def introspection?
|
235
|
-
@introspection
|
236
|
-
end
|
237
|
-
|
238
223
|
# Get a value for this field
|
239
224
|
# @example resolving a field value
|
240
225
|
# field.resolve(obj, args, ctx)
|
@@ -290,8 +275,8 @@ module GraphQL
|
|
290
275
|
"<Field name:#{name || "not-named"} desc:#{description} resolve:#{resolve_proc}>"
|
291
276
|
end
|
292
277
|
|
293
|
-
# If {#resolve} returned
|
294
|
-
# this method will be called later
|
278
|
+
# If {#resolve} returned and object which should be handled lazily,
|
279
|
+
# this method will be called later force the object to return its value.
|
295
280
|
# @param obj [Object] The {#resolve}-provided object, registered with {Schema#lazy_resolve}
|
296
281
|
# @param args [GraphQL::Query::Arguments] Arguments to this field
|
297
282
|
# @param ctx [GraphQL::Query::Context] Context for this field
|
data/lib/graphql/function.rb
CHANGED
@@ -97,6 +97,18 @@ module GraphQL
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
def build_field(function)
|
101
|
+
GraphQL::Field.define(
|
102
|
+
arguments: function.arguments,
|
103
|
+
complexity: function.complexity,
|
104
|
+
type: function.type,
|
105
|
+
resolve: function,
|
106
|
+
description: function.description,
|
107
|
+
function: function,
|
108
|
+
deprecation_reason: function.deprecation_reason,
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
100
112
|
# Class-level reader/writer which is inherited
|
101
113
|
# @api private
|
102
114
|
def self.inherited_value(name)
|
@@ -84,7 +84,6 @@ module GraphQL
|
|
84
84
|
|
85
85
|
def coerce_non_null_input(value, ctx)
|
86
86
|
input_values = {}
|
87
|
-
defaults_used = Set.new
|
88
87
|
|
89
88
|
arguments.each do |input_key, input_field_defn|
|
90
89
|
field_value = value[input_key]
|
@@ -94,11 +93,10 @@ module GraphQL
|
|
94
93
|
input_values[input_key] = input_field_defn.prepare(coerced_value, ctx)
|
95
94
|
elsif input_field_defn.default_value?
|
96
95
|
input_values[input_key] = input_field_defn.default_value
|
97
|
-
defaults_used << input_key
|
98
96
|
end
|
99
97
|
end
|
100
98
|
|
101
|
-
arguments_class.new(input_values,
|
99
|
+
arguments_class.new(input_values, context: ctx)
|
102
100
|
end
|
103
101
|
|
104
102
|
# @api private
|
@@ -4,12 +4,6 @@ module GraphQL
|
|
4
4
|
class Node
|
5
5
|
# @api private
|
6
6
|
DEFAULT_TYPED_CHILDREN = Proc.new { |h, k| h[k] = {} }
|
7
|
-
|
8
|
-
# A specialized, reusable object for leaf nodes.
|
9
|
-
NO_TYPED_CHILDREN = Hash.new({}.freeze)
|
10
|
-
def NO_TYPED_CHILDREN.dup; self; end;
|
11
|
-
NO_TYPED_CHILDREN.freeze
|
12
|
-
|
13
7
|
# @return [String] the name this node has in the response
|
14
8
|
attr_reader :name
|
15
9
|
|
@@ -22,9 +16,9 @@ module GraphQL
|
|
22
16
|
# This value is derived from {#scoped_children} after the rewrite is finished.
|
23
17
|
# @return [Hash<GraphQL::ObjectType, Hash<String => Node>>]
|
24
18
|
def typed_children
|
25
|
-
@
|
19
|
+
@typed_childen ||= begin
|
20
|
+
new_tc = Hash.new(&DEFAULT_TYPED_CHILDREN)
|
26
21
|
if @scoped_children.any?
|
27
|
-
new_tc = Hash.new(&DEFAULT_TYPED_CHILDREN)
|
28
22
|
all_object_types = Set.new
|
29
23
|
scoped_children.each_key { |t| all_object_types.merge(@query.possible_types(t)) }
|
30
24
|
# Remove any scoped children which don't follow this return type
|
@@ -33,11 +27,8 @@ module GraphQL
|
|
33
27
|
all_object_types.each do |t|
|
34
28
|
new_tc[t] = get_typed_children(t)
|
35
29
|
end
|
36
|
-
new_tc
|
37
|
-
else
|
38
|
-
NO_TYPED_CHILDREN
|
39
30
|
end
|
40
|
-
|
31
|
+
new_tc
|
41
32
|
end
|
42
33
|
end
|
43
34
|
|
@@ -134,20 +125,17 @@ module GraphQL
|
|
134
125
|
@ast_nodes |= new_parent.ast_nodes
|
135
126
|
@definitions |= new_parent.definitions
|
136
127
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
prev_node
|
146
|
-
|
147
|
-
|
148
|
-
else
|
149
|
-
prev_fields[name] = new_node
|
150
|
-
end
|
128
|
+
scope ||= Scope.new(@query, @return_type.unwrap)
|
129
|
+
new_parent.scoped_children.each do |obj_type, new_fields|
|
130
|
+
inner_scope = scope.enter(obj_type)
|
131
|
+
inner_scope.each do |scoped_type|
|
132
|
+
prev_fields = @scoped_children[scoped_type]
|
133
|
+
new_fields.each do |name, new_node|
|
134
|
+
prev_node = prev_fields[name]
|
135
|
+
if prev_node
|
136
|
+
prev_node.deep_merge_node(new_node)
|
137
|
+
else
|
138
|
+
prev_fields[name] = new_node
|
151
139
|
end
|
152
140
|
end
|
153
141
|
end
|
@@ -24,9 +24,12 @@ module GraphQL
|
|
24
24
|
# visiting the node itself and each of its typed children.
|
25
25
|
def each_node(node)
|
26
26
|
yield(node)
|
27
|
-
node.typed_children.
|
28
|
-
|
29
|
-
|
27
|
+
if node.typed_children.any?
|
28
|
+
visit_block = Proc.new
|
29
|
+
node.typed_children.each do |obj_type, children|
|
30
|
+
children.each do |name, node|
|
31
|
+
each_node(node, &visit_block)
|
32
|
+
end
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
GraphQL::Introspection::EnumValuesField = GraphQL::Field.define do
|
3
3
|
type types[!GraphQL::Introspection::EnumValueType]
|
4
|
-
introspection true
|
5
4
|
argument :includeDeprecated, types.Boolean, default_value: false
|
6
5
|
resolve ->(object, arguments, context) do
|
7
6
|
if !object.kind.enum?
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
GraphQL::Introspection::FieldsField = GraphQL::Field.define do
|
3
3
|
type -> { types[!GraphQL::Introspection::FieldType] }
|
4
|
-
introspection true
|
5
4
|
argument :includeDeprecated, GraphQL::BOOLEAN_TYPE, default_value: false
|
6
5
|
resolve ->(object, arguments, context) {
|
7
6
|
return nil if !object.kind.fields?
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
GraphQL::Introspection::InterfacesField = GraphQL::Field.define do
|
3
3
|
type -> { types[!GraphQL::Introspection::TypeType] }
|
4
|
-
introspection true
|
5
4
|
resolve ->(target, a, ctx) {
|
6
5
|
if target.kind == GraphQL::TypeKinds::OBJECT
|
7
6
|
ctx.warden.interfaces(target)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
GraphQL::Introspection::PossibleTypesField = GraphQL::Field.define do
|
3
3
|
type -> { types[!GraphQL::Introspection::TypeType] }
|
4
|
-
introspection true
|
5
4
|
resolve ->(target, args, ctx) {
|
6
5
|
if target.kind.resolves?
|
7
6
|
ctx.warden.possible_types(target)
|
data/lib/graphql/language.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require "graphql/language/block_string"
|
3
|
-
require "graphql/language/printer"
|
4
2
|
require "graphql/language/definition_slice"
|
5
|
-
require "graphql/language/document_from_schema_definition"
|
6
3
|
require "graphql/language/generation"
|
7
4
|
require "graphql/language/lexer"
|
8
5
|
require "graphql/language/nodes"
|
@@ -14,10 +14,189 @@ module GraphQL
|
|
14
14
|
#
|
15
15
|
# @param node [GraphQL::Language::Nodes::AbstractNode] an AST node to recursively stringify
|
16
16
|
# @param indent [String] Whitespace to add to each printed node
|
17
|
-
# @param printer [GraphQL::Language::Printer] An optional custom printer for printing AST nodes. Defaults to GraphQL::Language::Printer
|
18
17
|
# @return [String] Valid GraphQL for `node`
|
19
|
-
def generate(node, indent: ""
|
20
|
-
|
18
|
+
def generate(node, indent: "")
|
19
|
+
case node
|
20
|
+
when Nodes::Document
|
21
|
+
node.definitions.map { |d| generate(d) }.join("\n\n")
|
22
|
+
when Nodes::Argument
|
23
|
+
"#{node.name}: #{generate(node.value)}".dup
|
24
|
+
when Nodes::Directive
|
25
|
+
out = "@#{node.name}".dup
|
26
|
+
out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
|
27
|
+
out
|
28
|
+
when Nodes::Enum
|
29
|
+
"#{node.name}".dup
|
30
|
+
when Nodes::NullValue
|
31
|
+
"null".dup
|
32
|
+
when Nodes::Field
|
33
|
+
out = "#{indent}".dup
|
34
|
+
out << "#{node.alias}: " if node.alias
|
35
|
+
out << "#{node.name}"
|
36
|
+
out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
|
37
|
+
out << generate_directives(node.directives)
|
38
|
+
out << generate_selections(node.selections, indent: indent)
|
39
|
+
out
|
40
|
+
when Nodes::FragmentDefinition
|
41
|
+
out = "#{indent}fragment #{node.name}".dup
|
42
|
+
if node.type
|
43
|
+
out << " on #{generate(node.type)}"
|
44
|
+
end
|
45
|
+
out << generate_directives(node.directives)
|
46
|
+
out << generate_selections(node.selections, indent: indent)
|
47
|
+
out
|
48
|
+
when Nodes::FragmentSpread
|
49
|
+
out = "#{indent}...#{node.name}".dup
|
50
|
+
out << generate_directives(node.directives)
|
51
|
+
out
|
52
|
+
when Nodes::InlineFragment
|
53
|
+
out = "#{indent}...".dup
|
54
|
+
if node.type
|
55
|
+
out << " on #{generate(node.type)}"
|
56
|
+
end
|
57
|
+
out << generate_directives(node.directives)
|
58
|
+
out << generate_selections(node.selections, indent: indent)
|
59
|
+
out
|
60
|
+
when Nodes::InputObject
|
61
|
+
generate(node.to_h)
|
62
|
+
when Nodes::ListType
|
63
|
+
"[#{generate(node.of_type)}]".dup
|
64
|
+
when Nodes::NonNullType
|
65
|
+
"#{generate(node.of_type)}!".dup
|
66
|
+
when Nodes::OperationDefinition
|
67
|
+
out = "#{indent}#{node.operation_type}".dup
|
68
|
+
out << " #{node.name}" if node.name
|
69
|
+
out << "(#{node.variables.map { |v| generate(v) }.join(", ")})" if node.variables.any?
|
70
|
+
out << generate_directives(node.directives)
|
71
|
+
out << generate_selections(node.selections, indent: indent)
|
72
|
+
out
|
73
|
+
when Nodes::TypeName
|
74
|
+
"#{node.name}".dup
|
75
|
+
when Nodes::VariableDefinition
|
76
|
+
out = "$#{node.name}: #{generate(node.type)}".dup
|
77
|
+
out << " = #{generate(node.default_value)}" unless node.default_value.nil?
|
78
|
+
out
|
79
|
+
when Nodes::VariableIdentifier
|
80
|
+
"$#{node.name}".dup
|
81
|
+
when Nodes::SchemaDefinition
|
82
|
+
if (node.query.nil? || node.query == 'Query') &&
|
83
|
+
(node.mutation.nil? || node.mutation == 'Mutation') &&
|
84
|
+
(node.subscription.nil? || node.subscription == 'Subscription')
|
85
|
+
return
|
86
|
+
end
|
87
|
+
|
88
|
+
out = "schema {\n".dup
|
89
|
+
out << " query: #{node.query}\n" if node.query
|
90
|
+
out << " mutation: #{node.mutation}\n" if node.mutation
|
91
|
+
out << " subscription: #{node.subscription}\n" if node.subscription
|
92
|
+
out << "}"
|
93
|
+
when Nodes::ScalarTypeDefinition
|
94
|
+
out = generate_description(node)
|
95
|
+
out << "scalar #{node.name}"
|
96
|
+
out << generate_directives(node.directives)
|
97
|
+
when Nodes::ObjectTypeDefinition
|
98
|
+
out = generate_description(node)
|
99
|
+
out << "type #{node.name}"
|
100
|
+
out << generate_directives(node.directives)
|
101
|
+
out << " implements " << node.interfaces.map(&:name).join(", ") unless node.interfaces.empty?
|
102
|
+
out << generate_field_definitions(node.fields)
|
103
|
+
when Nodes::InputValueDefinition
|
104
|
+
out = "#{node.name}: #{generate(node.type)}".dup
|
105
|
+
out << " = #{generate(node.default_value)}" unless node.default_value.nil?
|
106
|
+
out << generate_directives(node.directives)
|
107
|
+
when Nodes::FieldDefinition
|
108
|
+
out = node.name.dup
|
109
|
+
unless node.arguments.empty?
|
110
|
+
out << "(" << node.arguments.map{ |arg| generate(arg) }.join(", ") << ")"
|
111
|
+
end
|
112
|
+
out << ": #{generate(node.type)}"
|
113
|
+
out << generate_directives(node.directives)
|
114
|
+
when Nodes::InterfaceTypeDefinition
|
115
|
+
out = generate_description(node)
|
116
|
+
out << "interface #{node.name}"
|
117
|
+
out << generate_directives(node.directives)
|
118
|
+
out << generate_field_definitions(node.fields)
|
119
|
+
when Nodes::UnionTypeDefinition
|
120
|
+
out = generate_description(node)
|
121
|
+
out << "union #{node.name}"
|
122
|
+
out << generate_directives(node.directives)
|
123
|
+
out << " = " + node.types.map(&:name).join(" | ")
|
124
|
+
when Nodes::EnumTypeDefinition
|
125
|
+
out = generate_description(node)
|
126
|
+
out << "enum #{node.name}#{generate_directives(node.directives)} {\n"
|
127
|
+
node.values.each.with_index do |value, i|
|
128
|
+
out << generate_description(value, indent: ' ', first_in_block: i == 0)
|
129
|
+
out << generate(value)
|
130
|
+
end
|
131
|
+
out << "}"
|
132
|
+
when Nodes::EnumValueDefinition
|
133
|
+
out = " #{node.name}".dup
|
134
|
+
out << generate_directives(node.directives)
|
135
|
+
out << "\n"
|
136
|
+
when Nodes::InputObjectTypeDefinition
|
137
|
+
out = generate_description(node)
|
138
|
+
out << "input #{node.name}"
|
139
|
+
out << generate_directives(node.directives)
|
140
|
+
out << " {\n"
|
141
|
+
node.fields.each.with_index do |field, i|
|
142
|
+
out << generate_description(field, indent: ' ', first_in_block: i == 0)
|
143
|
+
out << " #{generate(field)}\n"
|
144
|
+
end
|
145
|
+
out << "}"
|
146
|
+
when Nodes::DirectiveDefinition
|
147
|
+
out = generate_description(node)
|
148
|
+
out << "directive @#{node.name}"
|
149
|
+
out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
|
150
|
+
out << " on #{node.locations.join(' | ')}"
|
151
|
+
when Nodes::AbstractNode
|
152
|
+
node.to_query_string(indent: indent)
|
153
|
+
when FalseClass, Float, Integer, NilClass, String, TrueClass
|
154
|
+
GraphQL::Language.serialize(node)
|
155
|
+
when Array
|
156
|
+
"[#{node.map { |v| generate(v) }.join(", ")}]".dup
|
157
|
+
when Hash
|
158
|
+
"{#{node.map { |k, v| "#{k}: #{generate(v)}" }.join(", ")}}".dup
|
159
|
+
else
|
160
|
+
raise TypeError
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def generate_directives(directives)
|
167
|
+
if directives.any?
|
168
|
+
directives.map { |d| " #{generate(d)}" }.join
|
169
|
+
else
|
170
|
+
""
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def generate_selections(selections, indent: "")
|
175
|
+
if selections.any?
|
176
|
+
out = " {\n".dup
|
177
|
+
selections.each do |selection|
|
178
|
+
out << generate(selection, indent: indent + " ") << "\n"
|
179
|
+
end
|
180
|
+
out << "#{indent}}"
|
181
|
+
else
|
182
|
+
""
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def generate_description(node, indent: '', first_in_block: true)
|
187
|
+
return ''.dup unless node.description
|
188
|
+
|
189
|
+
description = indent != '' && !first_in_block ? "\n".dup : "".dup
|
190
|
+
description << GraphQL::Language::Comments.commentize(node.description, indent: indent)
|
191
|
+
end
|
192
|
+
|
193
|
+
def generate_field_definitions(fields)
|
194
|
+
out = " {\n".dup
|
195
|
+
fields.each.with_index do |field, i|
|
196
|
+
out << generate_description(field, indent: ' ', first_in_block: i == 0)
|
197
|
+
out << " #{generate(field)}\n"
|
198
|
+
end
|
199
|
+
out << "}"
|
21
200
|
end
|
22
201
|
end
|
23
202
|
end
|