graphql 0.15.3 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +4 -1
  3. data/lib/graphql/analysis.rb +5 -0
  4. data/lib/graphql/analysis/analyze_query.rb +73 -0
  5. data/lib/graphql/analysis/max_query_complexity.rb +25 -0
  6. data/lib/graphql/analysis/max_query_depth.rb +25 -0
  7. data/lib/graphql/analysis/query_complexity.rb +122 -0
  8. data/lib/graphql/analysis/query_depth.rb +54 -0
  9. data/lib/graphql/analysis_error.rb +4 -0
  10. data/lib/graphql/base_type.rb +7 -0
  11. data/lib/graphql/define/assign_object_field.rb +2 -1
  12. data/lib/graphql/field.rb +25 -3
  13. data/lib/graphql/input_object_type.rb +1 -1
  14. data/lib/graphql/internal_representation.rb +2 -0
  15. data/lib/graphql/internal_representation/node.rb +81 -0
  16. data/lib/graphql/internal_representation/rewrite.rb +177 -0
  17. data/lib/graphql/language/visitor.rb +15 -9
  18. data/lib/graphql/object_type.rb +1 -1
  19. data/lib/graphql/query.rb +66 -7
  20. data/lib/graphql/query/context.rb +10 -3
  21. data/lib/graphql/query/directive_resolution.rb +5 -5
  22. data/lib/graphql/query/serial_execution.rb +5 -3
  23. data/lib/graphql/query/serial_execution/field_resolution.rb +22 -15
  24. data/lib/graphql/query/serial_execution/operation_resolution.rb +7 -5
  25. data/lib/graphql/query/serial_execution/selection_resolution.rb +20 -105
  26. data/lib/graphql/query/serial_execution/value_resolution.rb +15 -12
  27. data/lib/graphql/schema.rb +7 -2
  28. data/lib/graphql/schema/timeout_middleware.rb +67 -0
  29. data/lib/graphql/static_validation/all_rules.rb +0 -1
  30. data/lib/graphql/static_validation/type_stack.rb +7 -11
  31. data/lib/graphql/static_validation/validation_context.rb +11 -1
  32. data/lib/graphql/static_validation/validator.rb +14 -4
  33. data/lib/graphql/version.rb +1 -1
  34. data/readme.md +10 -9
  35. data/spec/graphql/analysis/analyze_query_spec.rb +50 -0
  36. data/spec/graphql/analysis/max_query_complexity_spec.rb +62 -0
  37. data/spec/graphql/{static_validation/rules/document_does_not_exceed_max_depth_spec.rb → analysis/max_query_depth_spec.rb} +20 -21
  38. data/spec/graphql/analysis/query_complexity_spec.rb +235 -0
  39. data/spec/graphql/analysis/query_depth_spec.rb +80 -0
  40. data/spec/graphql/directive_spec.rb +1 -0
  41. data/spec/graphql/internal_representation/rewrite_spec.rb +120 -0
  42. data/spec/graphql/introspection/schema_type_spec.rb +1 -0
  43. data/spec/graphql/language/visitor_spec.rb +14 -4
  44. data/spec/graphql/non_null_type_spec.rb +31 -0
  45. data/spec/graphql/query/context_spec.rb +24 -1
  46. data/spec/graphql/query_spec.rb +6 -2
  47. data/spec/graphql/schema/timeout_middleware_spec.rb +180 -0
  48. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -1
  49. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +1 -1
  50. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -1
  51. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +1 -1
  52. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +1 -1
  53. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -1
  54. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +1 -1
  55. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +1 -1
  56. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +1 -1
  57. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +1 -1
  58. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +1 -1
  59. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
  60. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +1 -1
  61. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +1 -1
  62. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +1 -1
  63. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +1 -1
  64. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +1 -1
  65. data/spec/graphql/static_validation/validator_spec.rb +1 -1
  66. data/spec/support/dairy_app.rb +22 -1
  67. metadata +29 -5
  68. data/lib/graphql/static_validation/rules/document_does_not_exceed_max_depth.rb +0 -79
@@ -19,7 +19,7 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
19
19
 
20
20
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::ArgumentLiteralsAreCompatible]) }
21
21
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
22
- let(:errors) { validator.validate(query) }
22
+ let(:errors) { validator.validate(query)[:errors] }
23
23
 
24
24
  it "finds undefined or missing-required arguments to fields and directives" do
25
25
  assert_equal(6, errors.length)
@@ -16,7 +16,7 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
16
16
 
17
17
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::ArgumentsAreDefined]) }
18
18
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
19
- let(:errors) { validator.validate(query) }
19
+ let(:errors) { validator.validate(query)[:errors] }
20
20
 
21
21
  it "finds undefined arguments to fields and directives" do
22
22
  assert_equal(4, errors.length)
@@ -15,7 +15,7 @@ describe GraphQL::StaticValidation::DirectivesAreDefined do
15
15
 
16
16
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::DirectivesAreDefined]) }
17
17
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
18
- let(:errors) { validator.validate(query) }
18
+ let(:errors) { validator.validate(query)[:errors] }
19
19
 
20
20
  describe "non-existent directives" do
21
21
  it "makes errors for them" do
@@ -19,7 +19,7 @@ describe GraphQL::StaticValidation::DirectivesAreInValidLocations do
19
19
 
20
20
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::DirectivesAreInValidLocations]) }
21
21
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
22
- let(:errors) { validator.validate(query) }
22
+ let(:errors) { validator.validate(query)[:errors] }
23
23
 
24
24
  describe "invalid directive locations" do
25
25
  it "makes errors for them" do
@@ -13,7 +13,7 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
13
13
 
14
14
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsAreDefinedOnType]) }
15
15
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
16
- let(:errors) { validator.validate(query) }
16
+ let(:errors) { validator.validate(query)[:errors] }
17
17
  let(:error_messages) { errors.map { |e| e["message"] } }
18
18
 
19
19
  it "finds fields that are requested on types that don't have that field" do
@@ -11,7 +11,7 @@ describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
11
11
 
12
12
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsHaveAppropriateSelections]) }
13
13
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
14
- let(:errors) { validator.validate(query) }
14
+ let(:errors) { validator.validate(query)[:errors] }
15
15
 
16
16
  it "adds errors for selections on scalars" do
17
17
  assert_equal(2, errors.length)
@@ -31,7 +31,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
31
31
 
32
32
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsWillMerge]) }
33
33
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
34
- let(:errors) { validator.validate(query) }
34
+ let(:errors) { validator.validate(query)[:errors] }
35
35
  let(:error_messages) { errors.map { |e| e["message" ] }}
36
36
 
37
37
  it "finds field naming conflicts" do
@@ -24,7 +24,7 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
24
24
 
25
25
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentSpreadsArePossible]) }
26
26
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
27
- let(:errors) { validator.validate(query) }
27
+ let(:errors) { validator.validate(query)[:errors] }
28
28
 
29
29
  it "doesnt allow spreads where they'll never apply" do
30
30
  # TODO: more negative, abstract examples here, add stuff to the schema
@@ -21,7 +21,7 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
21
21
 
22
22
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentTypesExist]) }
23
23
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
24
- let(:errors) { validator.validate(query) }
24
+ let(:errors) { validator.validate(query)[:errors] }
25
25
 
26
26
  it "finds non-existent types on fragments" do
27
27
  assert_equal(2, errors.length)
@@ -26,7 +26,7 @@ describe GraphQL::StaticValidation::FragmentsAreFinite do
26
26
 
27
27
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreFinite]) }
28
28
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
29
- let(:errors) { validator.validate(query) }
29
+ let(:errors) { validator.validate(query)[:errors] }
30
30
 
31
31
  it "doesnt allow infinite loops" do
32
32
  expected = [
@@ -27,7 +27,7 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
27
27
 
28
28
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreOnCompositeTypes]) }
29
29
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
30
- let(:errors) { validator.validate(query) }
30
+ let(:errors) { validator.validate(query)[:errors] }
31
31
 
32
32
  it "requires Object/Union/Interface fragment types" do
33
33
  expected = [
@@ -13,7 +13,7 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
13
13
 
14
14
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreUsed]) }
15
15
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
16
- let(:errors) { validator.validate(query) }
16
+ let(:errors) { validator.validate(query)[:errors] }
17
17
 
18
18
  it "adds errors for unused fragment definitions" do
19
19
  assert_includes(errors, {"message"=>"Fragment unusedFields was defined, but not used", "locations"=>[{"line"=>8, "column"=>5}]})
@@ -16,7 +16,7 @@ describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
16
16
 
17
17
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::RequiredArgumentsArePresent]) }
18
18
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
19
- let(:errors) { validator.validate(query) }
19
+ let(:errors) { validator.validate(query)[:errors] }
20
20
 
21
21
  it "finds undefined arguments to fields and directives" do
22
22
  assert_equal(3, errors.length)
@@ -18,7 +18,7 @@ describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
18
18
 
19
19
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped]) }
20
20
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
21
- let(:errors) { validator.validate(query) }
21
+ let(:errors) { validator.validate(query)[:errors] }
22
22
 
23
23
  it "finds default values that don't match their types" do
24
24
  expected = [
@@ -36,7 +36,7 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
36
36
 
37
37
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableUsagesAreAllowed]) }
38
38
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
39
- let(:errors) { validator.validate(query) }
39
+ let(:errors) { validator.validate(query)[:errors] }
40
40
 
41
41
  it "finds variables used as arguments but don't match the argument's type" do
42
42
  assert_equal(4, errors.length)
@@ -15,7 +15,7 @@ describe GraphQL::StaticValidation::VariablesAreInputTypes do
15
15
 
16
16
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreInputTypes]) }
17
17
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
18
- let(:errors) { validator.validate(query) }
18
+ let(:errors) { validator.validate(query)[:errors] }
19
19
 
20
20
  it "finds variables whose types are invalid" do
21
21
  expected = [
@@ -31,7 +31,7 @@ describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
31
31
 
32
32
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreUsedAndDefined]) }
33
33
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
34
- let(:errors) { validator.validate(query) }
34
+ let(:errors) { validator.validate(query)[:errors] }
35
35
 
36
36
  it "finds variables which are used-but-not-defined or defined-but-not-used" do
37
37
  expected = [
@@ -3,7 +3,7 @@ require "spec_helper"
3
3
  describe GraphQL::StaticValidation::Validator do
4
4
  let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema) }
5
5
  let(:query) { GraphQL::Query.new(DummySchema, query_string) }
6
- let(:errors) { validator.validate(query) }
6
+ let(:errors) { validator.validate(query)[:errors] }
7
7
 
8
8
 
9
9
  describe "validation order" do
@@ -83,11 +83,17 @@ MilkType = GraphQL::ObjectType.define do
83
83
  end
84
84
  end
85
85
 
86
+ SweetenerInterface = GraphQL::InterfaceType.define do
87
+ name "Sweetener"
88
+ field :sweetness, types.Int
89
+ end
90
+
86
91
  # No actual data; This type is an "orphan", only accessible through Interfaces
87
92
  HoneyType = GraphQL::ObjectType.define do
88
93
  name "Honey"
89
94
  description "Sweet, dehydrated bee barf"
90
- interfaces [EdibleInterface, AnimalProductInterface]
95
+ field :flowerType, types.String, "What flower this honey came from"
96
+ interfaces [EdibleInterface, AnimalProductInterface, SweetenerInterface]
91
97
  end
92
98
 
93
99
  DairyType = GraphQL::ObjectType.define do
@@ -150,6 +156,17 @@ DairyProductInputType = GraphQL::InputObjectType.define {
150
156
  input_field :organic, types.Boolean, default_value: false
151
157
  }
152
158
 
159
+ DeepNonNullType = GraphQL::ObjectType.define do
160
+ name "DeepNonNull"
161
+ field :nonNullInt, !types.Int do
162
+ argument :returning, types.Int
163
+ resolve -> (obj, args, ctx) { args[:returning] }
164
+ end
165
+
166
+ field :deepNonNull, -> { DeepNonNullType.to_non_null_type } do
167
+ resolve -> (obj, args, ctx) { :deepNonNull }
168
+ end
169
+ end
153
170
 
154
171
  class FetchField
155
172
  def self.create(type:, data:, id_type: !GraphQL::INT_TYPE)
@@ -239,6 +256,10 @@ QueryType = GraphQL::ObjectType.define do
239
256
  field :maybeNull, MaybeNullType do
240
257
  resolve -> (t, a, c) { OpenStruct.new(cheese: nil) }
241
258
  end
259
+
260
+ field :deepNonNull, !DeepNonNullType do
261
+ resolve -> (o, a, c) { :deepNonNull }
262
+ end
242
263
  end
243
264
 
244
265
  GLOBAL_VALUES = []
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: 0.15.3
4
+ version: 0.16.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: 2016-06-28 00:00:00.000000000 Z
11
+ date: 2016-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: codeclimate-test-reporter
@@ -188,6 +188,13 @@ extra_rdoc_files: []
188
188
  files:
189
189
  - MIT-LICENSE
190
190
  - lib/graphql.rb
191
+ - lib/graphql/analysis.rb
192
+ - lib/graphql/analysis/analyze_query.rb
193
+ - lib/graphql/analysis/max_query_complexity.rb
194
+ - lib/graphql/analysis/max_query_depth.rb
195
+ - lib/graphql/analysis/query_complexity.rb
196
+ - lib/graphql/analysis/query_depth.rb
197
+ - lib/graphql/analysis_error.rb
191
198
  - lib/graphql/argument.rb
192
199
  - lib/graphql/base_type.rb
193
200
  - lib/graphql/boolean_type.rb
@@ -211,6 +218,9 @@ files:
211
218
  - lib/graphql/input_object_type.rb
212
219
  - lib/graphql/int_type.rb
213
220
  - lib/graphql/interface_type.rb
221
+ - lib/graphql/internal_representation.rb
222
+ - lib/graphql/internal_representation/node.rb
223
+ - lib/graphql/internal_representation/rewrite.rb
214
224
  - lib/graphql/introspection.rb
215
225
  - lib/graphql/introspection/arguments_field.rb
216
226
  - lib/graphql/introspection/directive_location_enum.rb
@@ -269,6 +279,7 @@ files:
269
279
  - lib/graphql/schema/printer.rb
270
280
  - lib/graphql/schema/reduce_types.rb
271
281
  - lib/graphql/schema/rescue_middleware.rb
282
+ - lib/graphql/schema/timeout_middleware.rb
272
283
  - lib/graphql/schema/type_expression.rb
273
284
  - lib/graphql/schema/type_map.rb
274
285
  - lib/graphql/schema/validation.rb
@@ -281,7 +292,6 @@ files:
281
292
  - lib/graphql/static_validation/rules/arguments_are_defined.rb
282
293
  - lib/graphql/static_validation/rules/directives_are_defined.rb
283
294
  - lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb
284
- - lib/graphql/static_validation/rules/document_does_not_exceed_max_depth.rb
285
295
  - lib/graphql/static_validation/rules/fields_are_defined_on_type.rb
286
296
  - lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb
287
297
  - lib/graphql/static_validation/rules/fields_will_merge.rb
@@ -303,6 +313,11 @@ files:
303
313
  - lib/graphql/union_type.rb
304
314
  - lib/graphql/version.rb
305
315
  - readme.md
316
+ - spec/graphql/analysis/analyze_query_spec.rb
317
+ - spec/graphql/analysis/max_query_complexity_spec.rb
318
+ - spec/graphql/analysis/max_query_depth_spec.rb
319
+ - spec/graphql/analysis/query_complexity_spec.rb
320
+ - spec/graphql/analysis/query_depth_spec.rb
306
321
  - spec/graphql/argument_spec.rb
307
322
  - spec/graphql/base_type_spec.rb
308
323
  - spec/graphql/boolean_type_spec.rb
@@ -316,6 +331,7 @@ files:
316
331
  - spec/graphql/input_object_type_spec.rb
317
332
  - spec/graphql/int_type_spec.rb
318
333
  - spec/graphql/interface_type_spec.rb
334
+ - spec/graphql/internal_representation/rewrite_spec.rb
319
335
  - spec/graphql/introspection/directive_type_spec.rb
320
336
  - spec/graphql/introspection/input_value_type_spec.rb
321
337
  - spec/graphql/introspection/introspection_query_spec.rb
@@ -325,6 +341,7 @@ files:
325
341
  - spec/graphql/language/parser_spec.rb
326
342
  - spec/graphql/language/visitor_spec.rb
327
343
  - spec/graphql/list_type_spec.rb
344
+ - spec/graphql/non_null_type_spec.rb
328
345
  - spec/graphql/object_type_spec.rb
329
346
  - spec/graphql/query/arguments_spec.rb
330
347
  - spec/graphql/query/context_spec.rb
@@ -340,6 +357,7 @@ files:
340
357
  - spec/graphql/schema/printer_spec.rb
341
358
  - spec/graphql/schema/reduce_types_spec.rb
342
359
  - spec/graphql/schema/rescue_middleware_spec.rb
360
+ - spec/graphql/schema/timeout_middleware_spec.rb
343
361
  - spec/graphql/schema/type_expression_spec.rb
344
362
  - spec/graphql/schema/validation_spec.rb
345
363
  - spec/graphql/schema_spec.rb
@@ -347,7 +365,6 @@ files:
347
365
  - spec/graphql/static_validation/rules/arguments_are_defined_spec.rb
348
366
  - spec/graphql/static_validation/rules/directives_are_defined_spec.rb
349
367
  - spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb
350
- - spec/graphql/static_validation/rules/document_does_not_exceed_max_depth_spec.rb
351
368
  - spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb
352
369
  - spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb
353
370
  - spec/graphql/static_validation/rules/fields_will_merge_spec.rb
@@ -396,6 +413,11 @@ signing_key:
396
413
  specification_version: 4
397
414
  summary: A GraphQL server implementation for Ruby
398
415
  test_files:
416
+ - spec/graphql/analysis/analyze_query_spec.rb
417
+ - spec/graphql/analysis/max_query_complexity_spec.rb
418
+ - spec/graphql/analysis/max_query_depth_spec.rb
419
+ - spec/graphql/analysis/query_complexity_spec.rb
420
+ - spec/graphql/analysis/query_depth_spec.rb
399
421
  - spec/graphql/argument_spec.rb
400
422
  - spec/graphql/base_type_spec.rb
401
423
  - spec/graphql/boolean_type_spec.rb
@@ -409,6 +431,7 @@ test_files:
409
431
  - spec/graphql/input_object_type_spec.rb
410
432
  - spec/graphql/int_type_spec.rb
411
433
  - spec/graphql/interface_type_spec.rb
434
+ - spec/graphql/internal_representation/rewrite_spec.rb
412
435
  - spec/graphql/introspection/directive_type_spec.rb
413
436
  - spec/graphql/introspection/input_value_type_spec.rb
414
437
  - spec/graphql/introspection/introspection_query_spec.rb
@@ -418,6 +441,7 @@ test_files:
418
441
  - spec/graphql/language/parser_spec.rb
419
442
  - spec/graphql/language/visitor_spec.rb
420
443
  - spec/graphql/list_type_spec.rb
444
+ - spec/graphql/non_null_type_spec.rb
421
445
  - spec/graphql/object_type_spec.rb
422
446
  - spec/graphql/query/arguments_spec.rb
423
447
  - spec/graphql/query/context_spec.rb
@@ -433,6 +457,7 @@ test_files:
433
457
  - spec/graphql/schema/printer_spec.rb
434
458
  - spec/graphql/schema/reduce_types_spec.rb
435
459
  - spec/graphql/schema/rescue_middleware_spec.rb
460
+ - spec/graphql/schema/timeout_middleware_spec.rb
436
461
  - spec/graphql/schema/type_expression_spec.rb
437
462
  - spec/graphql/schema/validation_spec.rb
438
463
  - spec/graphql/schema_spec.rb
@@ -440,7 +465,6 @@ test_files:
440
465
  - spec/graphql/static_validation/rules/arguments_are_defined_spec.rb
441
466
  - spec/graphql/static_validation/rules/directives_are_defined_spec.rb
442
467
  - spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb
443
- - spec/graphql/static_validation/rules/document_does_not_exceed_max_depth_spec.rb
444
468
  - spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb
445
469
  - spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb
446
470
  - spec/graphql/static_validation/rules/fields_will_merge_spec.rb
@@ -1,79 +0,0 @@
1
- module GraphQL
2
- module StaticValidation
3
- class DocumentDoesNotExceedMaxDepth
4
- include GraphQL::StaticValidation::Message::MessageHelper
5
-
6
- def validate(context)
7
- max_allowed_depth = context.query.max_depth
8
- return if max_allowed_depth.nil?
9
-
10
- visitor = context.visitor
11
-
12
- # operation or fragment name
13
- current_field_scope = nil
14
- current_depth = 0
15
- skip_current_scope = false
16
-
17
- # {name => depth} pairs for operations and fragments
18
- depths = Hash.new { |h, k| h[k] = 0 }
19
-
20
- # {name => [fragmentName...]} pairs
21
- fragments = Hash.new { |h, k| h[k] = []}
22
-
23
- visitor[GraphQL::Language::Nodes::Document].leave << -> (node, parent) {
24
- context.errors.none? && assert_under_max_depth(context, max_allowed_depth, depths, fragments)
25
- }
26
-
27
- visitor[GraphQL::Language::Nodes::OperationDefinition] << -> (node, parent) {
28
- current_field_scope = node.name
29
- }
30
-
31
- visitor[GraphQL::Language::Nodes::FragmentDefinition] << -> (node, parent) {
32
- current_field_scope = node.name
33
- }
34
-
35
- visitor[GraphQL::Language::Nodes::Field] << -> (node, parent) {
36
- # Don't validate queries on __schema, __type
37
- skip_current_scope ||= context.skip_field?(node.name)
38
-
39
- if node.selections.any? && !skip_current_scope
40
- current_depth += 1
41
- if current_depth > depths[current_field_scope]
42
- depths[current_field_scope] = current_depth
43
- end
44
- end
45
- }
46
-
47
- visitor[GraphQL::Language::Nodes::Field].leave << -> (node, parent) {
48
- if skip_current_scope && context.skip_field?(node.name)
49
- skip_current_scope = false
50
- elsif node.selections.any?
51
- current_depth -= 1
52
- end
53
- }
54
-
55
- visitor [GraphQL::Language::Nodes::FragmentSpread] << -> (node, parent) {
56
- fragments[current_field_scope] << node.name
57
- }
58
- end
59
-
60
- private
61
-
62
- def assert_under_max_depth(context, max_allowed_depth, depths, fragments)
63
- context.operations.each do |op_name, operation|
64
- op_depth = get_total_depth(op_name, depths, fragments)
65
- if op_depth > max_allowed_depth
66
- op_name ||= "operation"
67
- context.errors << message("#{op_name} has depth of #{op_depth}, which exceeds max depth of #{max_allowed_depth}", operation)
68
- end
69
- end
70
- end
71
-
72
- # Get the total depth of a given fragment or operation
73
- def get_total_depth(scope_name, depths, fragments)
74
- own_fragments = fragments[scope_name]
75
- depths[scope_name] + own_fragments.reduce(0) { |memo, frag_name| memo + get_total_depth(frag_name, depths, fragments) }
76
- end
77
- end
78
- end
79
- end