graphql 0.15.3 → 0.16.0

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