graphql 1.8.0.pre5 → 1.8.0.pre6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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