graphql 1.8.0.pre2 → 1.8.0.pre3

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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +1 -1
  3. data/lib/graphql/deprecated_dsl.rb +2 -0
  4. data/lib/graphql/enum_type.rb +1 -1
  5. data/lib/graphql/field.rb +10 -1
  6. data/lib/graphql/input_object_type.rb +3 -1
  7. data/lib/graphql/introspection.rb +3 -10
  8. data/lib/graphql/introspection/base_object.rb +15 -0
  9. data/lib/graphql/introspection/directive_location_enum.rb +11 -7
  10. data/lib/graphql/introspection/directive_type.rb +23 -16
  11. data/lib/graphql/introspection/dynamic_fields.rb +11 -0
  12. data/lib/graphql/introspection/entry_points.rb +29 -0
  13. data/lib/graphql/introspection/enum_value_type.rb +16 -11
  14. data/lib/graphql/introspection/field_type.rb +21 -12
  15. data/lib/graphql/introspection/input_value_type.rb +26 -23
  16. data/lib/graphql/introspection/schema_field.rb +7 -2
  17. data/lib/graphql/introspection/schema_type.rb +36 -22
  18. data/lib/graphql/introspection/type_by_name_field.rb +10 -2
  19. data/lib/graphql/introspection/type_kind_enum.rb +10 -6
  20. data/lib/graphql/introspection/type_type.rb +85 -23
  21. data/lib/graphql/introspection/typename_field.rb +1 -0
  22. data/lib/graphql/language.rb +1 -0
  23. data/lib/graphql/language/document_from_schema_definition.rb +129 -37
  24. data/lib/graphql/language/generation.rb +3 -182
  25. data/lib/graphql/language/nodes.rb +12 -2
  26. data/lib/graphql/language/parser.rb +63 -55
  27. data/lib/graphql/language/parser.y +2 -1
  28. data/lib/graphql/language/printer.rb +351 -0
  29. data/lib/graphql/object_type.rb +1 -1
  30. data/lib/graphql/query.rb +1 -1
  31. data/lib/graphql/query/arguments.rb +24 -8
  32. data/lib/graphql/query/context.rb +3 -0
  33. data/lib/graphql/query/literal_input.rb +4 -1
  34. data/lib/graphql/railtie.rb +28 -6
  35. data/lib/graphql/schema.rb +42 -7
  36. data/lib/graphql/schema/enum.rb +1 -0
  37. data/lib/graphql/schema/field.rb +26 -5
  38. data/lib/graphql/schema/field/dynamic_resolve.rb +18 -9
  39. data/lib/graphql/schema/input_object.rb +2 -2
  40. data/lib/graphql/schema/introspection_system.rb +93 -0
  41. data/lib/graphql/schema/late_bound_type.rb +32 -0
  42. data/lib/graphql/schema/member.rb +21 -1
  43. data/lib/graphql/schema/member/build_type.rb +8 -6
  44. data/lib/graphql/schema/member/has_fields.rb +1 -1
  45. data/lib/graphql/schema/member/instrumentation.rb +3 -1
  46. data/lib/graphql/schema/member/list_type_proxy.rb +4 -0
  47. data/lib/graphql/schema/member/non_null_type_proxy.rb +4 -0
  48. data/lib/graphql/schema/object.rb +2 -1
  49. data/lib/graphql/schema/printer.rb +33 -266
  50. data/lib/graphql/schema/traversal.rb +74 -6
  51. data/lib/graphql/schema/validation.rb +3 -2
  52. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
  53. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  54. data/lib/graphql/upgrader/member.rb +463 -63
  55. data/lib/graphql/version.rb +1 -1
  56. data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
  57. data/spec/fixtures/upgrader/blame_range.transformed.rb +31 -0
  58. data/spec/fixtures/upgrader/subscribable.original.rb +51 -0
  59. data/spec/fixtures/upgrader/subscribable.transformed.rb +46 -0
  60. data/spec/fixtures/upgrader/type_x.original.rb +35 -0
  61. data/spec/fixtures/upgrader/type_x.transformed.rb +35 -0
  62. data/spec/graphql/language/document_from_schema_definition_spec.rb +729 -296
  63. data/spec/graphql/language/generation_spec.rb +21 -186
  64. data/spec/graphql/language/nodes_spec.rb +21 -0
  65. data/spec/graphql/language/printer_spec.rb +203 -0
  66. data/spec/graphql/query/arguments_spec.rb +14 -4
  67. data/spec/graphql/query/context_spec.rb +17 -0
  68. data/spec/graphql/schema/build_from_definition_spec.rb +13 -4
  69. data/spec/graphql/schema/field_spec.rb +14 -0
  70. data/spec/graphql/schema/introspection_system_spec.rb +39 -0
  71. data/spec/graphql/schema/object_spec.rb +12 -1
  72. data/spec/graphql/schema/printer_spec.rb +14 -14
  73. data/spec/graphql/tracing/platform_tracing_spec.rb +2 -2
  74. data/spec/graphql/upgrader/member_spec.rb +274 -62
  75. data/spec/support/jazz.rb +75 -3
  76. metadata +38 -9
  77. data/lib/graphql/introspection/arguments_field.rb +0 -7
  78. data/lib/graphql/introspection/enum_values_field.rb +0 -18
  79. data/lib/graphql/introspection/fields_field.rb +0 -13
  80. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  81. data/lib/graphql/introspection/interfaces_field.rb +0 -11
  82. data/lib/graphql/introspection/of_type_field.rb +0 -6
  83. 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
- @graphql_name || self.name.split("::").last.sub(/Type\Z/, "")
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
- string.split('_').map(&:capitalize).join.tap do |camelized|
101
- camelized[0] = camelized[0].downcase
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)
@@ -30,7 +30,7 @@ module GraphQL
30
30
  # @param field_defn [GraphQL::Schema::Field]
31
31
  # @return [void]
32
32
  def add_field(field_defn)
33
- fields.reject! {|f| f.name == field_defn.name}
33
+ own_fields.reject! {|f| f.name == field_defn.name}
34
34
  own_fields << field_defn
35
35
  nil
36
36
  end
@@ -100,7 +100,9 @@ module GraphQL
100
100
  end
101
101
 
102
102
  if concrete_type && (object_class = concrete_type.metadata[:object_class])
103
- object_class.new(obj, ctx)
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
@@ -15,6 +15,10 @@ module GraphQL
15
15
  def to_graphql
16
16
  @member.graphql_definition.to_list_type
17
17
  end
18
+
19
+ def to_non_null_type
20
+ NonNullTypeProxy.new(self)
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -15,6 +15,10 @@ module GraphQL
15
15
  def to_graphql
16
16
  @member.graphql_definition.to_non_null_type
17
17
  end
18
+
19
+ def to_list_type
20
+ ListTypeProxy.new(self)
21
+ end
18
22
  end
19
23
  end
20
24
  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.graphql_definition
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
- @schema = schema
49
- @context = context
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
- blacklist = build_blacklist(only, except, introspection: introspection)
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
- blacklist = ->(m, ctx) { m == query_root }
61
- printer = new(schema, except: blacklist, introspection: true)
62
- printer.print_schema
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
- directive_definitions = warden.directives.map { |directive| print_directive(directive) }
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
- TypeKindPrinters::STRATEGIES.fetch(type.kind).print(warden, type)
92
+ node = @document_from_schema.build_object_type_node(type)
93
+ print(node)
92
94
  end
93
95
 
94
- private
95
-
96
- # By default, these are included in a schema printout
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
- def build_blacklist(only, except, introspection:)
111
- if introspection
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
- ->(m, ctx) { false }
103
+ "@deprecated(reason: \"#{reason.value}\")"
118
104
  end
119
105
  else
120
- if only
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
- def print_schema_definition
131
- if (schema.query.nil? || schema.query.name == 'Query') &&
132
- (schema.mutation.nil? || schema.mutation.name == 'Mutation') &&
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