graphql 1.8.0.pre2 → 1.8.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +2 -0
- data/lib/graphql/enum_type.rb +1 -1
- data/lib/graphql/field.rb +10 -1
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/introspection.rb +3 -10
- data/lib/graphql/introspection/base_object.rb +15 -0
- data/lib/graphql/introspection/directive_location_enum.rb +11 -7
- data/lib/graphql/introspection/directive_type.rb +23 -16
- data/lib/graphql/introspection/dynamic_fields.rb +11 -0
- data/lib/graphql/introspection/entry_points.rb +29 -0
- data/lib/graphql/introspection/enum_value_type.rb +16 -11
- data/lib/graphql/introspection/field_type.rb +21 -12
- data/lib/graphql/introspection/input_value_type.rb +26 -23
- data/lib/graphql/introspection/schema_field.rb +7 -2
- data/lib/graphql/introspection/schema_type.rb +36 -22
- data/lib/graphql/introspection/type_by_name_field.rb +10 -2
- data/lib/graphql/introspection/type_kind_enum.rb +10 -6
- data/lib/graphql/introspection/type_type.rb +85 -23
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +129 -37
- data/lib/graphql/language/generation.rb +3 -182
- data/lib/graphql/language/nodes.rb +12 -2
- data/lib/graphql/language/parser.rb +63 -55
- data/lib/graphql/language/parser.y +2 -1
- data/lib/graphql/language/printer.rb +351 -0
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/query/arguments.rb +24 -8
- data/lib/graphql/query/context.rb +3 -0
- data/lib/graphql/query/literal_input.rb +4 -1
- data/lib/graphql/railtie.rb +28 -6
- data/lib/graphql/schema.rb +42 -7
- data/lib/graphql/schema/enum.rb +1 -0
- data/lib/graphql/schema/field.rb +26 -5
- data/lib/graphql/schema/field/dynamic_resolve.rb +18 -9
- data/lib/graphql/schema/input_object.rb +2 -2
- data/lib/graphql/schema/introspection_system.rb +93 -0
- data/lib/graphql/schema/late_bound_type.rb +32 -0
- data/lib/graphql/schema/member.rb +21 -1
- data/lib/graphql/schema/member/build_type.rb +8 -6
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/instrumentation.rb +3 -1
- data/lib/graphql/schema/member/list_type_proxy.rb +4 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +4 -0
- data/lib/graphql/schema/object.rb +2 -1
- data/lib/graphql/schema/printer.rb +33 -266
- data/lib/graphql/schema/traversal.rb +74 -6
- data/lib/graphql/schema/validation.rb +3 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/upgrader/member.rb +463 -63
- data/lib/graphql/version.rb +1 -1
- data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
- data/spec/fixtures/upgrader/blame_range.transformed.rb +31 -0
- data/spec/fixtures/upgrader/subscribable.original.rb +51 -0
- data/spec/fixtures/upgrader/subscribable.transformed.rb +46 -0
- data/spec/fixtures/upgrader/type_x.original.rb +35 -0
- data/spec/fixtures/upgrader/type_x.transformed.rb +35 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +729 -296
- data/spec/graphql/language/generation_spec.rb +21 -186
- data/spec/graphql/language/nodes_spec.rb +21 -0
- data/spec/graphql/language/printer_spec.rb +203 -0
- data/spec/graphql/query/arguments_spec.rb +14 -4
- data/spec/graphql/query/context_spec.rb +17 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +13 -4
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/introspection_system_spec.rb +39 -0
- data/spec/graphql/schema/object_spec.rb +12 -1
- data/spec/graphql/schema/printer_spec.rb +14 -14
- data/spec/graphql/tracing/platform_tracing_spec.rb +2 -2
- data/spec/graphql/upgrader/member_spec.rb +274 -62
- data/spec/support/jazz.rb +75 -3
- metadata +38 -9
- data/lib/graphql/introspection/arguments_field.rb +0 -7
- data/lib/graphql/introspection/enum_values_field.rb +0 -18
- data/lib/graphql/introspection/fields_field.rb +0 -13
- data/lib/graphql/introspection/input_fields_field.rb +0 -12
- data/lib/graphql/introspection/interfaces_field.rb +0 -11
- data/lib/graphql/introspection/of_type_field.rb +0 -6
- data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -4,8 +4,8 @@ module GraphQL
|
|
4
4
|
class InputObject < GraphQL::Schema::Member
|
5
5
|
extend GraphQL::Delegate
|
6
6
|
|
7
|
-
def initialize(values, context:)
|
8
|
-
@arguments = self.class.arguments_class.new(values, context: context)
|
7
|
+
def initialize(values, context:, defaults_used:)
|
8
|
+
@arguments = self.class.arguments_class.new(values, context: context, defaults_used: defaults_used)
|
9
9
|
@context = context
|
10
10
|
end
|
11
11
|
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class IntrospectionSystem
|
5
|
+
attr_reader :schema_type, :type_type, :typename_field
|
6
|
+
|
7
|
+
def initialize(schema)
|
8
|
+
@schema = schema
|
9
|
+
@built_in_namespace = GraphQL::Introspection
|
10
|
+
@custom_namespace = schema.introspection_namespace || @built_in_namespace
|
11
|
+
|
12
|
+
# Use to-graphql to avoid sharing with any previous instantiations
|
13
|
+
@schema_type = load_constant(:SchemaType).to_graphql
|
14
|
+
@type_type = load_constant(:TypeType).to_graphql
|
15
|
+
@field_type = load_constant(:FieldType).to_graphql
|
16
|
+
@directive_type = load_constant(:DirectiveType).to_graphql
|
17
|
+
@enum_value_type = load_constant(:EnumValueType).to_graphql
|
18
|
+
@input_value_type = load_constant(:InputValueType).to_graphql
|
19
|
+
@type_kind_enum = load_constant(:TypeKindEnum).to_graphql
|
20
|
+
@directive_location_enum = load_constant(:DirectiveLocationEnum).to_graphql
|
21
|
+
@entry_point_fields = get_fields_from_class(class_sym: :EntryPoints)
|
22
|
+
@dynamic_fields = get_fields_from_class(class_sym: :DynamicFields)
|
23
|
+
end
|
24
|
+
|
25
|
+
def object_types
|
26
|
+
[
|
27
|
+
@schema_type,
|
28
|
+
@type_type,
|
29
|
+
@field_type,
|
30
|
+
@directive_type,
|
31
|
+
@enum_value_type,
|
32
|
+
@input_value_type,
|
33
|
+
@type_kind_enum,
|
34
|
+
@directive_location_enum,
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
def entry_points
|
39
|
+
@entry_point_fields.values
|
40
|
+
end
|
41
|
+
|
42
|
+
def entry_point(name:)
|
43
|
+
@entry_point_fields[name]
|
44
|
+
end
|
45
|
+
|
46
|
+
def dynamic_fields
|
47
|
+
@dynamic_fields.values
|
48
|
+
end
|
49
|
+
|
50
|
+
def dynamic_field(name:)
|
51
|
+
@dynamic_fields[name]
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def load_constant(class_name)
|
57
|
+
@custom_namespace.const_get(class_name)
|
58
|
+
rescue NameError
|
59
|
+
# Dup the built-in so that the cached fields aren't shared
|
60
|
+
@built_in_namespace.const_get(class_name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_fields_from_class(class_sym:)
|
64
|
+
object_class = load_constant(class_sym)
|
65
|
+
object_type_defn = object_class.to_graphql
|
66
|
+
extracted_field_defns = {}
|
67
|
+
object_type_defn.all_fields.each do |field_defn|
|
68
|
+
inner_resolve = field_defn.resolve_proc
|
69
|
+
resolve_with_instantiate = PerFieldProxyResolve.new(object_class: object_class, inner_resolve: inner_resolve)
|
70
|
+
extracted_field_defns[field_defn.name] = field_defn.redefine(resolve: resolve_with_instantiate)
|
71
|
+
end
|
72
|
+
extracted_field_defns
|
73
|
+
end
|
74
|
+
|
75
|
+
class PerFieldProxyResolve
|
76
|
+
def initialize(object_class:, inner_resolve:)
|
77
|
+
@object_class = object_class
|
78
|
+
@inner_resolve = inner_resolve
|
79
|
+
end
|
80
|
+
|
81
|
+
def call(obj, args, ctx)
|
82
|
+
query_ctx = ctx.query.context
|
83
|
+
# Remove the QueryType wrapper
|
84
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
85
|
+
obj = obj.object
|
86
|
+
end
|
87
|
+
wrapped_object = @object_class.new(obj, query_ctx)
|
88
|
+
@inner_resolve.call(wrapped_object, args, ctx)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
# A stand-in for a type which will be resolved in a given schema, by name.
|
5
|
+
# TODO: support argument types too, make this a public API somehow
|
6
|
+
# @api Private
|
7
|
+
class LateBoundType
|
8
|
+
attr_reader :name
|
9
|
+
def initialize(local_name)
|
10
|
+
@name = local_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def unwrap
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_non_null_type
|
18
|
+
GraphQL::NonNullType.new(of_type: self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_list_type
|
22
|
+
GraphQL::ListType.new(of_type: self)
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
"#<LateBoundType @name=#{name}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
alias :to_s :inspect
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -15,6 +15,11 @@ module GraphQL
|
|
15
15
|
def graphql_definition
|
16
16
|
@graphql_definition ||= to_graphql
|
17
17
|
end
|
18
|
+
|
19
|
+
def initialize_copy(original)
|
20
|
+
super
|
21
|
+
@graphql_definition = nil
|
22
|
+
end
|
18
23
|
end
|
19
24
|
|
20
25
|
# These constants are interpreted as GraphQL types
|
@@ -58,7 +63,7 @@ module GraphQL
|
|
58
63
|
if new_name
|
59
64
|
@graphql_name = new_name
|
60
65
|
else
|
61
|
-
|
66
|
+
overridden_graphql_name || self.name.split("::").last.sub(/Type\Z/, "")
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
@@ -84,6 +89,15 @@ module GraphQL
|
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
92
|
+
# @return [Boolean] If true, this object is part of the introspection system
|
93
|
+
def introspection(new_introspection = nil)
|
94
|
+
if !new_introspection.nil?
|
95
|
+
@introspection = new_introspection
|
96
|
+
else
|
97
|
+
@introspection || (superclass <= Schema::Member ? superclass.introspection : false)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
87
101
|
def to_graphql
|
88
102
|
raise NotImplementedError
|
89
103
|
end
|
@@ -95,6 +109,12 @@ module GraphQL
|
|
95
109
|
def to_non_null_type
|
96
110
|
NonNullTypeProxy.new(self)
|
97
111
|
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
def overridden_graphql_name
|
116
|
+
@graphql_name || (superclass <= GraphQL::Schema::Member ? superclass.overridden_graphql_name : nil)
|
117
|
+
end
|
98
118
|
end
|
99
119
|
end
|
100
120
|
end
|
@@ -43,7 +43,7 @@ module GraphQL
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
when GraphQL::BaseType
|
46
|
+
when GraphQL::BaseType, GraphQL::Schema::LateBoundType
|
47
47
|
type_expr
|
48
48
|
when Array
|
49
49
|
if type_expr.length != 1
|
@@ -77,7 +77,7 @@ module GraphQL
|
|
77
77
|
|
78
78
|
def to_type_name(something)
|
79
79
|
case something
|
80
|
-
when GraphQL::BaseType
|
80
|
+
when GraphQL::BaseType, GraphQL::Schema::LateBoundType
|
81
81
|
something.unwrap.name
|
82
82
|
when Array
|
83
83
|
to_type_name(something.first)
|
@@ -95,11 +95,13 @@ module GraphQL
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def camelize(string)
|
98
|
-
return string unless string.include?(
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
return string unless string.include?("_")
|
99
|
+
camelized = string.split('_').map(&:capitalize).join
|
100
|
+
camelized[0] = camelized[0].downcase
|
101
|
+
if string.start_with?("__")
|
102
|
+
camelized = "__#{camelized}"
|
102
103
|
end
|
104
|
+
camelized
|
103
105
|
end
|
104
106
|
|
105
107
|
def underscore(string)
|
@@ -100,7 +100,9 @@ module GraphQL
|
|
100
100
|
end
|
101
101
|
|
102
102
|
if concrete_type && (object_class = concrete_type.metadata[:object_class])
|
103
|
-
|
103
|
+
# use the query-level context here, since it won't be field-specific anyways
|
104
|
+
query_ctx = ctx.query.context
|
105
|
+
object_class.new(obj, query_ctx)
|
104
106
|
else
|
105
107
|
obj
|
106
108
|
end
|
@@ -45,9 +45,10 @@ module GraphQL
|
|
45
45
|
obj_type.name = graphql_name
|
46
46
|
obj_type.description = description
|
47
47
|
obj_type.interfaces = interfaces
|
48
|
+
obj_type.introspection = introspection
|
48
49
|
|
49
50
|
fields.each do |field_inst|
|
50
|
-
field_defn = field_inst.
|
51
|
+
field_defn = field_inst.to_graphql
|
51
52
|
obj_type.fields[field_defn.name] = field_defn
|
52
53
|
end
|
53
54
|
|
@@ -36,7 +36,7 @@ module GraphQL
|
|
36
36
|
# printer = GraphQL::Schema::Printer.new(MySchema)
|
37
37
|
# puts printer.print_type(post_type)
|
38
38
|
#
|
39
|
-
class Printer
|
39
|
+
class Printer < GraphQL::Language::Printer
|
40
40
|
attr_reader :schema, :warden
|
41
41
|
|
42
42
|
# @param schema [GraphQL::Schema]
|
@@ -45,21 +45,32 @@ module GraphQL
|
|
45
45
|
# @param except [<#call(member, ctx)>]
|
46
46
|
# @param introspection [Boolean] Should include the introspection types in the string?
|
47
47
|
def initialize(schema, context: nil, only: nil, except: nil, introspection: false)
|
48
|
-
@
|
49
|
-
|
48
|
+
@document_from_schema = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
49
|
+
schema,
|
50
|
+
context: context,
|
51
|
+
only: only,
|
52
|
+
except: except,
|
53
|
+
include_introspection_types: introspection,
|
54
|
+
)
|
55
|
+
|
56
|
+
@document = @document_from_schema.document
|
50
57
|
|
51
|
-
|
52
|
-
filter = GraphQL::Filter.new(except: blacklist)
|
53
|
-
@warden = GraphQL::Schema::Warden.new(filter, schema: @schema, context: @context)
|
58
|
+
@schema = schema
|
54
59
|
end
|
55
60
|
|
56
61
|
# Return the GraphQL schema string for the introspection type system
|
57
62
|
def self.print_introspection_schema
|
58
63
|
query_root = ObjectType.define(name: "Root")
|
59
64
|
schema = GraphQL::Schema.define(query: query_root)
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
|
66
|
+
introspection_schema_ast = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
67
|
+
schema,
|
68
|
+
except: ->(member, _) { member.name == "Root" },
|
69
|
+
include_introspection_types: true,
|
70
|
+
include_built_in_directives: true,
|
71
|
+
).document
|
72
|
+
|
73
|
+
introspection_schema_ast.to_query_string(printer: IntrospectionPrinter.new)
|
63
74
|
end
|
64
75
|
|
65
76
|
# Return a GraphQL schema string for the defined types in the schema
|
@@ -74,277 +85,33 @@ module GraphQL
|
|
74
85
|
|
75
86
|
# Return a GraphQL schema string for the defined types in the schema
|
76
87
|
def print_schema
|
77
|
-
|
78
|
-
|
79
|
-
printable_types = warden.types.reject(&:default_scalar?)
|
80
|
-
|
81
|
-
type_definitions = printable_types
|
82
|
-
.sort_by(&:name)
|
83
|
-
.map { |type| print_type(type) }
|
84
|
-
|
85
|
-
[print_schema_definition].compact
|
86
|
-
.concat(directive_definitions)
|
87
|
-
.concat(type_definitions).join("\n\n")
|
88
|
+
print(@document)
|
88
89
|
end
|
89
90
|
|
90
91
|
def print_type(type)
|
91
|
-
|
92
|
+
node = @document_from_schema.build_object_type_node(type)
|
93
|
+
print(node)
|
92
94
|
end
|
93
95
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
IS_USER_DEFINED_MEMBER = ->(member) {
|
98
|
-
case member
|
99
|
-
when GraphQL::BaseType
|
100
|
-
!member.introspection?
|
101
|
-
when GraphQL::Directive
|
102
|
-
!member.default_directive?
|
103
|
-
else
|
104
|
-
true
|
105
|
-
end
|
106
|
-
}
|
107
|
-
|
108
|
-
private_constant :IS_USER_DEFINED_MEMBER
|
96
|
+
def print_directive(directive)
|
97
|
+
if directive.name == "deprecated"
|
98
|
+
reason = directive.arguments.find { |arg| arg.name == "reason" }
|
109
99
|
|
110
|
-
|
111
|
-
|
112
|
-
if only
|
113
|
-
->(m, ctx) { !only.call(m, ctx) }
|
114
|
-
elsif except
|
115
|
-
except
|
100
|
+
if reason.value == GraphQL::Directive::DEFAULT_DEPRECATION_REASON
|
101
|
+
"@deprecated"
|
116
102
|
else
|
117
|
-
|
103
|
+
"@deprecated(reason: \"#{reason.value}\")"
|
118
104
|
end
|
119
105
|
else
|
120
|
-
|
121
|
-
->(m, ctx) { !(IS_USER_DEFINED_MEMBER.call(m) && only.call(m, ctx)) }
|
122
|
-
elsif except
|
123
|
-
->(m, ctx) { !IS_USER_DEFINED_MEMBER.call(m) || except.call(m, ctx) }
|
124
|
-
else
|
125
|
-
->(m, ctx) { !IS_USER_DEFINED_MEMBER.call(m) }
|
126
|
-
end
|
106
|
+
super
|
127
107
|
end
|
128
108
|
end
|
129
109
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
(schema.subscription.nil? || schema.subscription.name == 'Subscription')
|
134
|
-
return
|
110
|
+
class IntrospectionPrinter < GraphQL::Language::Printer
|
111
|
+
def print_schema_definition(schema)
|
112
|
+
"schema {\n query: Root\n}"
|
135
113
|
end
|
136
|
-
|
137
|
-
operations = [:query, :mutation, :subscription].map do |operation_type|
|
138
|
-
object_type = schema.public_send(operation_type)
|
139
|
-
# Special treatment for the introspection schema, which prints `{ query: "Root" }`
|
140
|
-
if object_type && (warden.get_type(object_type.name) || (object_type.name == "Root" && schema.query == object_type))
|
141
|
-
" #{operation_type}: #{object_type.name}\n"
|
142
|
-
else
|
143
|
-
nil
|
144
|
-
end
|
145
|
-
end.compact.join
|
146
|
-
"schema {\n#{operations}}"
|
147
|
-
end
|
148
|
-
|
149
|
-
def print_directive(directive)
|
150
|
-
TypeKindPrinters::DirectivePrinter.print(warden, directive)
|
151
|
-
end
|
152
|
-
|
153
|
-
module TypeKindPrinters
|
154
|
-
module DeprecatedPrinter
|
155
|
-
def print_deprecated(field_or_enum_value)
|
156
|
-
return unless field_or_enum_value.deprecation_reason
|
157
|
-
|
158
|
-
case field_or_enum_value.deprecation_reason
|
159
|
-
when nil
|
160
|
-
''
|
161
|
-
when '', GraphQL::Directive::DEFAULT_DEPRECATION_REASON
|
162
|
-
' @deprecated'
|
163
|
-
else
|
164
|
-
" @deprecated(reason: #{field_or_enum_value.deprecation_reason.to_s.inspect})"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
module DescriptionPrinter
|
170
|
-
def print_description(definition, indentation='', first_in_block=true)
|
171
|
-
return '' unless definition.description
|
172
|
-
|
173
|
-
description = indentation != '' && !first_in_block ? "\n".dup : "".dup
|
174
|
-
description << GraphQL::Language::Comments.commentize(definition.description, indent: indentation)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
module ArgsPrinter
|
179
|
-
include DescriptionPrinter
|
180
|
-
def print_args(warden, field, indentation = '')
|
181
|
-
arguments = warden.arguments(field)
|
182
|
-
return if arguments.empty?
|
183
|
-
|
184
|
-
if arguments.all?{ |arg| !arg.description }
|
185
|
-
return "(#{arguments.map{ |arg| print_input_value(arg) }.join(", ")})"
|
186
|
-
end
|
187
|
-
|
188
|
-
out = "(\n".dup
|
189
|
-
out << arguments.sort_by(&:name).map.with_index{ |arg, i|
|
190
|
-
"#{print_description(arg, " #{indentation}", i == 0)} #{indentation}"\
|
191
|
-
"#{print_input_value(arg)}"
|
192
|
-
}.join("\n")
|
193
|
-
out << "\n#{indentation})"
|
194
|
-
end
|
195
|
-
|
196
|
-
def print_input_value(arg)
|
197
|
-
if arg.default_value?
|
198
|
-
default_string = " = #{print_value(arg.default_value, arg.type)}"
|
199
|
-
else
|
200
|
-
default_string = nil
|
201
|
-
end
|
202
|
-
|
203
|
-
"#{arg.name}: #{arg.type.to_s}#{default_string}"
|
204
|
-
end
|
205
|
-
|
206
|
-
def print_value(value, type)
|
207
|
-
case type
|
208
|
-
when FLOAT_TYPE
|
209
|
-
return 'null' if value.nil?
|
210
|
-
value.to_f.inspect
|
211
|
-
when INT_TYPE
|
212
|
-
return 'null' if value.nil?
|
213
|
-
value.to_i.inspect
|
214
|
-
when BOOLEAN_TYPE
|
215
|
-
return 'null' if value.nil?
|
216
|
-
(!!value).inspect
|
217
|
-
when ScalarType, ID_TYPE, STRING_TYPE
|
218
|
-
return 'null' if value.nil?
|
219
|
-
value.to_s.inspect
|
220
|
-
when EnumType
|
221
|
-
return 'null' if value.nil?
|
222
|
-
type.coerce_isolated_result(value)
|
223
|
-
when InputObjectType
|
224
|
-
return 'null' if value.nil?
|
225
|
-
fields = value.to_h.map{ |field_name, field_value|
|
226
|
-
field_type = type.input_fields.fetch(field_name.to_s).type
|
227
|
-
"#{field_name}: #{print_value(field_value, field_type)}"
|
228
|
-
}.join(", ")
|
229
|
-
"{#{fields}}"
|
230
|
-
when NonNullType
|
231
|
-
print_value(value, type.of_type)
|
232
|
-
when ListType
|
233
|
-
return 'null' if value.nil?
|
234
|
-
"[#{value.to_a.map{ |v| print_value(v, type.of_type) }.join(", ")}]"
|
235
|
-
else
|
236
|
-
raise NotImplementedError, "Unexpected value type #{type.inspect}"
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
module FieldPrinter
|
242
|
-
include DeprecatedPrinter
|
243
|
-
include ArgsPrinter
|
244
|
-
include DescriptionPrinter
|
245
|
-
def print_fields(warden, type)
|
246
|
-
fields = warden.fields(type)
|
247
|
-
fields.sort_by(&:name).map.with_index { |field, i|
|
248
|
-
"#{print_description(field, ' ', i == 0)}"\
|
249
|
-
" #{field.name}#{print_args(warden, field, ' ')}: #{field.type}#{print_deprecated(field)}"
|
250
|
-
}.join("\n")
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
class DirectivePrinter
|
255
|
-
extend ArgsPrinter
|
256
|
-
extend DescriptionPrinter
|
257
|
-
def self.print(warden, directive)
|
258
|
-
"#{print_description(directive)}"\
|
259
|
-
"directive @#{directive.name}#{print_args(warden, directive)} "\
|
260
|
-
"on #{directive.locations.join(' | ')}"
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
class ScalarPrinter
|
265
|
-
extend DescriptionPrinter
|
266
|
-
def self.print(warden, type)
|
267
|
-
"#{print_description(type)}"\
|
268
|
-
"scalar #{type.name}"
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
class ObjectPrinter
|
273
|
-
extend FieldPrinter
|
274
|
-
extend DescriptionPrinter
|
275
|
-
def self.print(warden, type)
|
276
|
-
interfaces = warden.interfaces(type)
|
277
|
-
if interfaces.any?
|
278
|
-
implementations = " implements #{interfaces.sort_by(&:name).map(&:to_s).join(", ")}"
|
279
|
-
else
|
280
|
-
implementations = nil
|
281
|
-
end
|
282
|
-
|
283
|
-
"#{print_description(type)}"\
|
284
|
-
"type #{type.name}#{implementations} {\n"\
|
285
|
-
"#{print_fields(warden, type)}\n"\
|
286
|
-
"}"
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
class InterfacePrinter
|
291
|
-
extend FieldPrinter
|
292
|
-
extend DescriptionPrinter
|
293
|
-
def self.print(warden, type)
|
294
|
-
"#{print_description(type)}"\
|
295
|
-
"interface #{type.name} {\n#{print_fields(warden, type)}\n}"
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
class UnionPrinter
|
300
|
-
extend DescriptionPrinter
|
301
|
-
def self.print(warden, type)
|
302
|
-
possible_types = warden.possible_types(type)
|
303
|
-
"#{print_description(type)}"\
|
304
|
-
"union #{type.name} = #{possible_types.sort_by(&:name).map(&:to_s).join(" | ")}"
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
class EnumPrinter
|
309
|
-
extend DeprecatedPrinter
|
310
|
-
extend DescriptionPrinter
|
311
|
-
def self.print(warden, type)
|
312
|
-
enum_values = warden.enum_values(type)
|
313
|
-
|
314
|
-
values = enum_values.sort_by(&:name).map.with_index { |v, i|
|
315
|
-
"#{print_description(v, ' ', i == 0)}"\
|
316
|
-
" #{v.name}#{print_deprecated(v)}"
|
317
|
-
}.join("\n")
|
318
|
-
|
319
|
-
"#{print_description(type)}"\
|
320
|
-
"enum #{type.name} {\n#{values}\n}"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
class InputObjectPrinter
|
325
|
-
extend FieldPrinter
|
326
|
-
extend DescriptionPrinter
|
327
|
-
def self.print(warden, type)
|
328
|
-
arguments = warden.arguments(type)
|
329
|
-
fields = arguments.sort_by(&:name).map.with_index{ |field, i|
|
330
|
-
"#{print_description(field, " ", i == 0)}"\
|
331
|
-
" #{print_input_value(field)}"
|
332
|
-
}.join("\n")
|
333
|
-
"#{print_description(type)}"\
|
334
|
-
"input #{type.name} {\n#{fields}\n}"
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
STRATEGIES = {
|
339
|
-
GraphQL::TypeKinds::SCALAR => ScalarPrinter,
|
340
|
-
GraphQL::TypeKinds::OBJECT => ObjectPrinter,
|
341
|
-
GraphQL::TypeKinds::INTERFACE => InterfacePrinter,
|
342
|
-
GraphQL::TypeKinds::UNION => UnionPrinter,
|
343
|
-
GraphQL::TypeKinds::ENUM => EnumPrinter,
|
344
|
-
GraphQL::TypeKinds::INPUT_OBJECT => InputObjectPrinter,
|
345
|
-
}
|
346
114
|
end
|
347
|
-
private_constant :TypeKindPrinters
|
348
115
|
end
|
349
116
|
end
|
350
117
|
end
|