graphql 1.5.13 → 1.5.14

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.
@@ -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