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 +4 -4
- data/lib/graphql/internal_representation/node.rb +10 -0
- data/lib/graphql/language/printer.rb +1 -1
- data/lib/graphql/schema.rb +1 -0
- data/lib/graphql/schema/enum.rb +15 -13
- data/lib/graphql/schema/enum_value.rb +66 -0
- data/lib/graphql/upgrader/member.rb +133 -30
- data/lib/graphql/version.rb +1 -1
- data/spec/fixtures/upgrader/account.original.rb +19 -0
- data/spec/fixtures/upgrader/account.transformed.rb +20 -0
- data/spec/fixtures/upgrader/date_time.original.rb +24 -0
- data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
- data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
- data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
- data/spec/fixtures/upgrader/release_order.original.rb +15 -0
- data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
- data/spec/fixtures/upgrader/subscribable.original.rb +4 -0
- data/spec/fixtures/upgrader/subscribable.transformed.rb +4 -0
- data/spec/graphql/language/printer_spec.rb +2 -2
- data/spec/graphql/schema/enum_spec.rb +9 -0
- data/spec/graphql/upgrader/member_spec.rb +10 -1
- data/spec/support/jazz.rb +21 -3
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d974acad8e306ebc40d3ef5185293be78a6172a7
|
4
|
+
data.tar.gz: 68befc3fffce8764a3bd14173ecc55484dad4fc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -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"
|
data/lib/graphql/schema/enum.rb
CHANGED
@@ -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
|
-
|
34
|
-
|
35
|
-
value
|
36
|
-
own_values[graphql_name] =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
263
|
-
|
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_]*)
|
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.
|
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}
|
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 = [
|
data/lib/graphql/version.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
|
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)
|
data/spec/support/jazz.rb
CHANGED
@@ -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 <
|
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.
|
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-
|
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
|