graphql 1.5.15 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +4 -19
  3. data/lib/graphql/analysis/analyze_query.rb +27 -2
  4. data/lib/graphql/analysis/query_complexity.rb +10 -11
  5. data/lib/graphql/argument.rb +7 -6
  6. data/lib/graphql/backwards_compatibility.rb +47 -0
  7. data/lib/graphql/compatibility/execution_specification.rb +14 -0
  8. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +6 -1
  9. data/lib/graphql/compatibility/lazy_execution_specification.rb +19 -0
  10. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +15 -6
  11. data/lib/graphql/directive.rb +1 -6
  12. data/lib/graphql/execution.rb +1 -0
  13. data/lib/graphql/execution/execute.rb +174 -160
  14. data/lib/graphql/execution/field_result.rb +5 -1
  15. data/lib/graphql/execution/lazy.rb +2 -2
  16. data/lib/graphql/execution/lazy/resolve.rb +8 -11
  17. data/lib/graphql/execution/multiplex.rb +134 -0
  18. data/lib/graphql/execution/selection_result.rb +5 -0
  19. data/lib/graphql/field.rb +1 -8
  20. data/lib/graphql/filter.rb +53 -0
  21. data/lib/graphql/internal_representation/node.rb +11 -6
  22. data/lib/graphql/internal_representation/rewrite.rb +3 -3
  23. data/lib/graphql/query.rb +160 -78
  24. data/lib/graphql/query/arguments.rb +14 -25
  25. data/lib/graphql/query/arguments_cache.rb +6 -13
  26. data/lib/graphql/query/context.rb +28 -10
  27. data/lib/graphql/query/executor.rb +1 -0
  28. data/lib/graphql/query/literal_input.rb +10 -4
  29. data/lib/graphql/query/null_context.rb +1 -1
  30. data/lib/graphql/query/serial_execution/field_resolution.rb +5 -1
  31. data/lib/graphql/query/validation_pipeline.rb +12 -7
  32. data/lib/graphql/query/variables.rb +1 -1
  33. data/lib/graphql/rake_task.rb +140 -0
  34. data/lib/graphql/relay/array_connection.rb +29 -48
  35. data/lib/graphql/relay/base_connection.rb +9 -7
  36. data/lib/graphql/relay/mutation.rb +0 -11
  37. data/lib/graphql/relay/mutation/instrumentation.rb +2 -2
  38. data/lib/graphql/relay/mutation/resolve.rb +7 -10
  39. data/lib/graphql/relay/relation_connection.rb +98 -61
  40. data/lib/graphql/scalar_type.rb +1 -15
  41. data/lib/graphql/schema.rb +90 -25
  42. data/lib/graphql/schema/build_from_definition.rb +22 -23
  43. data/lib/graphql/schema/build_from_definition/resolve_map.rb +70 -0
  44. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
  45. data/lib/graphql/schema/middleware_chain.rb +1 -1
  46. data/lib/graphql/schema/printer.rb +2 -1
  47. data/lib/graphql/schema/timeout_middleware.rb +6 -6
  48. data/lib/graphql/schema/type_map.rb +1 -1
  49. data/lib/graphql/schema/warden.rb +5 -9
  50. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  51. data/lib/graphql/version.rb +1 -1
  52. data/spec/graphql/analysis/analyze_query_spec.rb +2 -2
  53. data/spec/graphql/analysis/max_query_complexity_spec.rb +28 -0
  54. data/spec/graphql/argument_spec.rb +3 -3
  55. data/spec/graphql/execution/lazy_spec.rb +8 -114
  56. data/spec/graphql/execution/multiplex_spec.rb +131 -0
  57. data/spec/graphql/internal_representation/rewrite_spec.rb +10 -0
  58. data/spec/graphql/query/arguments_spec.rb +14 -16
  59. data/spec/graphql/query/context_spec.rb +14 -1
  60. data/spec/graphql/query/literal_input_spec.rb +19 -13
  61. data/spec/graphql/query/variables_spec.rb +1 -1
  62. data/spec/graphql/query_spec.rb +12 -1
  63. data/spec/graphql/rake_task_spec.rb +57 -0
  64. data/spec/graphql/relay/array_connection_spec.rb +24 -3
  65. data/spec/graphql/relay/connection_instrumentation_spec.rb +23 -0
  66. data/spec/graphql/relay/mutation_spec.rb +2 -10
  67. data/spec/graphql/relay/page_info_spec.rb +2 -2
  68. data/spec/graphql/relay/relation_connection_spec.rb +167 -3
  69. data/spec/graphql/schema/build_from_definition_spec.rb +93 -19
  70. data/spec/graphql/schema/warden_spec.rb +80 -0
  71. data/spec/graphql/schema_spec.rb +26 -2
  72. data/spec/spec_helper.rb +4 -2
  73. data/spec/support/lazy_helpers.rb +152 -0
  74. data/spec/support/star_wars/schema.rb +23 -0
  75. metadata +28 -3
  76. data/lib/graphql/schema/mask.rb +0 -55
@@ -228,6 +228,21 @@ type Query {
228
228
  end
229
229
  end
230
230
 
231
+ # Use this to assert instrumenters are called as a stack
232
+ class StackCheckInstrumenter
233
+ def initialize(counter)
234
+ @counter = counter
235
+ end
236
+
237
+ def before_query(query)
238
+ @counter.counts << :in
239
+ end
240
+
241
+ def after_query(query)
242
+ @counter.counts << :out
243
+ end
244
+ end
245
+
231
246
  let(:variable_counter) {
232
247
  VariableCountInstrumenter.new
233
248
  }
@@ -246,6 +261,7 @@ type Query {
246
261
  GraphQL::Schema.define do
247
262
  query(spec.query_type)
248
263
  instrument(:field, MultiplyInstrumenter.new(3))
264
+ instrument(:query, StackCheckInstrumenter.new(spec.variable_counter))
249
265
  instrument(:query, spec.variable_counter)
250
266
  end
251
267
  }
@@ -258,7 +274,7 @@ type Query {
258
274
  it "can wrap query execution" do
259
275
  schema.execute("query getInt($val: Int = 5){ int(value: $val) } ")
260
276
  schema.execute("query getInt($val: Int = 5, $val2: Int = 3){ int(value: $val) int2: int(value: $val2) } ")
261
- assert_equal [1, :end, 2, :end], variable_counter.counts
277
+ assert_equal [:in, 1, :end, :out, :in, 2, :end, :out], variable_counter.counts
262
278
  end
263
279
 
264
280
  it "runs even when a runtime error occurs" do
@@ -266,7 +282,7 @@ type Query {
266
282
  assert_raises(RuntimeError) {
267
283
  schema.execute("query getInt($val: Int = 13){ int(value: $val) } ")
268
284
  }
269
- assert_equal [1, :end, 1, :end], variable_counter.counts
285
+ assert_equal [:in, 1, :end, :out, :in, 1, :end, :out], variable_counter.counts
270
286
  end
271
287
 
272
288
  it "can be applied after the fact" do
@@ -336,4 +352,12 @@ type Query {
336
352
  assert_equal([], errors)
337
353
  end
338
354
  end
355
+
356
+ describe "#as_json / #to_json" do
357
+ it "returns the instrospection result" do
358
+ result = schema.execute(GraphQL::Introspection::INTROSPECTION_QUERY)
359
+ assert_equal result, schema.as_json
360
+ assert_equal result, JSON.parse(schema.to_json)
361
+ end
362
+ end
339
363
  end
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
  require "codeclimate-test-reporter"
3
3
  CodeClimate::TestReporter.start
4
+ require "rake"
4
5
  require "rails/all"
5
6
  require "rails/generators"
6
7
  require "jdbc/sqlite3" if RUBY_ENGINE == 'jruby'
7
8
  require "sqlite3" if RUBY_ENGINE == 'ruby'
8
9
  require "sequel"
9
10
  require "graphql"
11
+ require "graphql/rake_task"
10
12
  require "benchmark"
11
13
  require "minitest/autorun"
12
14
  require "minitest/focus"
@@ -37,6 +39,6 @@ end
37
39
  # Load support files
38
40
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
39
41
 
40
- def star_wars_query(string, variables={})
41
- GraphQL::Query.new(StarWars::Schema, string, variables: variables).result
42
+ def star_wars_query(string, variables={}, context: {})
43
+ GraphQL::Query.new(StarWars::Schema, string, variables: variables, context: context).result
42
44
  end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+ module LazyHelpers
3
+ class Wrapper
4
+ def initialize(item = nil, &block)
5
+ if block
6
+ @block = block
7
+ else
8
+ @item = item
9
+ end
10
+ end
11
+
12
+ def item
13
+ if @block
14
+ @item = @block.call()
15
+ @block = nil
16
+ end
17
+ @item
18
+ end
19
+ end
20
+
21
+ class SumAll
22
+ attr_reader :own_value
23
+ attr_accessor :value
24
+
25
+ def initialize(ctx, own_value)
26
+ @own_value = own_value
27
+ all << self
28
+ end
29
+
30
+ def value
31
+ @value ||= begin
32
+ total_value = all.map(&:own_value).reduce(&:+)
33
+ all.each { |v| v.value = total_value}
34
+ all.clear
35
+ total_value
36
+ end
37
+ @value
38
+ end
39
+
40
+ def all
41
+ self.class.all
42
+ end
43
+
44
+ def self.all
45
+ @all ||= []
46
+ end
47
+ end
48
+
49
+ LazySum = GraphQL::ObjectType.define do
50
+ name "LazySum"
51
+ field :value, types.Int do
52
+ resolve ->(o, a, c) { o == 13 ? nil : o }
53
+ end
54
+ field :nestedSum, !LazySum do
55
+ argument :value, !types.Int
56
+ resolve ->(o, args, c) {
57
+ if args[:value] == 13
58
+ Wrapper.new(nil)
59
+ else
60
+ SumAll.new(c, o + args[:value])
61
+ end
62
+ }
63
+ end
64
+
65
+ field :nullableNestedSum, LazySum do
66
+ argument :value, types.Int
67
+ resolve ->(o, args, c) {
68
+ if args[:value] == 13
69
+ Wrapper.new(nil)
70
+ else
71
+ SumAll.new(c, o + args[:value])
72
+ end
73
+ }
74
+ end
75
+ end
76
+
77
+ LazyQuery = GraphQL::ObjectType.define do
78
+ name "Query"
79
+ field :int, !types.Int do
80
+ argument :value, !types.Int
81
+ argument :plus, types.Int, default_value: 0
82
+ resolve ->(o, a, c) { Wrapper.new(a[:value] + a[:plus])}
83
+ end
84
+
85
+ field :nestedSum, !LazySum do
86
+ argument :value, !types.Int
87
+ resolve ->(o, args, c) { SumAll.new(c, args[:value]) }
88
+ end
89
+
90
+ field :nullableNestedSum, LazySum do
91
+ argument :value, types.Int
92
+ resolve ->(o, args, c) {
93
+ if args[:value] == 13
94
+ Wrapper.new { raise GraphQL::ExecutionError.new("13 is unlucky") }
95
+ else
96
+ SumAll.new(c, args[:value])
97
+ end
98
+ }
99
+ end
100
+
101
+ field :listSum, types[LazySum] do
102
+ argument :values, types[types.Int]
103
+ resolve ->(o, args, c) { args[:values] }
104
+ end
105
+ end
106
+
107
+ class SumAllInstrumentation
108
+ def initialize(counter:)
109
+ @counter = counter
110
+ end
111
+
112
+ def before_query(q)
113
+ add_check(q, "before #{q.selected_operation.name}")
114
+ # TODO not threadsafe
115
+ # This should use multiplex-level context
116
+ SumAll.all.clear
117
+ end
118
+
119
+ def after_query(q)
120
+ add_check(q, "after #{q.selected_operation.name}")
121
+ end
122
+
123
+ def before_multiplex(multiplex)
124
+ add_check(multiplex, "before multiplex #@counter")
125
+ end
126
+
127
+ def after_multiplex(multiplex)
128
+ add_check(multiplex, "after multiplex #@counter")
129
+ end
130
+
131
+ def add_check(obj, text)
132
+ checks = obj.context[:instrumentation_checks]
133
+ if checks
134
+ checks << text
135
+ end
136
+ end
137
+ end
138
+
139
+ LazySchema = GraphQL::Schema.define do
140
+ query(LazyQuery)
141
+ mutation(LazyQuery)
142
+ lazy_resolve(Wrapper, :item)
143
+ lazy_resolve(SumAll, :value)
144
+ instrument(:query, SumAllInstrumentation.new(counter: nil))
145
+ instrument(:multiplex, SumAllInstrumentation.new(counter: 1))
146
+ instrument(:multiplex, SumAllInstrumentation.new(counter: 2))
147
+ end
148
+
149
+ def run_query(query_str)
150
+ LazySchema.execute(query_str)
151
+ end
152
+ end
@@ -309,6 +309,26 @@ module StarWars
309
309
  field :introduceShipFunction, IntroduceShipFunctionMutation.field
310
310
  end
311
311
 
312
+ class ClassNameRecorder
313
+ def initialize(context_key)
314
+ @context_key = context_key
315
+ end
316
+
317
+ def instrument(type, field)
318
+ inner_resolve = field.resolve_proc
319
+ key = @context_key
320
+ field.redefine {
321
+ resolve ->(o, a, c) {
322
+ res = inner_resolve.call(o, a, c)
323
+ if c[key]
324
+ c[key] << res.class.name
325
+ end
326
+ res
327
+ }
328
+ }
329
+ end
330
+ end
331
+
312
332
  Schema = GraphQL::Schema.define do
313
333
  query(QueryType)
314
334
  mutation(MutationType)
@@ -337,5 +357,8 @@ module StarWars
337
357
  end
338
358
 
339
359
  lazy_resolve(LazyWrapper, :value)
360
+
361
+ instrument(:field, ClassNameRecorder.new(:before_built_ins))
362
+ instrument(:field, ClassNameRecorder.new(:after_built_ins), after_built_ins: true)
340
363
  end
341
364
  end
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.15
4
+ version: 1.6.0
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-06-09 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
@@ -276,6 +276,20 @@ dependencies:
276
276
  - - ">="
277
277
  - !ruby/object:Gem::Version
278
278
  version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: yard
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
279
293
  description: A plain-Ruby implementation of GraphQL.
280
294
  email:
281
295
  - rdmosolgo@gmail.com
@@ -315,6 +329,7 @@ files:
315
329
  - lib/graphql/analysis/reducer_state.rb
316
330
  - lib/graphql/analysis_error.rb
317
331
  - lib/graphql/argument.rb
332
+ - lib/graphql/backwards_compatibility.rb
318
333
  - lib/graphql/base_type.rb
319
334
  - lib/graphql/boolean_type.rb
320
335
  - lib/graphql/compatibility.rb
@@ -350,11 +365,13 @@ files:
350
365
  - lib/graphql/execution/lazy.rb
351
366
  - lib/graphql/execution/lazy/lazy_method_map.rb
352
367
  - lib/graphql/execution/lazy/resolve.rb
368
+ - lib/graphql/execution/multiplex.rb
353
369
  - lib/graphql/execution/selection_result.rb
354
370
  - lib/graphql/execution/typecast.rb
355
371
  - lib/graphql/execution_error.rb
356
372
  - lib/graphql/field.rb
357
373
  - lib/graphql/field/resolve.rb
374
+ - lib/graphql/filter.rb
358
375
  - lib/graphql/float_type.rb
359
376
  - lib/graphql/function.rb
360
377
  - lib/graphql/id_type.rb
@@ -419,6 +436,7 @@ files:
419
436
  - lib/graphql/query/validation_pipeline.rb
420
437
  - lib/graphql/query/variable_validation_error.rb
421
438
  - lib/graphql/query/variables.rb
439
+ - lib/graphql/rake_task.rb
422
440
  - lib/graphql/relay.rb
423
441
  - lib/graphql/relay/array_connection.rb
424
442
  - lib/graphql/relay/base_connection.rb
@@ -441,13 +459,14 @@ files:
441
459
  - lib/graphql/schema.rb
442
460
  - lib/graphql/schema/base_64_encoder.rb
443
461
  - lib/graphql/schema/build_from_definition.rb
462
+ - lib/graphql/schema/build_from_definition/resolve_map.rb
463
+ - lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb
444
464
  - lib/graphql/schema/catchall_middleware.rb
445
465
  - lib/graphql/schema/default_parse_error.rb
446
466
  - lib/graphql/schema/default_type_error.rb
447
467
  - lib/graphql/schema/instrumented_field_map.rb
448
468
  - lib/graphql/schema/invalid_type_error.rb
449
469
  - lib/graphql/schema/loader.rb
450
- - lib/graphql/schema/mask.rb
451
470
  - lib/graphql/schema/middleware_chain.rb
452
471
  - lib/graphql/schema/null_mask.rb
453
472
  - lib/graphql/schema/possible_types.rb
@@ -529,6 +548,7 @@ files:
529
548
  - spec/graphql/execution/execute_spec.rb
530
549
  - spec/graphql/execution/lazy/lazy_method_map_spec.rb
531
550
  - spec/graphql/execution/lazy_spec.rb
551
+ - spec/graphql/execution/multiplex_spec.rb
532
552
  - spec/graphql/execution/typecast_spec.rb
533
553
  - spec/graphql/execution_error_spec.rb
534
554
  - spec/graphql/field_spec.rb
@@ -562,6 +582,7 @@ files:
562
582
  - spec/graphql/query/serial_execution/value_resolution_spec.rb
563
583
  - spec/graphql/query/variables_spec.rb
564
584
  - spec/graphql/query_spec.rb
585
+ - spec/graphql/rake_task_spec.rb
565
586
  - spec/graphql/relay/array_connection_spec.rb
566
587
  - spec/graphql/relay/base_connection_spec.rb
567
588
  - spec/graphql/relay/connection_instrumentation_spec.rb
@@ -618,6 +639,7 @@ files:
618
639
  - spec/support/base_generator_test.rb
619
640
  - spec/support/dummy/data.rb
620
641
  - spec/support/dummy/schema.rb
642
+ - spec/support/lazy_helpers.rb
621
643
  - spec/support/minimum_input_object.rb
622
644
  - spec/support/star_wars/data.rb
623
645
  - spec/support/star_wars/schema.rb
@@ -676,6 +698,7 @@ test_files:
676
698
  - spec/graphql/execution/execute_spec.rb
677
699
  - spec/graphql/execution/lazy/lazy_method_map_spec.rb
678
700
  - spec/graphql/execution/lazy_spec.rb
701
+ - spec/graphql/execution/multiplex_spec.rb
679
702
  - spec/graphql/execution/typecast_spec.rb
680
703
  - spec/graphql/execution_error_spec.rb
681
704
  - spec/graphql/field_spec.rb
@@ -709,6 +732,7 @@ test_files:
709
732
  - spec/graphql/query/serial_execution/value_resolution_spec.rb
710
733
  - spec/graphql/query/variables_spec.rb
711
734
  - spec/graphql/query_spec.rb
735
+ - spec/graphql/rake_task_spec.rb
712
736
  - spec/graphql/relay/array_connection_spec.rb
713
737
  - spec/graphql/relay/base_connection_spec.rb
714
738
  - spec/graphql/relay/connection_instrumentation_spec.rb
@@ -765,6 +789,7 @@ test_files:
765
789
  - spec/support/base_generator_test.rb
766
790
  - spec/support/dummy/data.rb
767
791
  - spec/support/dummy/schema.rb
792
+ - spec/support/lazy_helpers.rb
768
793
  - spec/support/minimum_input_object.rb
769
794
  - spec/support/star_wars/data.rb
770
795
  - spec/support/star_wars/schema.rb
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Schema
4
- # Tools for working with schema masks (`only` / `except`).
5
- #
6
- # In general, these are functions which, when they return `true`,
7
- # the `member` is hidden for the current query.
8
- #
9
- # @api private
10
- module Mask
11
- module_function
12
-
13
- # Combine a schema's default_mask with query-level masks.
14
- def combine(default_mask, except:, only:)
15
- query_mask = if except
16
- except
17
- elsif only
18
- InvertedMask.new(only)
19
- end
20
-
21
- if query_mask && (default_mask != GraphQL::Schema::NullMask)
22
- EitherMask.new(default_mask, query_mask)
23
- else
24
- query_mask || default_mask
25
- end
26
- end
27
-
28
- # @api private
29
- # Returns true when the inner mask returned false
30
- # Returns false when the inner mask returned true
31
- class InvertedMask
32
- def initialize(inner_mask)
33
- @inner_mask = inner_mask
34
- end
35
-
36
- def call(member, ctx)
37
- !@inner_mask.call(member, ctx)
38
- end
39
- end
40
-
41
- # Hides `member` if _either_ mask would hide the member.
42
- # @api private
43
- class EitherMask
44
- def initialize(first_mask, second_mask)
45
- @first_mask = first_mask
46
- @second_mask = second_mask
47
- end
48
-
49
- def call(member, ctx)
50
- @first_mask.call(member, ctx) || @second_mask.call(member, ctx)
51
- end
52
- end
53
- end
54
- end
55
- end