graphql 1.8.0.pre5 → 1.8.0.pre6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f08af6fe85ac8b3665acc0a2b8a38ab165dd418a
4
- data.tar.gz: f4be355d3ba05a0566ff508d4f00621acafa0f77
3
+ metadata.gz: d974acad8e306ebc40d3ef5185293be78a6172a7
4
+ data.tar.gz: 68befc3fffce8764a3bd14173ecc55484dad4fc7
5
5
  SHA512:
6
- metadata.gz: 0a6b65f5db04ad1c127e3328d0ab5dce93430cfb20f6be9cf08e95e9cfbf681d653a1d1277a81347dbbf04d95541010956d7711f14a865bc9e00bad16db62a78
7
- data.tar.gz: e5f307b33f3136c71fcd538a9e5e957271bf1a0aaf622287e0e991a5e1a0d3dbc23621df0307332ed3af4840e80eee8b5b3f2ee94deec3f274dadfe3c1eadb72
6
+ metadata.gz: a98b86f3ddfd3443da23161c7c662d2dc1bf12e5ec32c202d2376d71800f5b8f6ee8c99c33f13242ad5858743b6edbe90e228e558c20a6de55dc58545460f6a7
7
+ data.tar.gz: 4b0f87b1f29351dea232bcf0032438669a1cbba9a90b0ab87de4535767c6861018285c13fc4c8e22780cb7571013114fdd1c3ef6c34ab9534217a4e375fca772
@@ -12,8 +12,18 @@ module GraphQL
12
12
  CHILDREN = [].freeze
13
13
  def dup; self; end
14
14
  def any?; false; end
15
+ def none?; true; end
15
16
  def [](key); CHILDREN; end
16
17
  def each; end
18
+
19
+ # Compatibility for when this was an Array:
20
+ def method_missing(method_name, *args, &block)
21
+ if CHILDREN.respond_to?(method_name)
22
+ CHILDREN.send(method_name, *args, &block)
23
+ else
24
+ raise NotImplementedError
25
+ end
26
+ end
17
27
  end
18
28
  NO_TYPED_CHILDREN = NoTypedChildren.new
19
29
 
@@ -154,8 +154,8 @@ module GraphQL
154
154
  def print_object_type_definition(object_type)
155
155
  out = print_description(object_type)
156
156
  out << "type #{object_type.name}"
157
- out << print_directives(object_type.directives)
158
157
  out << " implements " << object_type.interfaces.map(&:name).join(", ") unless object_type.interfaces.empty?
158
+ out << print_directives(object_type.directives)
159
159
  out << print_field_definitions(object_type.fields)
160
160
  end
161
161
 
@@ -22,6 +22,7 @@ require "graphql/schema/build_from_definition"
22
22
 
23
23
  require "graphql/schema/member"
24
24
  require "graphql/schema/argument"
25
+ require "graphql/schema/enum_value"
25
26
  require "graphql/schema/enum"
26
27
  require "graphql/schema/field"
27
28
  require "graphql/schema/input_object"
@@ -20,9 +20,6 @@ module GraphQL
20
20
  # end
21
21
  class Schema
22
22
  class Enum < GraphQL::Schema::Member
23
- # @api private
24
- Value = Struct.new(:name, :description, :value, :deprecation_reason)
25
-
26
23
  class << self
27
24
  # Define a value for this enum
28
25
  # @param graphql_name [String, Symbol] the GraphQL value for this, usually `SCREAMING_CASE`
@@ -30,10 +27,10 @@ module GraphQL
30
27
  # @param value [Object], the translated Ruby value for this object (defaults to `graphql_name`)
31
28
  # @param deprecation_reason [String] if this object is deprecated, include a message here
32
29
  # @return [void]
33
- def value(graphql_name, description = nil, value: nil, deprecation_reason: nil)
34
- graphql_name = graphql_name.to_s
35
- value ||= graphql_name
36
- own_values[graphql_name] = Value.new(graphql_name, description, value, deprecation_reason)
30
+ # @see {Schema::EnumValue} which handles these inputs by default
31
+ def value(*args, &block)
32
+ value = enum_value_class.new(*args, &block)
33
+ own_values[value.graphql_name] = value
37
34
  nil
38
35
  end
39
36
 
@@ -51,22 +48,27 @@ module GraphQL
51
48
  enum_type.description = description
52
49
  enum_type.introspection = introspection
53
50
  values.each do |name, val|
54
- enum_value = GraphQL::EnumType::EnumValue.new
55
- enum_value.name = val.name
56
- enum_value.description = val.description
57
- enum_value.value = val.value
58
- enum_value.deprecation_reason = val.deprecation_reason
59
- enum_type.add_value(enum_value)
51
+ enum_type.add_value(val.to_graphql)
60
52
  end
61
53
  enum_type
62
54
  end
63
55
 
56
+ # @return [Class] for handling `value(...)` inputs and building `GraphQL::Enum::EnumValue`s out of them
57
+ def enum_value_class(new_enum_value_class = nil)
58
+ if new_enum_value_class
59
+ @enum_value_class = new_enum_value_class
60
+ end
61
+ @enum_value_class || (superclass <= GraphQL::Schema::Enum ? superclass.enum_value_class : nil)
62
+ end
63
+
64
64
  private
65
65
 
66
66
  def own_values
67
67
  @own_values ||= {}
68
68
  end
69
69
  end
70
+
71
+ enum_value_class(GraphQL::Schema::EnumValue)
70
72
  end
71
73
  end
72
74
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # A possible value for an {Enum}.
6
+ #
7
+ # You can extend this class to customize enum values in your schema.
8
+ #
9
+ # @example custom enum value class
10
+ # # define a custom class:
11
+ # class CustomEnumValue < GraphQL::Schema::EnumValue
12
+ # def initialize(*args)
13
+ # # arguments to `value(...)` in Enum classes are passed here
14
+ # super
15
+ # end
16
+ #
17
+ # def to_graphql
18
+ # enum_value = super
19
+ # # customize the derived GraphQL::EnumValue here
20
+ # enum_value
21
+ # end
22
+ # end
23
+ #
24
+ # class BaseEnum < GraphQL::Schema::Enum
25
+ # # use it for these enums:
26
+ # enum_value_class CustomEnumValue
27
+ # end
28
+ class EnumValue < GraphQL::Schema::Member
29
+ attr_reader :graphql_name
30
+
31
+ def initialize(graphql_name, desc = nil, description: nil, value: nil, deprecation_reason: nil, &block)
32
+ @graphql_name = graphql_name.to_s
33
+ @description = desc || description
34
+ @value = value || @graphql_name
35
+ @deprecation_reason = deprecation_reason
36
+ if block_given?
37
+ instance_eval(&block)
38
+ end
39
+ end
40
+
41
+ def description(new_desc = nil)
42
+ if new_desc
43
+ @description = new_desc
44
+ end
45
+ @description
46
+ end
47
+
48
+ def value(new_val = nil)
49
+ if new_val
50
+ @value = new_val
51
+ end
52
+ @value
53
+ end
54
+
55
+ # @return [GraphQL::EnumType::EnumValue] A runtime-ready object derived from this object
56
+ def to_graphql
57
+ enum_value = GraphQL::EnumType::EnumValue.new
58
+ enum_value.name = @graphql_name
59
+ enum_value.description = @description
60
+ enum_value.value = @value
61
+ enum_value.deprecation_reason = @deprecation_reason
62
+ enum_value
63
+ end
64
+ end
65
+ end
66
+ end
@@ -59,6 +59,32 @@ module GraphQL
59
59
  .gsub(/([a-z\d])([A-Z])/,'\1_\2') # someThing -> some_Thing
60
60
  .downcase
61
61
  end
62
+
63
+ def apply_processor(input_text, processor)
64
+ ruby_ast = Parser::CurrentRuby.parse(input_text)
65
+ processor.process(ruby_ast)
66
+ processor
67
+ rescue Parser::SyntaxError
68
+ puts "Error text:"
69
+ puts input_text
70
+ raise
71
+ end
72
+
73
+ def reindent_lines(input_text, from_indent:, to_indent:)
74
+ prev_indent = " " * from_indent
75
+ next_indent = " " * to_indent
76
+ # For each line, remove the previous indent, then add the new indent
77
+ lines = input_text.split("\n").map do |line|
78
+ line = line.sub(prev_indent, "")
79
+ "#{next_indent}#{line}".rstrip
80
+ end
81
+ lines.join("\n")
82
+ end
83
+
84
+ # Remove trailing whitespace
85
+ def trim_lines(input_text)
86
+ input_text.gsub(/ +$/, "")
87
+ end
62
88
  end
63
89
 
64
90
  # Turns `{X} = GraphQL::{Y}Type.define do` into `class {X} < Types::Base{Y}`.
@@ -174,7 +200,7 @@ module GraphQL
174
200
  class RemoveRedundantKwargTransform < Transform
175
201
  def initialize(kwarg:)
176
202
  @kwarg = kwarg
177
- @finder_pattern = /(field|connection|argument) :(?<name>[a-zA-Z_0-9]*).*#{@kwarg}: ['":](?<kwarg_value>[a-zA-Z_0-9]+)['"]?/
203
+ @finder_pattern = /(field|connection|argument) :(?<name>[a-zA-Z_0-9]*).*#{@kwarg}: ['":](?<kwarg_value>[a-zA-Z_0-9?!]+)['"]?/
178
204
  end
179
205
 
180
206
  def apply(input_text)
@@ -203,6 +229,75 @@ module GraphQL
203
229
  end
204
230
  end
205
231
 
232
+ class ProcToClassMethodTransform < Transform
233
+ # @param proc_name [String] The name of the proc to be moved to `def self.#{proc_name}`
234
+ def initialize(proc_name)
235
+ @proc_name = proc_name
236
+ # This will tell us whether to operate on the input or not
237
+ @proc_check_pattern = /#{proc_name}\s?->/
238
+ end
239
+
240
+ def apply(input_text)
241
+ if input_text =~ @proc_check_pattern
242
+ processor = apply_processor(input_text, NamedProcProcessor.new(@proc_name))
243
+ proc_body = input_text[processor.proc_body_start..processor.proc_body_end]
244
+ method_defn_indent = " " * processor.proc_defn_indent
245
+ method_defn = "def self.#{@proc_name}(#{processor.proc_arg_names.join(", ")})\n#{method_defn_indent} #{proc_body}\n#{method_defn_indent}end\n"
246
+ method_defn = trim_lines(method_defn)
247
+ # replace the proc with the new method
248
+ input_text[processor.proc_defn_start..processor.proc_defn_end] = method_defn
249
+ end
250
+ input_text
251
+ end
252
+
253
+ class NamedProcProcessor < Parser::AST::Processor
254
+ attr_reader :proc_arg_names, :proc_defn_start, :proc_defn_end, :proc_defn_indent, :proc_body_start, :proc_body_end
255
+ def initialize(proc_name)
256
+ @proc_name_sym = proc_name.to_sym
257
+ @proc_arg_names = nil
258
+ # Beginning of the `#{proc_name} -> {...}` call
259
+ @proc_defn_start = nil
260
+ # End of the last `end/}`
261
+ @proc_defn_end = nil
262
+ # Amount of whitespace to insert to the rewritten body
263
+ @proc_defn_indent = nil
264
+ # First statement of the proc
265
+ @proc_body_start = nil
266
+ # End of last statement in the proc
267
+ @proc_body_end = nil
268
+ # Used for identifying the proper block
269
+ @inside_proc = false
270
+ end
271
+
272
+ def on_send(node)
273
+ receiver, method_name, _args = *node
274
+ if method_name == @proc_name_sym && receiver.nil?
275
+ source_exp = node.loc.expression
276
+ @proc_defn_start = source_exp.begin.begin_pos
277
+ @proc_defn_end = source_exp.end.end_pos
278
+ @proc_defn_indent = source_exp.column
279
+ @inside_proc = true
280
+ end
281
+ res = super(node)
282
+ @inside_proc = false
283
+ res
284
+ end
285
+
286
+ def on_block(node)
287
+ send_node, args_node, body_node = node.children
288
+ _receiver, method_name, _send_args_node = *send_node
289
+ if method_name == :lambda && @inside_proc
290
+ source_exp = body_node.loc.expression
291
+ @proc_arg_names = args_node.children.map { |arg_node| arg_node.children[0].to_s }
292
+ @proc_body_start = source_exp.begin.begin_pos
293
+ @proc_body_end = source_exp.end.end_pos
294
+ end
295
+ super(node)
296
+ end
297
+ end
298
+ end
299
+
300
+
206
301
  class ResolveProcToMethodTransform < Transform
207
302
  def apply(input_text)
208
303
  if input_text =~ /resolve ->/
@@ -226,15 +321,7 @@ module GraphQL
226
321
 
227
322
  input_text.match(/(?<field_type>input_field|field|connection|argument) :(?<name>[a-zA-Z_0-9_]*)/)
228
323
  field_name = $~[:name]
229
- begin
230
- field_ast = Parser::CurrentRuby.parse(input_text)
231
- rescue Parser::SyntaxError
232
- puts "Error text:"
233
- puts input_text
234
- raise
235
- end
236
- processor = ResolveProcProcessor.new
237
- processor.process(field_ast)
324
+ processor = apply_processor(input_text, ResolveProcProcessor.new)
238
325
  proc_body = input_text[processor.proc_start..processor.proc_end]
239
326
  obj_arg_name, args_arg_name, ctx_arg_name = processor.proc_arg_names
240
327
  # This is not good, it will hit false positives
@@ -242,15 +329,9 @@ module GraphQL
242
329
  proc_body.gsub!(/([^\w:]|^)#{obj_arg_name}([^\w]|$)/, '\1@object\2')
243
330
  proc_body.gsub!(/([^\w:]|^)#{ctx_arg_name}([^\w]|$)/, '\1@context\2')
244
331
 
245
- indent = " " * processor.resolve_indent
246
- prev_body_indent = "#{indent} "
247
- next_body_indent = indent
248
- method_def_indent = indent[2..-1]
332
+ method_def_indent = " " * (processor.resolve_indent - 2)
249
333
  # Turn the proc body into a method body
250
- lines = proc_body.split("\n").map do |line|
251
- line = line.sub(prev_body_indent, "")
252
- "#{next_body_indent}#{line}".rstrip
253
- end
334
+ method_body = reindent_lines(proc_body, from_indent: processor.resolve_indent + 2, to_indent: processor.resolve_indent)
254
335
  # Add `def... end`
255
336
  method_def = if input_text.include?("argument ")
256
337
  # This field has arguments
@@ -259,9 +340,8 @@ module GraphQL
259
340
  # No field arguments, so, no method arguments
260
341
  "def #{field_name}"
261
342
  end
262
- lines.unshift("\n#{method_def_indent}#{method_def}")
263
- lines << "#{method_def_indent}end\n"
264
- method_body = lines.join("\n")
343
+ # Wrap the body in def ... end
344
+ method_body = "\n#{method_def_indent}#{method_def}\n#{method_body}\n#{method_def_indent}end\n"
265
345
  # Update Argument access to be underscore and symbols
266
346
  # Update `args[...]` and `args.key?`
267
347
  method_body = method_body.gsub(/#{args_arg_name}(?<method_begin>\.key\?\(?|\[)["':](?<arg_name>[a-zA-Z0-9_]+)["']?(?<method_end>\]|\))?/) do
@@ -288,7 +368,6 @@ module GraphQL
288
368
  end
289
369
  end
290
370
 
291
-
292
371
  class ResolveProcProcessor < Parser::AST::Processor
293
372
  attr_reader :proc_start, :proc_end, :proc_arg_names, :resolve_start, :resolve_end, :resolve_indent
294
373
  def initialize
@@ -327,10 +406,9 @@ module GraphQL
327
406
 
328
407
  # Transform `interfaces [A, B, C]` to `implements A\nimplements B\nimplements C\n`
329
408
  class InterfacesToImplementsTransform < Transform
409
+ PATTERN = /(?<indent>\s*)(?:interfaces) \[\s*(?<interfaces>(?:[a-zA-Z_0-9:\.,\s]+))\]/m
330
410
  def apply(input_text)
331
- input_text.gsub(
332
- /(?<indent>\s*)(?:interfaces) \[\s*(?<interfaces>(?:[a-zA-Z_0-9:\.,\s]+))\]/m
333
- ) do
411
+ input_text.gsub(PATTERN) do
334
412
  indent = $~[:indent]
335
413
  interfaces = $~[:interfaces].split(',').map(&:strip).reject(&:empty?)
336
414
  # Preserve leading newlines before the `interfaces ...`
@@ -345,10 +423,26 @@ module GraphQL
345
423
  end
346
424
  end
347
425
 
426
+ # Transform `possible_types [A, B, C]` to `possible_types(A, B, C)`
427
+ class PossibleTypesTransform < Transform
428
+ PATTERN = /(?<indent>\s*)(?:possible_types) \[\s*(?<possible_types>(?:[a-zA-Z_0-9:\.,\s]+))\]/m
429
+ def apply(input_text)
430
+ input_text.gsub(PATTERN) do
431
+ indent = $~[:indent]
432
+ possible_types = $~[:possible_types].split(',').map(&:strip).reject(&:empty?)
433
+ extra_leading_newlines = indent[/^\n*/]
434
+ method_indent = indent.sub(/^\n*/m, "")
435
+ type_indent = " " + method_indent
436
+ possible_types_call = "#{method_indent}possible_types(\n#{possible_types.map { |t| "#{type_indent}#{t},"}.join("\n")}\n#{method_indent})"
437
+ extra_leading_newlines + trim_lines(possible_types_call)
438
+ end
439
+ end
440
+ end
441
+
348
442
  class UpdateMethodSignatureTransform < Transform
349
443
  def apply(input_text)
350
444
  input_text.scan(/(?:input_field|field|connection|argument) .*$/).each do |field|
351
- matches = /(?<field_type>input_field|field|connection|argument) :(?<name>[a-zA-Z_0-9_]*)?, (?<return_type>([A-Za-z\[\]\.\!_0-9]|::|-> ?\{ ?| ?\})+)(?<remainder>( |,|$).*)/.match(field)
445
+ matches = /(?<field_type>input_field|field|connection|argument) :(?<name>[a-zA-Z_0-9_]*)?(:?, (?<return_type>([A-Za-z\[\]\.\!_0-9\(\)]|::|-> ?\{ ?| ?\})+))?(?<remainder>( |,|$).*)/.match(field)
352
446
  if matches
353
447
  name = matches[:name]
354
448
  return_type = matches[:return_type]
@@ -361,7 +455,7 @@ module GraphQL
361
455
  remainder.chomp!
362
456
 
363
457
  if return_type
364
- non_nullable = return_type.gsub! '!', ''
458
+ non_nullable = return_type.sub! /(^|[^\[])!/, '\1'
365
459
  nullable = !non_nullable
366
460
  return_type = normalize_type_expression(return_type)
367
461
  return_type = return_type.gsub ',', ''
@@ -372,7 +466,11 @@ module GraphQL
372
466
 
373
467
  input_text.sub!(field) do
374
468
  is_argument = ['argument', 'input_field'].include?(field_type)
375
- f = "#{is_argument ? 'argument' : 'field'} :#{name}, #{return_type}"
469
+ f = "#{is_argument ? 'argument' : 'field'} :#{name}"
470
+
471
+ if return_type
472
+ f += ", #{return_type}"
473
+ end
376
474
 
377
475
  unless remainder.empty?
378
476
  f += ',' + remainder
@@ -428,11 +526,12 @@ module GraphQL
428
526
  end
429
527
 
430
528
  # Skip this file if you see any `field`
431
- # helpers with `null: true` or `null: false` keywords,
529
+ # helpers with `null: true` or `null: false` keywords
530
+ # or `argument` helpers with `required:` keywords,
432
531
  # because it's already been transformed
433
532
  class SkipOnNullKeyword
434
533
  def skip?(input_text)
435
- input_text =~ /field.*null: (true|false)/
534
+ input_text =~ /field.*null: (true|false)/ || input_text =~ /argument.*required: (true|false)/
436
535
  end
437
536
  end
438
537
 
@@ -449,6 +548,10 @@ module GraphQL
449
548
  TypeDefineToClassTransform,
450
549
  NameTransform,
451
550
  InterfacesToImplementsTransform,
551
+ PossibleTypesTransform,
552
+ ProcToClassMethodTransform.new("coerce_input"),
553
+ ProcToClassMethodTransform.new("coerce_result"),
554
+ ProcToClassMethodTransform.new("resolve_type"),
452
555
  ]
453
556
 
454
557
  DEFAULT_FIELD_TRANSFORMS = [
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.8.0.pre5"
3
+ VERSION = "1.8.0.pre6"
4
4
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Unions
5
+ Account = GraphQL::UnionType.define do
6
+ name "Account"
7
+ description "Users and organizations."
8
+ visibility :internal
9
+
10
+ possible_types [
11
+ Objects::User,
12
+ Objects::Organization,
13
+ Objects::Bot
14
+ ]
15
+
16
+ resolve_type ->(obj, ctx) { :stand_in }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Unions
5
+ class Account < Platform::Unions::Base
6
+ description "Users and organizations."
7
+ visibility :internal
8
+
9
+ possible_types(
10
+ Objects::User,
11
+ Objects::Organization,
12
+ Objects::Bot,
13
+ )
14
+
15
+ def self.resolve_type(obj, ctx)
16
+ :stand_in
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Scalars
5
+ DateTime = GraphQL::ScalarType.define do
6
+ name "DateTime"
7
+ description "An ISO-8601 encoded UTC date string."
8
+
9
+ # rubocop:disable Layout/SpaceInLambdaLiteral
10
+ coerce_input -> (value, context) do
11
+ begin
12
+ Time.iso8601(value)
13
+ rescue ArgumentError, ::TypeError
14
+ end
15
+ end
16
+ # rubocop:enable Layout/SpaceInLambdaLiteral
17
+
18
+ coerce_result ->(value, context) do
19
+ return nil unless value
20
+ value.utc.iso8601
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Scalars
5
+ class DateTime < Platform::Scalars::Base
6
+ description "An ISO-8601 encoded UTC date string."
7
+
8
+ # rubocop:disable Layout/SpaceInLambdaLiteral
9
+ def self.coerce_input(value, context)
10
+ begin
11
+ Time.iso8601(value)
12
+ rescue ArgumentError, ::TypeError
13
+ end
14
+ end
15
+ # rubocop:enable Layout/SpaceInLambdaLiteral
16
+
17
+ def self.coerce_result(value, context)
18
+ return nil unless value
19
+ value.utc.iso8601
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Enums
5
+ GistOrderField = GraphQL::EnumType.define do
6
+ name "GistOrderField"
7
+ description "Properties by which gist connections can be ordered."
8
+
9
+ value "CREATED_AT", "Order gists by creation time", value: "created_at"
10
+ value "UPDATED_AT", "Order gists by update time", value: "updated_at"
11
+ value "PUSHED_AT", "Order gists by push time", value: "pushed_at"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Enums
5
+ class GistOrderField < Platform::Enums::Base
6
+ description "Properties by which gist connections can be ordered."
7
+
8
+ value "CREATED_AT", "Order gists by creation time", value: "created_at"
9
+ value "UPDATED_AT", "Order gists by update time", value: "updated_at"
10
+ value "PUSHED_AT", "Order gists by push time", value: "pushed_at"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Inputs
5
+ ReleaseOrder = GraphQL::InputObjectType.define do
6
+ name "ReleaseOrder"
7
+ description "Ways in which lists of releases can be ordered upon return."
8
+
9
+ input_field :field, types[!Enums::ReleaseOrderField], <<-MD
10
+ The field in which to order releases by.
11
+ MD
12
+ input_field :direction, !Enums::OrderDirection, "The direction in which to order releases by the specified field."
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Platform
4
+ module Inputs
5
+ class ReleaseOrder < Platform::Inputs::Base
6
+ description "Ways in which lists of releases can be ordered upon return."
7
+
8
+ argument :field, [Enums::ReleaseOrderField], <<-MD, required: false
9
+ The field in which to order releases by.
10
+ MD
11
+ argument :direction, Enums::OrderDirection, "The direction in which to order releases by the specified field.", required: true
12
+ end
13
+ end
14
+ end
@@ -46,6 +46,10 @@ module Platform
46
46
  subscribable.async_subscription_status(context[:viewer]).then(&:success?)
47
47
  end
48
48
  end
49
+
50
+ connection :issues, function: Platform::Functions::Issues.new, description: "A list of issues associated with the milestone."
51
+ connection :files, -> { !Connections.define(PackageFile) }, description: "List of files associated with this registry package version"
52
+ field :enabled, !types.Boolean, "Whether enabled for this project", property: :enabled?
49
53
  end
50
54
  end
51
55
  end
@@ -41,6 +41,10 @@ module Platform
41
41
 
42
42
  @object.async_subscription_status(@context[:viewer]).then(&:success?)
43
43
  end
44
+
45
+ field :issues, function: Platform::Functions::Issues.new, description: "A list of issues associated with the milestone.", connection: true
46
+ field :files, Connections.define(PackageFile), description: "List of files associated with this registry package version", null: false, connection: true
47
+ field :enabled, Boolean, "Whether enabled for this project", method: :enabled?, null: false
44
48
  end
45
49
  end
46
50
  end
@@ -105,7 +105,7 @@ describe GraphQL::Language::Printer do
105
105
  end
106
106
 
107
107
  describe "full featured schema" do
108
- # From: https://github.com/graphql/graphql-js/blob/bc96406ab44453a120da25a0bd6e2b0237119ddf/src/language/__tests__/schema-kitchen-sink.graphql
108
+ # Based on: https://github.com/graphql/graphql-js/blob/bc96406ab44453a120da25a0bd6e2b0237119ddf/src/language/__tests__/schema-kitchen-sink.graphql
109
109
  let(:query_string) {<<-schema
110
110
  schema {
111
111
  query: QueryType
@@ -128,7 +128,7 @@ describe GraphQL::Language::Printer do
128
128
  # Scalar description
129
129
  scalar CustomScalar
130
130
 
131
- type AnnotatedObject @onObject(arg: "value") {
131
+ type AnnotatedObject implements Bar @onObject(arg: "value") {
132
132
  annotatedField(arg: Type = "default" @onArg): Type @onField
133
133
  }
134
134
 
@@ -24,8 +24,17 @@ describe GraphQL::Schema::Enum do
24
24
  perc_value = new_enum.values["PERCUSSION"]
25
25
  assert_equal "new description", perc_value.description
26
26
  end
27
+
28
+ it "accepts a block" do
29
+ assert_equal "Neither here nor there, really", enum.values["KEYS"].description
30
+ end
27
31
  end
28
32
 
33
+ it "uses a custom enum value class" do
34
+ enum_type = enum.to_graphql
35
+ value = enum_type.values["STRING"]
36
+ assert_equal 1, value.metadata[:custom_setting]
37
+ end
29
38
 
30
39
  describe ".to_graphql" do
31
40
  it "creates an EnumType" do
@@ -463,6 +463,13 @@ describe GraphQL::Upgrader::Member do
463
463
  end
464
464
  end
465
465
 
466
+ # Modify the default output to match the custom structure
467
+ class InputObjectsToInputsTransform < GraphQL::Upgrader::Transform
468
+ def apply(input_text)
469
+ input_text.gsub("Platform::InputObjects::", "Platform::Inputs::")
470
+ end
471
+ end
472
+
466
473
  def custom_upgrade(original_text)
467
474
  # Replace the default one with a custom one:
468
475
  type_transforms = GraphQL::Upgrader::Member::DEFAULT_TYPE_TRANSFORMS.map { |t|
@@ -474,7 +481,8 @@ describe GraphQL::Upgrader::Member do
474
481
  }
475
482
 
476
483
  type_transforms.unshift(ActiveRecordTypeToClassTransform)
477
- field_transforms = GraphQL::Upgrader::Member::DEFAULT_FIELD_TRANSFORMS
484
+ type_transforms.push(InputObjectsToInputsTransform)
485
+ field_transforms = GraphQL::Upgrader::Member::DEFAULT_FIELD_TRANSFORMS.dup
478
486
  field_transforms.unshift(GraphQL::Upgrader::ConfigurationToKwargTransform.new(kwarg: "visibility"))
479
487
  upgrader = GraphQL::Upgrader::Member.new(original_text, type_transforms: type_transforms, field_transforms: field_transforms)
480
488
  upgrader.upgrade
@@ -485,6 +493,7 @@ describe GraphQL::Upgrader::Member do
485
493
  transformed_file = original_file.sub(".original.", ".transformed.")
486
494
  original_text = File.read(original_file)
487
495
  expected_text = File.read(transformed_file)
496
+
488
497
  it "transforms #{original_file} -> #{transformed_file}" do
489
498
  transformed_text = custom_upgrade(original_text)
490
499
  assert_equal(expected_text, transformed_text)
@@ -104,6 +104,22 @@ module Jazz
104
104
  field_class BaseField
105
105
  end
106
106
 
107
+ class BaseEnumValue < GraphQL::Schema::EnumValue
108
+ def initialize(*args, custom_setting: nil, **kwargs, &block)
109
+ @custom_setting = custom_setting
110
+ super(*args, **kwargs, &block)
111
+ end
112
+
113
+ def to_graphql
114
+ enum_value_defn = super
115
+ enum_value_defn.metadata[:custom_setting] = @custom_setting
116
+ enum_value_defn
117
+ end
118
+ end
119
+
120
+ class BaseEnum < GraphQL::Schema::Enum
121
+ enum_value_class BaseEnumValue
122
+ end
107
123
 
108
124
  # Some arbitrary global ID scheme
109
125
  # *Type suffix is removed automatically
@@ -154,15 +170,17 @@ module Jazz
154
170
  field :musicians, "[Jazz::Musician]", null: false
155
171
  end
156
172
 
157
- class Family < GraphQL::Schema::Enum
173
+ class Family < BaseEnum
158
174
  description "Groups of musical instruments"
159
175
  # support string and symbol
160
- value "STRING", "Makes a sound by vibrating strings", value: :str
176
+ value "STRING", "Makes a sound by vibrating strings", value: :str, custom_setting: 1
161
177
  value :WOODWIND, "Makes a sound by vibrating air in a pipe"
162
178
  value :BRASS, "Makes a sound by amplifying the sound of buzzing lips"
163
179
  value "PERCUSSION", "Makes a sound by hitting something that vibrates"
164
- value "KEYS", "Neither here nor there, really"
165
180
  value "DIDGERIDOO", "Makes a sound by amplifying the sound of buzzing lips", deprecation_reason: "Merged into BRASS"
181
+ value "KEYS" do
182
+ description "Neither here nor there, really"
183
+ end
166
184
  end
167
185
 
168
186
  # Lives side-by-side with an old-style definition
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0.pre5
4
+ version: 1.8.0.pre6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-01 00:00:00.000000000 Z
11
+ date: 2018-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -511,6 +511,7 @@ files:
511
511
  - lib/graphql/schema/default_parse_error.rb
512
512
  - lib/graphql/schema/default_type_error.rb
513
513
  - lib/graphql/schema/enum.rb
514
+ - lib/graphql/schema/enum_value.rb
514
515
  - lib/graphql/schema/field.rb
515
516
  - lib/graphql/schema/field/dynamic_resolve.rb
516
517
  - lib/graphql/schema/field/unwrapped_resolve.rb
@@ -899,8 +900,16 @@ files:
899
900
  - spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zywotY5ANjNyE78CLDqC1eYRFwL1ZFzkT9J5LzNlI4M.cache
900
901
  - spec/dummy/tmp/restart.txt
901
902
  - spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png
903
+ - spec/fixtures/upgrader/account.original.rb
904
+ - spec/fixtures/upgrader/account.transformed.rb
902
905
  - spec/fixtures/upgrader/blame_range.original.rb
903
906
  - spec/fixtures/upgrader/blame_range.transformed.rb
907
+ - spec/fixtures/upgrader/date_time.original.rb
908
+ - spec/fixtures/upgrader/date_time.transformed.rb
909
+ - spec/fixtures/upgrader/gist_order_field.original.rb
910
+ - spec/fixtures/upgrader/gist_order_field.transformed.rb
911
+ - spec/fixtures/upgrader/release_order.original.rb
912
+ - spec/fixtures/upgrader/release_order.transformed.rb
904
913
  - spec/fixtures/upgrader/subscribable.original.rb
905
914
  - spec/fixtures/upgrader/subscribable.transformed.rb
906
915
  - spec/fixtures/upgrader/type_x.original.rb
@@ -1390,8 +1399,16 @@ test_files:
1390
1399
  - spec/dummy/tmp/cache/assets/sprockets/v3.0/Zz/Zzsh2ASGqBSWLSWIU4fAyxS3iVuJDxdTCw8jOOsUNzA.cache
1391
1400
  - spec/dummy/tmp/restart.txt
1392
1401
  - spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png
1402
+ - spec/fixtures/upgrader/account.original.rb
1403
+ - spec/fixtures/upgrader/account.transformed.rb
1393
1404
  - spec/fixtures/upgrader/blame_range.original.rb
1394
1405
  - spec/fixtures/upgrader/blame_range.transformed.rb
1406
+ - spec/fixtures/upgrader/date_time.original.rb
1407
+ - spec/fixtures/upgrader/date_time.transformed.rb
1408
+ - spec/fixtures/upgrader/gist_order_field.original.rb
1409
+ - spec/fixtures/upgrader/gist_order_field.transformed.rb
1410
+ - spec/fixtures/upgrader/release_order.original.rb
1411
+ - spec/fixtures/upgrader/release_order.transformed.rb
1395
1412
  - spec/fixtures/upgrader/subscribable.original.rb
1396
1413
  - spec/fixtures/upgrader/subscribable.transformed.rb
1397
1414
  - spec/fixtures/upgrader/type_x.original.rb