graphql 1.7.14 → 1.8.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|