graphql 1.9.0.pre1 → 1.9.0.pre2

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 (235) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +5 -1
  3. data/lib/graphql/analysis/ast/analyzer.rb +1 -1
  4. data/lib/graphql/analysis/ast/visitor.rb +6 -1
  5. data/lib/graphql/backwards_compatibility.rb +1 -1
  6. data/lib/graphql/dig.rb +19 -0
  7. data/lib/graphql/directive.rb +13 -1
  8. data/lib/graphql/directive/include_directive.rb +1 -7
  9. data/lib/graphql/directive/skip_directive.rb +1 -8
  10. data/lib/graphql/execution/interpreter.rb +23 -13
  11. data/lib/graphql/execution/interpreter/resolve.rb +56 -0
  12. data/lib/graphql/execution/interpreter/runtime.rb +174 -74
  13. data/lib/graphql/execution/lazy.rb +7 -1
  14. data/lib/graphql/execution/lookahead.rb +71 -6
  15. data/lib/graphql/execution_error.rb +1 -1
  16. data/lib/graphql/introspection/entry_points.rb +5 -1
  17. data/lib/graphql/introspection/type_type.rb +4 -4
  18. data/lib/graphql/language.rb +0 -1
  19. data/lib/graphql/language/block_string.rb +37 -0
  20. data/lib/graphql/language/document_from_schema_definition.rb +1 -1
  21. data/lib/graphql/language/lexer.rb +55 -36
  22. data/lib/graphql/language/lexer.rl +8 -3
  23. data/lib/graphql/language/nodes.rb +27 -4
  24. data/lib/graphql/language/parser.rb +55 -55
  25. data/lib/graphql/language/parser.y +11 -11
  26. data/lib/graphql/language/printer.rb +1 -1
  27. data/lib/graphql/language/visitor.rb +22 -13
  28. data/lib/graphql/literal_validation_error.rb +6 -0
  29. data/lib/graphql/query.rb +13 -0
  30. data/lib/graphql/query/arguments.rb +2 -1
  31. data/lib/graphql/query/context.rb +3 -10
  32. data/lib/graphql/query/executor.rb +1 -1
  33. data/lib/graphql/query/validation_pipeline.rb +1 -1
  34. data/lib/graphql/relay/connection_resolve.rb +1 -1
  35. data/lib/graphql/relay/relation_connection.rb +1 -1
  36. data/lib/graphql/schema.rb +81 -11
  37. data/lib/graphql/schema/argument.rb +1 -1
  38. data/lib/graphql/schema/build_from_definition.rb +2 -4
  39. data/lib/graphql/schema/directive.rb +103 -0
  40. data/lib/graphql/schema/directive/feature.rb +66 -0
  41. data/lib/graphql/schema/directive/include.rb +25 -0
  42. data/lib/graphql/schema/directive/skip.rb +25 -0
  43. data/lib/graphql/schema/directive/transform.rb +48 -0
  44. data/lib/graphql/schema/enum_value.rb +2 -2
  45. data/lib/graphql/schema/field.rb +63 -17
  46. data/lib/graphql/schema/input_object.rb +1 -0
  47. data/lib/graphql/schema/member/base_dsl_methods.rb +4 -2
  48. data/lib/graphql/schema/member/build_type.rb +33 -1
  49. data/lib/graphql/schema/member/has_fields.rb +8 -73
  50. data/lib/graphql/schema/relay_classic_mutation.rb +6 -1
  51. data/lib/graphql/schema/resolver.rb +1 -1
  52. data/lib/graphql/static_validation.rb +2 -1
  53. data/lib/graphql/static_validation/all_rules.rb +1 -0
  54. data/lib/graphql/static_validation/base_visitor.rb +25 -10
  55. data/lib/graphql/static_validation/definition_dependencies.rb +3 -3
  56. data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
  57. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  58. data/lib/graphql/static_validation/literal_validator.rb +54 -11
  59. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +34 -5
  60. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
  61. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +2 -2
  62. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  63. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +7 -1
  64. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
  65. data/lib/graphql/static_validation/rules/directives_are_defined.rb +5 -1
  66. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  67. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +11 -2
  68. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  69. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +11 -2
  70. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  71. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +14 -2
  72. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  73. data/lib/graphql/static_validation/rules/fields_will_merge.rb +24 -6
  74. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
  75. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +5 -1
  76. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  77. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -1
  78. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  79. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +5 -1
  80. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  81. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +6 -1
  82. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  83. data/lib/graphql/static_validation/rules/fragments_are_named.rb +4 -1
  84. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  85. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +5 -1
  86. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  87. data/lib/graphql/static_validation/rules/fragments_are_used.rb +13 -3
  88. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  89. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +4 -1
  90. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  91. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +2 -2
  92. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  93. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +9 -2
  94. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  95. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +7 -1
  96. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  97. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
  98. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  99. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +4 -1
  100. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  101. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +4 -3
  102. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  103. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +20 -6
  104. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  105. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +5 -1
  106. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  107. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +8 -1
  108. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  109. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +12 -2
  110. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  111. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +18 -2
  112. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  113. data/lib/graphql/static_validation/validator.rb +24 -14
  114. data/lib/graphql/tracing/new_relic_tracing.rb +2 -2
  115. data/lib/graphql/tracing/skylight_tracing.rb +2 -2
  116. data/lib/graphql/unauthorized_field_error.rb +23 -0
  117. data/lib/graphql/version.rb +1 -1
  118. data/spec/graphql/analysis/ast_spec.rb +40 -0
  119. data/spec/graphql/authorization_spec.rb +93 -20
  120. data/spec/graphql/base_type_spec.rb +3 -1
  121. data/spec/graphql/execution/interpreter_spec.rb +127 -4
  122. data/spec/graphql/execution/lazy_spec.rb +49 -0
  123. data/spec/graphql/execution/lookahead_spec.rb +113 -21
  124. data/spec/graphql/execution/multiplex_spec.rb +2 -1
  125. data/spec/graphql/introspection/type_type_spec.rb +1 -1
  126. data/spec/graphql/language/lexer_spec.rb +72 -3
  127. data/spec/graphql/language/printer_spec.rb +18 -6
  128. data/spec/graphql/query/arguments_spec.rb +21 -0
  129. data/spec/graphql/query/context_spec.rb +10 -0
  130. data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
  131. data/spec/graphql/schema/directive/feature_spec.rb +81 -0
  132. data/spec/graphql/schema/directive/transform_spec.rb +39 -0
  133. data/spec/graphql/schema/enum_spec.rb +5 -3
  134. data/spec/graphql/schema/field_extension_spec.rb +3 -3
  135. data/spec/graphql/schema/field_spec.rb +19 -0
  136. data/spec/graphql/schema/input_object_spec.rb +81 -0
  137. data/spec/graphql/schema/member/build_type_spec.rb +46 -0
  138. data/spec/graphql/schema/member/scoped_spec.rb +3 -3
  139. data/spec/graphql/schema/printer_spec.rb +244 -96
  140. data/spec/graphql/schema/relay_classic_mutation_spec.rb +26 -0
  141. data/spec/graphql/schema/resolver_spec.rb +1 -1
  142. data/spec/graphql/schema/warden_spec.rb +35 -11
  143. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +212 -72
  144. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
  145. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
  146. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
  147. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
  148. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
  149. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
  150. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -1
  151. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
  152. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
  153. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
  154. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
  155. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
  156. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
  157. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
  158. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
  159. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
  160. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
  161. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
  162. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
  163. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
  164. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
  165. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
  166. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
  167. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +6 -3
  168. data/spec/graphql/static_validation/validator_spec.rb +6 -4
  169. data/spec/graphql/tracing/new_relic_tracing_spec.rb +10 -0
  170. data/spec/graphql/tracing/skylight_tracing_spec.rb +10 -0
  171. data/spec/graphql/types/iso_8601_date_time_spec.rb +1 -2
  172. data/spec/integration/mongoid/star_trek/schema.rb +5 -5
  173. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +37 -8
  174. data/spec/integration/rails/graphql/schema_spec.rb +2 -2
  175. data/spec/integration/rails/spec_helper.rb +10 -0
  176. data/spec/integration/tmp/app/graphql/types/bird_type.rb +7 -0
  177. data/spec/integration/tmp/dummy/Gemfile +45 -0
  178. data/spec/integration/tmp/dummy/README.rdoc +28 -0
  179. data/spec/integration/tmp/dummy/Rakefile +6 -0
  180. data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +16 -0
  181. data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +15 -0
  182. data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +5 -0
  183. data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +43 -0
  184. data/spec/integration/tmp/dummy/app/graphql/dummy_schema.rb +34 -0
  185. data/spec/integration/tmp/dummy/app/graphql/types/base_enum.rb +4 -0
  186. data/spec/integration/tmp/dummy/app/graphql/types/base_input_object.rb +4 -0
  187. data/spec/integration/tmp/dummy/app/graphql/types/base_interface.rb +5 -0
  188. data/spec/integration/tmp/dummy/app/graphql/types/base_object.rb +4 -0
  189. data/spec/integration/tmp/dummy/app/graphql/types/base_scalar.rb +4 -0
  190. data/spec/integration/tmp/dummy/app/graphql/types/base_union.rb +4 -0
  191. data/spec/integration/tmp/dummy/app/graphql/types/mutation_type.rb +10 -0
  192. data/spec/integration/tmp/dummy/app/graphql/types/query_type.rb +15 -0
  193. data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +2 -0
  194. data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +14 -0
  195. data/spec/integration/tmp/dummy/bin/bundle +3 -0
  196. data/spec/integration/tmp/dummy/bin/rails +4 -0
  197. data/spec/integration/tmp/dummy/bin/rake +4 -0
  198. data/spec/integration/tmp/dummy/bin/setup +29 -0
  199. data/spec/integration/tmp/dummy/config.ru +4 -0
  200. data/spec/integration/tmp/dummy/config/application.rb +32 -0
  201. data/spec/integration/tmp/dummy/config/boot.rb +3 -0
  202. data/spec/integration/tmp/dummy/config/environment.rb +5 -0
  203. data/spec/integration/tmp/dummy/config/environments/development.rb +38 -0
  204. data/spec/integration/tmp/dummy/config/environments/production.rb +76 -0
  205. data/spec/integration/tmp/dummy/config/environments/test.rb +42 -0
  206. data/spec/integration/tmp/dummy/config/initializers/assets.rb +11 -0
  207. data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +7 -0
  208. data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +3 -0
  209. data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  210. data/spec/integration/tmp/dummy/config/initializers/inflections.rb +16 -0
  211. data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +4 -0
  212. data/spec/integration/tmp/dummy/config/initializers/session_store.rb +3 -0
  213. data/spec/integration/tmp/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  214. data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +9 -0
  215. data/spec/integration/tmp/dummy/config/locales/en.yml +23 -0
  216. data/spec/integration/tmp/dummy/config/routes.rb +61 -0
  217. data/spec/integration/tmp/dummy/config/secrets.yml +22 -0
  218. data/spec/integration/tmp/dummy/db/seeds.rb +7 -0
  219. data/spec/integration/tmp/dummy/public/404.html +67 -0
  220. data/spec/integration/tmp/dummy/public/422.html +67 -0
  221. data/spec/integration/tmp/dummy/public/500.html +66 -0
  222. data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
  223. data/spec/integration/tmp/dummy/public/robots.txt +5 -0
  224. data/spec/support/dummy/schema.rb +2 -2
  225. data/spec/support/error_bubbling_helpers.rb +23 -0
  226. data/spec/support/jazz.rb +53 -6
  227. data/spec/support/lazy_helpers.rb +26 -8
  228. data/spec/support/new_relic.rb +3 -0
  229. data/spec/support/skylight.rb +3 -0
  230. data/spec/support/star_wars/schema.rb +13 -9
  231. data/spec/support/static_validation_helpers.rb +3 -1
  232. metadata +145 -22
  233. data/lib/graphql/language/comments.rb +0 -45
  234. data/spec/graphql/schema/member/has_fields_spec.rb +0 -132
  235. data/spec/integration/tmp/app/graphql/types/family_type.rb +0 -9
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentTypesExistError < StaticValidation::Error
5
+ attr_reader :type_name
6
+
7
+ def initialize(message, path: nil, nodes: [], type:)
8
+ super(message, path: path, nodes: nodes)
9
+ @type_name = type
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "typeName" => type_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "undefinedType"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -7,7 +7,12 @@ module GraphQL
7
7
  dependency_map = context.dependencies
8
8
  dependency_map.cyclical_definitions.each do |defn|
9
9
  if defn.node.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
10
- context.errors << message("Fragment #{defn.name} contains an infinite loop", defn.node, path: defn.path)
10
+ context.errors << GraphQL::StaticValidation::FragmentsAreFiniteError.new(
11
+ "Fragment #{defn.name} contains an infinite loop",
12
+ nodes: defn.node,
13
+ path: defn.path,
14
+ name: defn.name
15
+ )
11
16
  end
12
17
  end
13
18
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreFiniteError < StaticValidation::Error
5
+ attr_reader :fragment_name
6
+
7
+ def initialize(message, path: nil, nodes: [], name:)
8
+ super(message, path: path, nodes: nodes)
9
+ @fragment_name = name
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "fragmentName" => fragment_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "infiniteLoop"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -4,7 +4,10 @@ module GraphQL
4
4
  module FragmentsAreNamed
5
5
  def on_fragment_definition(node, _parent)
6
6
  if node.name.nil?
7
- add_error("Fragment definition has no name", node)
7
+ add_error(GraphQL::StaticValidation::FragmentsAreNamedError.new(
8
+ "Fragment definition has no name",
9
+ nodes: node
10
+ ))
8
11
  end
9
12
  super
10
13
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreNamedError < StaticValidation::Error
5
+
6
+ def initialize(message, path: nil, nodes: [])
7
+ super(message, path: path, nodes: nodes)
8
+ end
9
+
10
+ # A hash representation of this Message
11
+ def to_h
12
+ extensions = {
13
+ "code" => code,
14
+ }
15
+
16
+ super.merge({
17
+ "extensions" => extensions
18
+ })
19
+ end
20
+
21
+ def code
22
+ "anonymousFragment"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -21,7 +21,11 @@ module GraphQL
21
21
  type_name = node_type.to_query_string
22
22
  type_def = context.warden.get_type(type_name)
23
23
  if type_def.nil? || !type_def.kind.composite?
24
- add_error("Invalid fragment on type #{type_name} (must be Union, Interface or Object)", node)
24
+ add_error(GraphQL::StaticValidation::FragmentsAreOnCompositeTypesError.new(
25
+ "Invalid fragment on type #{type_name} (must be Union, Interface or Object)",
26
+ nodes: node,
27
+ type: type_name
28
+ ))
25
29
  false
26
30
  else
27
31
  true
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreOnCompositeTypesError < StaticValidation::Error
5
+ attr_reader :type_name
6
+ attr_reader :argument_name
7
+
8
+ def initialize(message, path: nil, nodes: [], type:)
9
+ super(message, path: path, nodes: nodes)
10
+ @type_name = type
11
+ end
12
+
13
+ # A hash representation of this Message
14
+ def to_h
15
+ extensions = {
16
+ "code" => code,
17
+ "typeName" => type_name
18
+ }
19
+
20
+ super.merge({
21
+ "extensions" => extensions
22
+ })
23
+ end
24
+
25
+ def code
26
+ "fragmentOnNonCompositeType"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -7,13 +7,23 @@ module GraphQL
7
7
  dependency_map = context.dependencies
8
8
  dependency_map.unmet_dependencies.each do |op_defn, spreads|
9
9
  spreads.each do |fragment_spread|
10
- add_error("Fragment #{fragment_spread.name} was used, but not defined", fragment_spread.node, path: fragment_spread.path)
10
+ add_error(GraphQL::StaticValidation::FragmentsAreUsedError.new(
11
+ "Fragment #{fragment_spread.name} was used, but not defined",
12
+ nodes: fragment_spread.node,
13
+ path: fragment_spread.path,
14
+ fragment: fragment_spread.name
15
+ ))
11
16
  end
12
17
  end
13
18
 
14
19
  dependency_map.unused_dependencies.each do |fragment|
15
- if !fragment.name.nil?
16
- add_error("Fragment #{fragment.name} was defined, but not used", fragment.node, path: fragment.path)
20
+ if fragment && !fragment.name.nil?
21
+ add_error(GraphQL::StaticValidation::FragmentsAreUsedError.new(
22
+ "Fragment #{fragment.name} was defined, but not used",
23
+ nodes: fragment.node,
24
+ path: fragment.path,
25
+ fragment: fragment.name
26
+ ))
17
27
  end
18
28
  end
19
29
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentsAreUsedError < StaticValidation::Error
5
+ attr_reader :fragment_name
6
+
7
+ def initialize(message, path: nil, nodes: [], fragment:)
8
+ super(message, path: path, nodes: nodes)
9
+ @fragment_name = fragment
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "fragmentName" => fragment_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "useAndDefineFragment"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -4,7 +4,10 @@ module GraphQL
4
4
  module MutationRootExists
5
5
  def on_operation_definition(node, _parent)
6
6
  if node.operation_type == 'mutation' && context.warden.root_type_for_operation("mutation").nil?
7
- add_error('Schema is not configured for mutations', node)
7
+ add_error(GraphQL::StaticValidation::MutationRootExistsError.new(
8
+ 'Schema is not configured for mutations',
9
+ nodes: node
10
+ ))
8
11
  else
9
12
  super
10
13
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class MutationRootExistsError < StaticValidation::Error
5
+
6
+ def initialize(message, path: nil, nodes: [])
7
+ super(message, path: path, nodes: nodes)
8
+ end
9
+
10
+ # A hash representation of this Message
11
+ def to_h
12
+ extensions = {
13
+ "code" => code,
14
+ }
15
+
16
+ super.merge({
17
+ "extensions" => extensions
18
+ })
19
+ end
20
+
21
+ def code
22
+ "missingMutationConfiguration"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,7 +2,7 @@
2
2
  module GraphQL
3
3
  module StaticValidation
4
4
  module NoDefinitionsArePresent
5
- include GraphQL::StaticValidation::Message::MessageHelper
5
+ include GraphQL::StaticValidation::Error::ErrorHelper
6
6
 
7
7
  def initialize(*)
8
8
  super
@@ -33,7 +33,7 @@ module GraphQL
33
33
  def on_document(node, parent)
34
34
  super
35
35
  if @schema_definition_nodes.any?
36
- add_error(%|Query cannot contain schema definitions|, @schema_definition_nodes)
36
+ add_error(GraphQL::StaticValidation::NoDefinitionsArePresentError.new(%|Query cannot contain schema definitions|, nodes: @schema_definition_nodes))
37
37
  end
38
38
  end
39
39
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class NoDefinitionsArePresentError < StaticValidation::Error
5
+ def initialize(message, path: nil, nodes: [])
6
+ super(message, path: path, nodes: nodes)
7
+ end
8
+
9
+ # A hash representation of this Message
10
+ def to_h
11
+ extensions = {
12
+ "code" => code,
13
+ }
14
+
15
+ super.merge({
16
+ "extensions" => extensions
17
+ })
18
+ end
19
+
20
+ def code
21
+ "queryContainsSchemaDefinitions"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -18,9 +18,16 @@ module GraphQL
18
18
 
19
19
  @operation_names.each do |name, nodes|
20
20
  if name.nil? && op_count > 1
21
- add_error(%|Operation name is required when multiple operations are present|, nodes)
21
+ add_error(GraphQL::StaticValidation::OperationNamesAreValidError.new(
22
+ %|Operation name is required when multiple operations are present|,
23
+ nodes: nodes
24
+ ))
22
25
  elsif nodes.length > 1
23
- add_error(%|Operation name "#{name}" must be unique|, nodes)
26
+ add_error(GraphQL::StaticValidation::OperationNamesAreValidError.new(
27
+ %|Operation name "#{name}" must be unique|,
28
+ nodes: nodes,
29
+ name: name
30
+ ))
24
31
  end
25
32
  end
26
33
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class OperationNamesAreValidError < StaticValidation::Error
5
+ attr_reader :operation_name
6
+
7
+ def initialize(message, path: nil, nodes: [], name: nil)
8
+ super(message, path: path, nodes: nodes)
9
+ @operation_name = name
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code
16
+ }.tap { |h| h["operationName"] = operation_name unless operation_name.nil? }
17
+
18
+ super.merge({
19
+ "extensions" => extensions
20
+ })
21
+ end
22
+
23
+ def code
24
+ "uniquelyNamedOperations"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -23,7 +23,13 @@ module GraphQL
23
23
 
24
24
  missing_names = required_argument_names - present_argument_names
25
25
  if missing_names.any?
26
- add_error("#{ast_node.class.name.split("::").last} '#{ast_node.name}' is missing required arguments: #{missing_names.join(", ")}", ast_node)
26
+ add_error(GraphQL::StaticValidation::RequiredArgumentsArePresentError.new(
27
+ "#{ast_node.class.name.split("::").last} '#{ast_node.name}' is missing required arguments: #{missing_names.join(", ")}",
28
+ nodes: ast_node,
29
+ class_name: ast_node.class.name.split("::").last,
30
+ name: ast_node.name,
31
+ arguments: "#{missing_names.join(", ")}"
32
+ ))
27
33
  end
28
34
  end
29
35
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class RequiredArgumentsArePresentError < StaticValidation::Error
5
+ attr_reader :class_name
6
+ attr_reader :name
7
+ attr_reader :arguments
8
+
9
+ def initialize(message, path: nil, nodes: [], class_name:, name:, arguments:)
10
+ super(message, path: path, nodes: nodes)
11
+ @class_name = class_name
12
+ @name = name
13
+ @arguments = arguments
14
+ end
15
+
16
+ # A hash representation of this Message
17
+ def to_h
18
+ extensions = {
19
+ "code" => code,
20
+ "className" => class_name,
21
+ "name" => name,
22
+ "arguments" => arguments
23
+ }
24
+
25
+ super.merge({
26
+ "extensions" => extensions
27
+ })
28
+ end
29
+
30
+ def code
31
+ "missingRequiredArguments"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ module RequiredInputObjectAttributesArePresent
5
+ def on_input_object(node, parent)
6
+ if parent.is_a? GraphQL::Language::Nodes::Argument
7
+ validate_input_object(node, context, parent)
8
+ end
9
+ super
10
+ end
11
+
12
+ private
13
+
14
+ def get_parent_type(context, parent)
15
+ defn = context.field_definition
16
+ parent_type = context.warden.arguments(defn)
17
+ .find{|f| f.name == parent_name(parent, defn) }
18
+ parent_type ? parent_type.type.unwrap : nil
19
+ end
20
+
21
+ def validate_input_object(ast_node, context, parent)
22
+ parent_type = get_parent_type(context, parent)
23
+ return unless parent_type && parent_type.kind.input_object?
24
+
25
+ required_fields = parent_type.arguments
26
+ .select{|k,v| v.type.kind.non_null?}
27
+ .keys
28
+
29
+ present_fields = ast_node.arguments.map(&:name)
30
+ missing_fields = required_fields - present_fields
31
+
32
+ missing_fields.each do |missing_field|
33
+ path = [*context.path, missing_field]
34
+ missing_field_type = parent_type.arguments[missing_field].type
35
+ add_error(RequiredInputObjectAttributesArePresentError.new(
36
+ "Argument '#{missing_field}' on InputObject '#{parent_type}' is required. Expected type #{missing_field_type}",
37
+ argument_name: missing_field,
38
+ argument_type: missing_field_type.to_s,
39
+ input_object_type: parent_type.to_s,
40
+ path: path,
41
+ nodes: ast_node,
42
+ ))
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end