graphql 1.5.13 → 1.5.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,40 +49,40 @@
49
49
  UNKNOWN_CHAR = /./;
50
50
 
51
51
  main := |*
52
- INT => { emit_token.call(:INT) };
53
- FLOAT => { emit_token.call(:FLOAT) };
54
- ON => { emit_token.call(:ON) };
55
- FRAGMENT => { emit_token.call(:FRAGMENT) };
56
- TRUE => { emit_token.call(:TRUE) };
57
- FALSE => { emit_token.call(:FALSE) };
58
- NULL => { emit_token.call(:NULL) };
59
- QUERY => { emit_token.call(:QUERY) };
60
- MUTATION => { emit_token.call(:MUTATION) };
61
- SUBSCRIPTION => { emit_token.call(:SUBSCRIPTION) };
62
- SCHEMA => { emit_token.call(:SCHEMA) };
63
- SCALAR => { emit_token.call(:SCALAR) };
64
- TYPE => { emit_token.call(:TYPE) };
65
- IMPLEMENTS => { emit_token.call(:IMPLEMENTS) };
66
- INTERFACE => { emit_token.call(:INTERFACE) };
67
- UNION => { emit_token.call(:UNION) };
68
- ENUM => { emit_token.call(:ENUM) };
69
- INPUT => { emit_token.call(:INPUT) };
70
- DIRECTIVE => { emit_token.call(:DIRECTIVE) };
71
- RCURLY => { emit_token.call(:RCURLY) };
72
- LCURLY => { emit_token.call(:LCURLY) };
73
- RPAREN => { emit_token.call(:RPAREN) };
74
- LPAREN => { emit_token.call(:LPAREN) };
75
- RBRACKET => { emit_token.call(:RBRACKET) };
76
- LBRACKET => { emit_token.call(:LBRACKET) };
77
- COLON => { emit_token.call(:COLON) };
52
+ INT => { emit(:INT, ts, te, meta) };
53
+ FLOAT => { emit(:FLOAT, ts, te, meta) };
54
+ ON => { emit(:ON, ts, te, meta) };
55
+ FRAGMENT => { emit(:FRAGMENT, ts, te, meta) };
56
+ TRUE => { emit(:TRUE, ts, te, meta) };
57
+ FALSE => { emit(:FALSE, ts, te, meta) };
58
+ NULL => { emit(:NULL, ts, te, meta) };
59
+ QUERY => { emit(:QUERY, ts, te, meta) };
60
+ MUTATION => { emit(:MUTATION, ts, te, meta) };
61
+ SUBSCRIPTION => { emit(:SUBSCRIPTION, ts, te, meta) };
62
+ SCHEMA => { emit(:SCHEMA, ts, te, meta) };
63
+ SCALAR => { emit(:SCALAR, ts, te, meta) };
64
+ TYPE => { emit(:TYPE, ts, te, meta) };
65
+ IMPLEMENTS => { emit(:IMPLEMENTS, ts, te, meta) };
66
+ INTERFACE => { emit(:INTERFACE, ts, te, meta) };
67
+ UNION => { emit(:UNION, ts, te, meta) };
68
+ ENUM => { emit(:ENUM, ts, te, meta) };
69
+ INPUT => { emit(:INPUT, ts, te, meta) };
70
+ DIRECTIVE => { emit(:DIRECTIVE, ts, te, meta) };
71
+ RCURLY => { emit(:RCURLY, ts, te, meta) };
72
+ LCURLY => { emit(:LCURLY, ts, te, meta) };
73
+ RPAREN => { emit(:RPAREN, ts, te, meta) };
74
+ LPAREN => { emit(:LPAREN, ts, te, meta) };
75
+ RBRACKET => { emit(:RBRACKET, ts, te, meta) };
76
+ LBRACKET => { emit(:LBRACKET, ts, te, meta) };
77
+ COLON => { emit(:COLON, ts, te, meta) };
78
78
  QUOTED_STRING => { emit_string(ts + 1, te - 1, meta) };
79
- VAR_SIGN => { emit_token.call(:VAR_SIGN) };
80
- DIR_SIGN => { emit_token.call(:DIR_SIGN) };
81
- ELLIPSIS => { emit_token.call(:ELLIPSIS) };
82
- EQUALS => { emit_token.call(:EQUALS) };
83
- BANG => { emit_token.call(:BANG) };
84
- PIPE => { emit_token.call(:PIPE) };
85
- IDENTIFIER => { emit_token.call(:IDENTIFIER) };
79
+ VAR_SIGN => { emit(:VAR_SIGN, ts, te, meta) };
80
+ DIR_SIGN => { emit(:DIR_SIGN, ts, te, meta) };
81
+ ELLIPSIS => { emit(:ELLIPSIS, ts, te, meta) };
82
+ EQUALS => { emit(:EQUALS, ts, te, meta) };
83
+ BANG => { emit(:BANG, ts, te, meta) };
84
+ PIPE => { emit(:PIPE, ts, te, meta) };
85
+ IDENTIFIER => { emit(:IDENTIFIER, ts, te, meta) };
86
86
  COMMENT => { record_comment(ts, te, meta) };
87
87
 
88
88
  NEWLINE => {
@@ -92,7 +92,7 @@
92
92
 
93
93
  BLANK => { meta[:col] += te - ts };
94
94
 
95
- UNKNOWN_CHAR => { emit_token.call(:UNKNOWN_CHAR) };
95
+ UNKNOWN_CHAR => { emit(:UNKNOWN_CHAR, ts, te, meta) };
96
96
 
97
97
  *|;
98
98
  }%%
@@ -131,11 +131,10 @@ module GraphQL
131
131
  previous_token: nil,
132
132
  }
133
133
 
134
- %% write init;
134
+ p ||= 0
135
+ pe ||= data.length
135
136
 
136
- emit_token = ->(name) {
137
- emit(name, ts, te, meta)
138
- }
137
+ %% write init;
139
138
 
140
139
  %% write exec;
141
140
 
@@ -32,8 +32,8 @@ module GraphQL
32
32
  connection_arguments = DEFAULT_ARGUMENTS.merge(field.arguments)
33
33
  original_resolve = field.resolve_proc
34
34
  original_lazy_resolve = field.lazy_resolve_proc
35
- connection_resolve = GraphQL::Relay::ConnectionResolve.new(field, original_resolve)
36
- connection_lazy_resolve = GraphQL::Relay::ConnectionResolve.new(field, original_lazy_resolve)
35
+ connection_resolve = GraphQL::Relay::ConnectionResolve.new(field, original_resolve, lazy: false)
36
+ connection_lazy_resolve = GraphQL::Relay::ConnectionResolve.new(field, original_lazy_resolve, lazy: true)
37
37
  field.redefine(
38
38
  resolve: connection_resolve,
39
39
  lazy_resolve: connection_lazy_resolve,
@@ -2,21 +2,33 @@
2
2
  module GraphQL
3
3
  module Relay
4
4
  class ConnectionResolve
5
- def initialize(field, underlying_resolve)
5
+ def initialize(field, underlying_resolve, lazy:)
6
6
  @field = field
7
7
  @underlying_resolve = underlying_resolve
8
8
  @max_page_size = field.connection_max_page_size
9
+ @lazy = lazy
9
10
  end
10
11
 
11
12
  def call(obj, args, ctx)
13
+ if @lazy && obj.is_a?(LazyNodesWrapper)
14
+ parent = obj.parent
15
+ obj = obj.lazy_object
16
+ else
17
+ parent = obj
18
+ end
19
+
12
20
  nodes = @underlying_resolve.call(obj, args, ctx)
13
21
 
14
22
  if nodes.nil?
15
23
  nil
16
24
  elsif ctx.schema.lazy?(nodes)
17
- nodes
25
+ if !@lazy
26
+ LazyNodesWrapper.new(obj, nodes)
27
+ else
28
+ nodes
29
+ end
18
30
  else
19
- build_connection(nodes, args, obj, ctx)
31
+ build_connection(nodes, args, parent, ctx)
20
32
  end
21
33
  end
22
34
 
@@ -31,6 +43,16 @@ module GraphQL
31
43
  connection_class.new(nodes, args, field: @field, max_page_size: @max_page_size, parent: parent, context: ctx)
32
44
  end
33
45
  end
46
+
47
+ # A container for the proper `parent` of connection nodes.
48
+ # Without this wrapper, the lazy object _itself_ is passed into `build_connection`
49
+ # and it becomes the parent, which is wrong.
50
+ #
51
+ # We can get away with it because we know that this instrumentation will be applied last.
52
+ # That means its code after `underlying_resolve` will be _last_ on the way in.
53
+ # And, its code before `underlying_resolve` will be _first_ during lazy resolution.
54
+ # @api private
55
+ LazyNodesWrapper = Struct.new(:parent, :lazy_object)
34
56
  end
35
57
  end
36
58
  end
@@ -111,6 +111,7 @@ module GraphQL
111
111
  @parse_error_proc = DefaultParseError
112
112
  @instrumenters = Hash.new { |h, k| h[k] = [] }
113
113
  @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
114
+ @lazy_methods.set(GraphQL::Relay::ConnectionResolve::LazyNodesWrapper, :never_called)
114
115
  @cursor_encoder = Base64Encoder
115
116
  # Default to the built-in execution strategy:
116
117
  @query_execution_strategy = self.class.default_execution_strategy
@@ -15,8 +15,8 @@ module GraphQL
15
15
  def encode(type_name, object_value, separator: self.default_id_separator)
16
16
  object_value_str = object_value.to_s
17
17
 
18
- if type_name.include?(separator) || object_value_str.include?(separator)
19
- raise "encode(#{type_name}, #{object_value_str}) contains reserved characters `#{separator}`"
18
+ if type_name.include?(separator)
19
+ raise "encode(#{type_name}, #{object_value_str}) contains reserved characters `#{separator}` in the type name"
20
20
  end
21
21
 
22
22
  Base64.strict_encode64([type_name, object_value_str].join(separator))
@@ -25,7 +25,7 @@ module GraphQL
25
25
  # @param node_id [String] A unique ID generated by {.encode}
26
26
  # @return [Array<(String, String)>] The type name & value passed to {.encode}
27
27
  def decode(node_id, separator: self.default_id_separator)
28
- Base64.decode64(node_id).split(separator)
28
+ Base64.decode64(node_id).split(separator, 2)
29
29
  end
30
30
  end
31
31
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.5.13"
3
+ VERSION = "1.5.14"
4
4
  end
@@ -14,7 +14,7 @@ module Garden
14
14
  include GraphQL::Define::InstanceDefinable
15
15
  attr_accessor :name, :start_planting_on, :end_planting_on
16
16
  ensure_defined(:name, :start_planting_on, :end_planting_on)
17
- accepts_definitions :name, plant_between: DefinePlantBetween, color: GraphQL::Define.assign_metadata_key(:color)
17
+ accepts_definitions :name, plant_between: DefinePlantBetween, has_leaves: GraphQL::Define.assign_metadata_key(:has_leaves), color: GraphQL::Define.assign_metadata_key(:color)
18
18
 
19
19
  # definition added later:
20
20
  attr_accessor :height
@@ -58,6 +58,14 @@ describe GraphQL::Define::InstanceDefinable do
58
58
  assert_equal Date.new(2000, 4, 20), tomato.start_planting_on
59
59
  assert_equal Date.new(2000, 6, 1), tomato.end_planting_on
60
60
  end
61
+
62
+ it "accepts bare definitions" do
63
+ radish = Garden::Vegetable.define do
64
+ name "Radish"
65
+ has_leaves
66
+ end
67
+ assert_equal true, radish.metadata[:has_leaves]
68
+ end
61
69
  end
62
70
 
63
71
  describe ".define with keywords" do
@@ -11,6 +11,7 @@ describe GraphQL::Relay::ConnectionResolve do
11
11
  name
12
12
  }
13
13
  }
14
+ parentClassName
14
15
  }
15
16
  }
16
17
  }
@@ -43,6 +44,15 @@ describe GraphQL::Relay::ConnectionResolve do
43
44
  end
44
45
  end
45
46
 
47
+
48
+ describe "when a lazy object is returned" do
49
+ it "returns the items with the correct parent" do
50
+ result = star_wars_query(query_string, { "name" => "lazyObject"})
51
+ assert_equal 5, result["data"]["rebels"]["ships"]["edges"].length
52
+ assert_equal "StarWars::FactionRecord", result["data"]["rebels"]["ships"]["parentClassName"]
53
+ end
54
+ end
55
+
46
56
  describe "when nil is returned" do
47
57
  it "becomes null" do
48
58
  result = star_wars_query(query_string, { "name" => "null" })
@@ -27,11 +27,18 @@ describe GraphQL::Schema::UniqueWithinType do
27
27
  assert_equal("250cda0e-a89d-41cf-99e1-2872d89f1100", id)
28
28
  end
29
29
 
30
- it "raises an error if you try and use a reserved character in the ID" do
30
+ it "allows using the separator in the ID" do
31
+ global_id = GraphQL::Schema::UniqueWithinType.encode("SomeUUIDType", "250cda0e-a89d-41cf-99e1-2872d89f1100")
32
+ type_name, id = GraphQL::Schema::UniqueWithinType.decode(global_id)
33
+ assert_equal("SomeUUIDType", type_name)
34
+ assert_equal("250cda0e-a89d-41cf-99e1-2872d89f1100", id)
35
+ end
36
+
37
+ it "raises an error if you try and use a reserved character in the typename" do
31
38
  err = assert_raises(RuntimeError) {
32
- GraphQL::Schema::UniqueWithinType.encode("Best-Thing", "234")
39
+ GraphQL::Schema::UniqueWithinType.encode("Best-Thing", "234-567")
33
40
  }
34
- assert_includes err.message, "encode(Best-Thing, 234) contains reserved characters `-`"
41
+ assert_includes err.message, "encode(Best-Thing, 234-567) contains reserved characters `-` in the type name"
35
42
  end
36
43
  end
37
44
  end
@@ -55,7 +55,18 @@ module StarWars
55
55
  class SequelBase < Sequel::Model(:bases)
56
56
  end
57
57
 
58
- rebels = OpenStruct.new({
58
+ class FactionRecord
59
+ attr_reader :id, :name, :ships, :bases, :basesClone
60
+ def initialize(id:, name:, ships:, bases:, basesClone:)
61
+ @id = id
62
+ @name = name
63
+ @ships = ships
64
+ @bases = bases
65
+ @basesClone = basesClone
66
+ end
67
+ end
68
+
69
+ rebels = FactionRecord.new({
59
70
  id: '1',
60
71
  name: 'Alliance to Restore the Republic',
61
72
  ships: ['1', '2', '3', '4', '5'],
@@ -64,7 +75,7 @@ module StarWars
64
75
  })
65
76
 
66
77
 
67
- empire = OpenStruct.new({
78
+ empire = FactionRecord.new({
68
79
  id: '2',
69
80
  name: 'Galactic Empire',
70
81
  ships: ['6', '7', '8'],
@@ -83,13 +83,20 @@ module StarWars
83
83
  type Ship.connection_type
84
84
  end
85
85
 
86
+ ShipConnectionWithParentType = Ship.define_connection do
87
+ name "ShipConnectionWithParent"
88
+ field :parentClassName, !types.String do
89
+ resolve ->(o, a, c) { o.parent.class.name }
90
+ end
91
+ end
92
+
86
93
  Faction = GraphQL::ObjectType.define do
87
94
  name "Faction"
88
95
  interfaces [GraphQL::Relay::Node.interface]
89
96
 
90
97
  field :id, !types.ID, resolve: GraphQL::Relay::GlobalIdResolve.new(type: Faction)
91
98
  field :name, types.String
92
- connection :ships, Ship.connection_type do
99
+ connection :ships, ShipConnectionWithParentType do
93
100
  resolve ->(obj, args, ctx) {
94
101
  all_ships = obj.ships.map {|ship_id| StarWars::DATA["Ship"][ship_id] }
95
102
  if args[:nameIncludes]
@@ -104,6 +111,9 @@ module StarWars
104
111
  all_ships = LazyWrapper.new { raise GraphQL::ExecutionError.new("lazy raised error from within connection") }
105
112
  when "null"
106
113
  all_ships = nil
114
+ when "lazyObject"
115
+ prev_all_ships = all_ships
116
+ all_ships = LazyWrapper.new { prev_all_ships }
107
117
  else
108
118
  all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])}
109
119
  end
@@ -154,7 +164,7 @@ module StarWars
154
164
  resolve ->(obj, args, ctx) {
155
165
  all_bases = SequelBase.where(faction_id: obj.id)
156
166
  if args[:nameIncludes]
157
- all_bases = all_bases.where("name LIKE ?", "%#{args[:nameIncludes]}%")
167
+ all_bases = all_bases.where(Sequel.like(:name, "%#{args[:nameIncludes]}%"))
158
168
  end
159
169
  all_bases
160
170
  }
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.5.13
4
+ version: 1.5.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-11 00:00:00.000000000 Z
11
+ date: 2017-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips